The Linux Programming Interface
File I/O: Further Details
(01) 原子操作
Atomicity is essential to the successful completion of some operations. In particular, it allows us to avoid race conditions.
(02) 重要,man 手册查询错误码, man errno
ENOENT No such file or directory (POSIX.1)
(03)原子操作的错误实例,两个进程都声称单独创建t.txt文件
1 #include <stdio.h>
2 #include <fcntl.h>
3 #include <errno.h>
4
5 int main(int argc, char *argv[]) {
6 int fd;
7 fd = open(argv[1], O_WRONLY);
8 if (fd != -1) {
9 printf("[PID %ld File \"%s\" already exists\n",
10 (long) getpid(), argv[1]);
11 } else {
12 if (errno != ENOENT) { /* Failed for unexpected reason */
13 errExit("open");
14 } else {
15 printf("[PID %ld] File \"%s\" doesn't exist yet\n",
16 (long) getpid(), argv[1]);
17 if (argc > 2) {
18 sleep(30);
19 printf("[PID %ld] Done sleeping\n", (long) getpid());
20 }
21 /* WINDOW FOR FAILURE */
22 fd = open(argv[1], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
23 if (fd == -1)
24 errExit("open");
25
26 printf("[PID %ld] Create file \"%s\" exclusively\n",
27 (long) getpid(), argv[1]);
28 }
29 }
30 }
输出:
wang@wang:~/test/tlpi-dist/lib$ [PID 8567] File "t.txt" doesn't exist yet
wang@wang:~/test/tlpi-dist/lib$ ./bad_exclusive_open t.txt
[PID 8586] File "t.txt" doesn't exist yet
[PID 8586] Create file "t.txt" exclusively
wang@wang:~/test/tlpi-dist/lib$
wang@wang:~/test/tlpi-dist/lib$ [PID 8567] Done sleeping
[PID 8567] Create file "t.txt" exclusively
[1]+ Exit 43 ./bad_exclusive_open t.txt sleep
Using a single open() call that specifies the O_CREAT and O_EXCL flags prevents this possibility by guaranteeing that the check and creation steps are carried out as a single atomic operation.
(04) fcntl函数
One use of fcntl() is to retrieve or modify the access mode and open file status flags of an open file.
int flags, accessMode;
flags = fcntl(fd, F_GEETFL);
if (flags == -1)
errExit("fcntl");
if (flags & O_SYNC)
printf("writes are synchronized\n");
(05) 检查文件读写权限
Checking the access mode of the file is slightly more complex, since the O_RDONLY(0), O_WRONLY(1), and O_RDWR(2) constants don't correspond to single bits in the open file status flags.
Therefore, to make this check, we mask the flags value with the constant O_ACCMODE, and then test for equality with one of the constants:
accessMode = flags & O_ACCESS;
if (accessMode == O_WRONLY || accessMode == O_RDWR)
printf(