C言語システムコール-fcntl
fcntlシステムコール
概要
fcntlはファイルディスクリプタに対する各種操作を行います。
fcntlで実行できる操作は多数ありますので、詳細はmanコマンド等マニュアルを参照下さい。
使用頻度が高い操作としては以下のものがあります。
- ファイルディスクリプタの複製(F_DUPFD)
- open実行時に設定したファイル状態フラグの変更(F_SETFL)
- ファイルロック操作(F_GETLK, F_SETLK, F_SETLKW)
サンプルプログラム
コンパイルしたプログラムを実行し、別のシェルでもプログラムを実行するとロックが確認できます。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
/*!
* @brief 入力まで待ち合わせる
*/
static void
wait_input(void)
{
char buf[BUFSIZ] = {"¥0"};
read(0, buf, sizeof(buf));
return;
}
/*!
* @brief ディスクリプタをロックする。
* @param[in] fd ファイルディスクリプタ
* @return 0:success/-1:failure
*/
static int
lock_descriptor(int fd)
{
int rc = 0;
struct flock lock = {0};
lock.l_type = F_WRLCK; /* 書き込みロック */
lock.l_whence = SEEK_SET; /* オフセットを指定 */
lock.l_start = 0; /* 現在のオフセットからロックする */
lock.l_len = 0; /* ファイル終端までロックする */
lock.l_pid = getpid();
rc = fcntl(fd, F_SETLKW, &lock);
if(rc < 0){
printf("Error: fcntl() %s: lock\n", strerror(errno));
return(-1);
}
/* 待ち合わせ処理 */
fprintf(stdout, "Locked...\n");
fprintf(stdout, "Press <Enter> to release lock.\n");
wait_input();
/* ロック解除 */
lock.l_type = F_UNLCK;
rc = fcntl(fd, F_SETLK, &lock);
if(rc < 0){
printf("Error: fcntl() %s: unlock\n", strerror(errno));
return(-1);
}
fprintf(stdout, "Unlocked.\n");
return(0);
}
/*!
* @brief ファイルをロックする。
* @param[in] filepath ファイルパス名
* @return 0:success/-1:failure
*/
static int
file_lock(char *filepath)
{
int rc = 0;
int fd = 0;
fd = open(filepath, O_RDWR);
if(fd < 0){
printf("Error: open() %s: %s\n", strerror(errno), filepath);
return(-1);
}
rc = lock_descriptor(fd);
if(close(fd) < 0){
printf("Error: close() %s\n", strerror(errno));
return(-1);
}
return(rc);
}
int
main(int argc, char *argv[])
{
int rc = 0;
if(argc != 2){
fprintf(stderr, "Usage: %s <path>\n", argv[0]);
exit(EXIT_FAILURE);
}
rc = file_lock(argv[1]);
if(rc != 0) exit(EXIT_FAILURE);
exit(EXIT_SUCCESS);
}