《Linux/Unix系统编程手册》读书笔记2
《Linux/Unix系统编程手册》读书笔记2
《Linux/Unix系统编程手册》读书笔记 目录
第5章:
主要介绍了文件I/O更深入的一些内容。
原子操作,将一个系统调用所要完成的作为一个的操作,一次性执行;这样可以避免竞争状态(两个或多个共享资源的进程或线程的运行结果是一个无法预期的顺序)。
以独占方式创建一个文件:对文件是否存在的检查和创建文件属于同一个原子操作。防止新建文件的时候因为检查文件是否存在和新建文件之间发生中断(而其他进程也在新建相同文件名的文件),导致两个进程都认为自己是文件的创建者。
向文件尾部追加数据:将文件的偏移量的移动与数据的写操作属于同一个原子操作。防止多个进程同时往同一个文件尾部添加数据导致数据混乱。
,对一个打开的文件描述符执行一系列的操作。
#include <fcntl.h>
fcntl( fd, cmd, ...);
fd为文件描述符,cmd是决定具体操作,第三个参数(可选)用来设置为不同的类型。
cmd参数(部分),具体查看man手册:
F_DUPFD | 复制文件描述符 |
F_GETFD | 获取文件描述符 |
F_SET_FD | 设置文件描述符 |
F_GETFL | 获取文件访问模式和状态标志 |
F_SETFL | 设置文件访问模式和状态标志 |
文件描述符与打开文件之间的关系:多个文件描述符可以指向同一个打开文件。他们的关系如下
文件描述符表、打开文件表和i-node表。打开文件表的条目成为打开文件句柄(open file handle)。
,复制一个打开的文件描述符oldfd,并返回新的描述符。
,复制oldfd指定的文件描述符,返回newfd参数指定的描述符。
,参数与dup2()相同,添加了flags,用于修改系统调用行为。
#include <unistd.h>
dup(
dup2( oldfd,
dup3( oldfd, newfd, int flags);
成功调用返回新的文件描述符,失败返回-1。
和,在指定参数所指定的位置进行文件I/O操作,但不改变文件的偏移量。
#include <unistd.h>
ssize_t pread( fd, *
ssize_t pwrite( fd, *buf, size_t count, off_t offset);
fd为文件描述符,buf为缓冲区, count为缓冲区字节数, offset为偏移量。
pread()成功调用返回读取的字节数,失败返回-1
pwrite()成功调用返回写入的字节数,失败返回-1
练习:
5-1,请使用标准文件I/O系统调用(open()和lseek())和off_t数据类型修改程序清单5-3中的程序。将宏_FILE_OFFSET_BITS的值设置为64进行编译,并测试该程序是否能够成功创建一个大文件。
_FILE_OFFSET_BITS 64 #include <sys/stat.h> #include <fcntl.h> #include main( argc, * (argc != || strcmp(argv[], ) == usageErr(, argv[ fd = open(argv[], O_RDWR | O_CREAT, S_IRUSR | (fd == - errExit( off = atoll(argv[ (lseek(fd, off, SEEK_SET) == - errExit( (write(fd, , ) == - errExit( } View Code测试结果:
lancelot@debian:~/Code/tlpi$ ./large_file largefile
lancelot@debian:~/Code/tlpi$ - -rw------- lancelot lancelot 4月 : largefile
5-2,编写一个程序,使用O_APPEND标志并以写方式打开一个已存在的文件,且将文件偏移量置于起始位置,再写入数据。数据会显示在文件中的哪个位置?为什么?
#include <sys/stat.h> #include <ctype.h> #include <fcntl.h> #include main( argc, * (argc != || strcmp(argv[], ) == usageErr(, argv[ fd = open(argv[], O_RDWR | O_APPEND, S_IRUSR | (fd == - errExit( off = lseek(fd, (off == - errExit( numWritten = write(fd, , (numWritten == - errExit( } View Code测试结果:
lancelot@debian:~/Code/tlpi$
lancelot@debian:~/Code/tlpi$ ./ lancelot@debian:~/Code/tlpi$