flock関数は、ファイルに対してロックの適用・解除を行います。ロックには、次の2種類があります。

共有ロック
他のプロセスからファイルを参照することはできますが、変更はできません。
排他ロック
他のプロセスからファイルの参照も変更もできません。

この関数は、C言語のライブラリ関数(標準関数)ではありませんので、コンパイラにより、使えない場合があります。

#include <sys/file.h>
int flock(int fd, int operation);

fdはopen関数又は、creat関数でファイルをオープンした時に取得した、ファイル・ディスクリプタを指定します。
operationはロックの種類を指定します。

戻り値として、処理が成功した場合は0が、エラーの場合は-1を返します。

第2引数のoperationには、次の値を指定できます。

意味
LOCK_SH 共有ロックを適用します。
LOCK_EX 排他ロックを適用します。
LOCK_UN ロックを解除します。

ロックを適用した複数のプロセスがファイルにアクセスすると、1つのプロセスのみがアクセスできて、その他のプロセスは停止(block)します。非停止(non-blocking)タイプの要求を行うには、上記の操作(operation)にLOCK_NBを論理和(OR)の形で指定します。また、1つのファイルに対して、共有ロックと排他ロックを同時に設定することはできません。

ロックの解除は第2引数のoperationにLOCK_UNを指定して実行するか、ファイルをクローズした場合に行われます。

プログラム 例

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/file.h>

int main(int argc, char **argv)
{
  char        pathname[] = './temp_lock.txt';
  int         fd;
  char        out_buff[100];
  int         outcnt;
  int         return_code = 0;

  /* 書き込み専用、追加モードでオープン */
  if ((fd = open(pathname, O_WRONLY | O_APPEND)) != -1) {
    /* 排他ロックをかける */
    if (flock(fd, LOCK_EX) == 0) {
      /* メッセージ出力 */
      for (outcnt = 1; outcnt <= 3; ++outcnt) {
        sprintf(out_buff, '%s : %d回目\n', *(argv + 1), outcnt);
        write(fd, out_buff, strlen(out_buff));

        sleep(2);
      }
      /* ロック解除 */
      flock(fd, LOCK_UN);
    }
    else {
      perror('');
      return_code = 2;
    }
    close(fd);
  }
  else {
    perror('');
    return_code = 1;
  }

  return return_code;
}

例の実行結果

flock.exe実行コマンドで、&記号を付けて並列実行を行っています。

$ cat temp_lock.txt
This is temp_lock.txt.
$
$ ./flock.exe Proc01 &
[1] 2796
$ ./flock.exe Proc02 &
[2] 2797
$ ./flock.exe Proc03 &
[3] 2798
[1]   Done                    ./flock.exe Proc01
$ ./flock.exe Proc04 &
[4] 2799
[2]   Done                    ./flock.exe Proc02
$
[3]-  Done                    ./flock.exe Proc03
[4]+  Done                    ./flock.exe Proc04
$ cat temp_lock.txt
This is temp_lock.txt.
Proc01 : 1回目
Proc01 : 2回目
Proc01 : 3回目
Proc02 : 1回目
Proc02 : 2回目
Proc02 : 3回目
Proc03 : 1回目
Proc03 : 2回目
Proc03 : 3回目
Proc04 : 1回目
Proc04 : 2回目
Proc04 : 3回目
$