読者です 読者をやめる 読者になる 読者になる

複数ファイルから書き込む

複数ファイルから書き込む時には、排他ロックを掛ける or 一時ファイルに書き込んでrenameが常套手段。前者については 共有ロックと排他ロックとで調べたので、後者について。

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

#define BUFFSIZE 1024

int main(int argc, char** argv) 
{
   int fd;
   char buff[BUFFSIZE];
   int n;
   int i;

   fd = open("/tmp/kotaro", (O_RDONLY));
   while ( n = read(fd, buff, 1) > 0 ) {
       write(STDOUT_FILENO, buff, n);
   }
   close(fd);
}

で /tmp/kotaro を読んでいる最中に、

#include <stdio.h>
#include "error.h"

int main(int argc, char** argv)
{

    char oldname[1024] = "/tmp/kotaro.tmp";
    char newname[1024] = "/tmp/kotaro";

    rename(oldname, newname);
}

でファイルをrenameするとどうなるか?

man(2) rename

newpath が既に存在する場合、それは不可分操作で (atomically) 置き換えられる (ただし、いくつかの条件がある; 以下の「エラー」のセクションを参照)。 そのため、 newpath にアクセスしようとしている他のプロセスがファイルを見失うことはない (訳註: 常にアクセス可能である)。

と書かれており、確かに読み出し中プロセスでおかしなことにはならなかった。 file tableはv-node tableへのpointerを保持しておりopen時に準備されるので、別プロセスからrenameされても影響を受けない、という理解。

ということで、複数プロセスから同じファイルに書き出す可能性あるなら、一時ファイルに書き込んでrenameするというのがよさそう。