所以我被要求解决这个问题:
本练习旨在说明为什么通过打开带有O_APPEND
标志的文件来保证原子性是必要的。编写一个最多需要三个命令行参数的程序:
$ atomic_append filename num-bytes [x]
此文件应打开指定的文件名(必要时创建它),并使用num-bytes
一次写入一个字节,将write()
字节附加到文件中。默认情况下,程序应该使用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
当然,文件大小有所不同我有点无法清楚地理解为什么?我搜索并找到了解释的地方:
尺寸明显不同:
-rw------- 1 posborne posborne 1272426 2012-01-15 21:31 test2.txt
-rw------- 1 posborne posborne 2000000 2012-01-15 21:29 test.txt
在没有O_APPEND的情况下运行test2.txt。 test2.txt很短 寻求的次数(或由于时间而产生的字节数) 文件的结尾没有与写入同时发生(相当 的频率)。
但它似乎没有任何意义。那么为什么尺寸不同呢?
答案 0 :(得分:1)
此代码在未使用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);
对于以write()
打开的文件O_APPEND
的标准行为,保证,无论在何处结束,都要写入文件的末尾是
这是O_APPEND
旗帜的全部内容 - lseek()
然后write()
不起作用。