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

fcntl を使ったファイルロック

fcntl を使ったファイルロックであれば、NFS上のファイルでもロックできる(らしい。)
以下はテストコード。

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>


int main(int args, char** argv ){
	int file_desc;
	struct flock region;
	file_desc = open( argv[1], O_RDWR | O_CREAT, 0666);
	
	struct stat buf;
	fstat(file_desc, &buf);
	
	region.l_type = F_WRLCK;
	region.l_whence = SEEK_SET;
	region.l_start = 0;
	region.l_len = buf.st_size; 
	
	int res;
	int retry = 50;
	while( retry-- > 0 ){
		res = fcntl(file_desc, F_SETLK, &region);
		if(-1 != res){
			break;
		}
		printf("pid %d is waiting\n", getpid());
		fflush(stdout);
		sleep(1);
	}
	
	//Critical section
	int count = 5;
	while( count-- > 0 ){
		printf("pid %d has file lock\n", getpid());
		fflush(stdout);
		sleep(2);
	}
	close(file_desc);
	return 0;
}

第一引数にロックしたいファイルのパスを指定する。2つ同時に起動すると、ファイルロックしている様子が確認できる。

# ./fcntl fcntl.BAK &
[1] 3167
pid 3167 has file lock
# ./fcntl fcntl.BAK &
pid 3168 is waiting
[2] 3168
pid 3168 is waiting
pid 3167 has file lock
pid 3168 is waiting
pid 3168 is waiting
pid 3167 has file lock
pid 3168 is waiting
pid 3168 is waiting
pid 3167 has file lock
pid 3168 is waiting
pid 3168 is waiting
pid 3167 has file lock
pid 3168 is waiting
pid 3168 is waiting
pid 3168 has file lock
pid 3168 has file lock
pid 3168 has file lock
pid 3168 has file lock
pid 3168 has file lock

[1]-  Done                    ./fcntl fcntl.BAK
[2]+  Done                    ./fcntl fcntl.BAK