複数プロセスからの書き込み - file tableとcurrent offset
同時に複数プロセスから書き込むとファイルが壊れるというが、壊れるというのはどういうことか。
出典: Advanced Programing in the Unix Environment - Figure3.7
異なるプロセスから同じファイルをopenすると、異なるfile tableエントリー(current file offsetを保持する)が生成される、というのがUNIXにおける仕様とのこと。
#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include "error.h" #define BUFFSIZE 4096 int main(int argc, char* argv[]) { int fd; char buff[BUFFSIZE]; int i; fd = open("/tmp/kotaro", (O_WRONLY | O_CREAT)); for (i = 0; i < 1000000; i++ ) { sprintf(buff, "%d\r\n", getpid()); write(fd, buff, strlen(buff)); } close(fd); }
自身のpidを100万回書き込むという単純なプログラムだが、これを同時に実行してみた結果は以下の通り。
$ cat /tmp/kotaro | sort | uniq -c 263710 79026 736290 79027
全体行数は100万だが、2つのpid(79026と79027)が書き込まれていることがわかる。
ただし、O_APPENDフラグをつけると事情が異なる。これが付いているとwrite(2)実行時には、file末尾までseekし、書き込むまでがatomicになるので、同時に追記書き込みしても漏れることはない。
まとめ
同じファイルを別プロセスからopenすると、offsetを管理するfile tableエントリーは別々につくられるので気をつける。