c – write()在两种情况下表现不同

所以我被要求解决这个练习:

本练习旨在说明为什么通过打开带有O_APPEND标志的文件来保证原子性是必要的.编写一个最多需要三个命令行参数的程序:

$atomic_append filename num-bytes [x] 

此文件应打开指定的文件名(必要时创建它),并使用write()一次写入一个字节,将num-bytes字节追加到文件中.默认情况下,程序应使用O_APPEND标志打开文件,但如果提供了第三个命令行参数(x),则应省略O_APPEND标志,而程序应执行lseek(fd,0,SEEK_END) )在每次write()之前调用.同时运行此程序的两个实例而不使用x参数将100万个字节写入同一文件:

$atomic_append f1 1000000 & atomic_append f1 1000000 

重复相同的步骤,写入不同的文件,但这次指定x参数:

$atomic_append f2 1000000 x & atomic_append f2 1000000 x 

使用ls -l列出文件f1和f2的大小并解释差异.

所以这就是我写的:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[]) {
        int fd, flags, num_bytes;
        if (argc < 3 || strcmp(argv[1], "--help") == 0) {
                printf("Usage: %s filename num-bytes [x]\n", argv[0]);
                return 1;
        }
        num_bytes = atoi(argv[2]);
        if (argc == 4 && strcmp(argv[3], "x") == 0) {
                fd = open(argv[1], O_CREAT | O_WRONLY, 0666);
                if (fd == -1)
                        perror("open");
                while (num_bytes-- > 0) {
                        lseek(fd, 0, SEEK_END);
                        write(fd, "a", 1);
                }
                if (close(fd) == -1)
                        perror("close");
        }
        else {
                fd = open(argv[1], O_CREAT | O_APPEND | O_WRONLY, 0666);
                if (fd == -1)
                        perror("open");
                while(num_bytes-- > 0)
                        write(fd, "a", 1);
                if (close(fd) == -1)
                        perror("close");
        }
        return 0;
}

现在我根据需要运行它:

abhinav@cr33p:~/System/5$./a.out f1 1000000 & ./a.out f1 1000000
[1] 4335
[1]+  Done                    ./a.out f1 1000000
abhinav@cr33p:~/System/5$./a.out f2 1000000 x & ./a.out f2 1000000 x
[1] 4352
[1]+  Done                    ./a.out f2 1000000 x
abhinav@cr33p:~/System/5$ls f1 f2
f1  f2
abhinav@cr33p:~/System/5$ls -l f*
-rw-rw-r-- 1 abhinav abhinav 2000000 Dec 10 16:23 f1
-rw-rw-r-- 1 abhinav abhinav 1000593 Dec 10 16:24 f2

当然,文件大小有所不同我有点无法清楚地理解为什么?我搜索并找到了解释的地方:

The sizes were definitely different:

-rw------- 1 posborne posborne 1272426 2012-01-15 21:31 test2.txt
-rw------- 1 posborne posborne 2000000 2012-01-15 21:29 test.txt

Where test2.txt was run without O_APPEND. test2.txt is short by the
number of times (or bytes as a result of times) that seeking to the
end of the file did not happen at the same time as the write (quite
frequently).

但它似乎没有任何意义.那么为什么尺寸不同呢?

最佳答案 此代码在未使用O_APPEND打开的文件上运行:

            while (num_bytes-- > 0) {
                    lseek(fd, 0, SEEK_END);
                    write(fd, "a", 1);

写入文件末尾的位置,就像调用lseek()时一样.文件的结尾可以在lseek()和write()调用之间的时间内发生变化.

此代码位于使用O_APPEND打开的文件上:

            while(num_bytes-- > 0)
                    write(fd, "a", 1);

通过使用O_APPEND打开的文件write()的标准行为来保证写入文件的末尾,无论结果如何.

这就是O_APPEND标志的全部内容 – lseek()然后write()不起作用.

点赞