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);
}

関連ページ