forkしたプロセスから共有するファイルディスクリプタへの書き込みについて
ファイルを開いてからforkすると、そのファイルディスクリプタはシステムワイドなオープンファイルテーブルの同じ項目を指すので、書き込み位置(file offset)も共有され、同時に追加書き込みをしても競合は発生しないと思ったのですが、実験してみたら
log.txt
PARENT 24043 894 helloCPARENT 24043 895 hellCHPARENT 24043 896 helCHIPARENT 24043 897 heCHILPARENT 24043 898 hello
のようにおかしな部分が出ていました。環境はLinux 3.10.0です。
基礎的なことかと思いますが、どうしてこうなるのか教えていただけないでしょうか。
実験に使ったコード:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int main()
{
pid_t pid;
int fd;
int i;
char buf[256];
fd = open("log.txt", O_CREAT | O_WRONLY | O_TRUNC, 0644);
pid = fork();
if (pid > 0) {
for (i = 0; i < 1000; i++) {
sprintf(buf, "PARENT %d %d hello\n", getpid(), i);
write(fd, buf, strlen(buf));
}
}
else if (pid == 0) {
for (i = 0; i < 1000; i++) {
sprintf(buf, "CHILD %d %d hello\n", getpid(), i);
write(fd, buf, strlen(buf));
}
}
else {
perror("fork");
}
return 0;
}
[追記]
逆に下記を ./a.out& ./a.out& で同時に動かしたとき、きれいにログが出ていました。
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
int i;
char buf[256];
fd = open("log.txt", O_APPEND | O_WRONLY, 0644);
for (i = 0; i < 1000; i++) {
sprintf(buf, "This is %d %d hello\n", getpid(), i);
write(fd, buf, strlen(buf));
}
return 0;
}