スポンサーリンク

FCNTL(2) FreeBSD システムコールマニュアル FCNTL(2)

名称

fcntl − ファイル制御

ライブラリ

標準 C ライブラリ (libc, −lc)

書式

#include <fcntl.h>

int

fcntl(int fd, int cmd, ...);

解説

fcntl() システムコールは、記述子の制御機能を提供します。引数 fd は、後述 する cmd によって操作される記述子です。 cmd の値によっては、 fcntl() は 3 つめの引数 int arg を取ることができます。

       F_DUPFD

次のような新しい記述子を返します:

arg 以上で最小番号をもつ利用可能な記述子
オリジナルの記述子と同じオブジェクトを参照
オブジェクトがファイルだった場合、同じファイルオフセッ トを共有
同じアクセスモード (読取り、書込み、または読取りと書込 み)
同じファイル状態フラグ (すなわち、両方のファイル記述子 が同じファイル状態フラグを共有)
close-on-exec フラグは、 execve(2) システムコールの後 でも記述子をオープンしたままでいるように設定

F_GETFD
ファイル記述子 fd に結び付けられた close-on-exec フラグを、 FD_CLOEXEC として取得します。返された値と FD_CLOEXEC の論理積 が 0 の場合、ファイルは exec() を実行してもオープンされたまま になります。そうでない場合、ファイルは exec() の実行でクローズ されます (arg は無視されます)。

F_SETFD
fd
に結び付けられた close-on-exec フラグを arg に設定します。 arg は 0 または前述の FD_CLOEXEC です。

F_GETFL
後述するように記述子の状態フラグを取得します (arg は無視されま す)。

F_SETFL
記述子状態フラグを arg で指定される値に設定します。

F_GETOWN
現時点で SIGIO シグナルと SIGURG シグナルを受信しているプロセ ス ID またはプロセスグループを取得します。プロセスグループは負 の値として返されます (arg は無視されます)。

F_SETOWN
プロセスまたはプロセスグループが SIGIO シグナルおよび SIGURG シグナルを受信するように設定します。プロセスグループは arg を 負数にして与えることによって指定されます。そうでない場合、 arg はプロセス ID として解釈されます。

F_GETFL および F_SETFL 用のフラグは次のとおりです:

O_NONBLOCK
非ブロッキング入出力。 read(2) システムコールで読み取るべき データが無い場合、または write(2) 操作がブロックするであろう 場合に、読取り呼び出しまたは書込み呼び出しはエラー EAGAIN で -1 を返します。

O_APPEND
各書込みがファイルの末尾に追加されるようにします。 open(2) の O_APPEND フラグに対応します。

O_DIRECT
読み書きにおけるキャッシュ効果を最小化または無くします。シス テムは、読み書きするデータのキャッシングを避けようとします。 データのキャッシングが避けられない場合、データのキャッシュに 対する影響を最小化します。注意せずに使用すると、本フラグは劇 的に性能を劣化させます。

O_ASYNC
たとえば、読み取るべきデータが用意できたときなど、入出力が可 能になったときに SIGIO シグナルがプロセスグループに送信され るようにします。

問合せ型ファイルロックを行うためにいくつかのコマンドが利用できます。これ らのコマンドはすべて次の構造体で操作します:

struct flock {

off_t

l_start;

/* 開始位置のオフセット */

off_t

l_len;

/* len = 0 はファイル末尾までという意味 */

pid_t

l_pid;

/* ロック所有者 */

short

l_type;

/* ロックタイプ: 読取り / 書込みなど */

short

l_whence;

/* l_start のタイプ */

};
問合せ型レコードロックに利用できるコマンドは次のとおりです:

       F_GETLK

3 番めの引数 argstruct flock (前記を参照) へのポインタと解 釈して、それによって指定されるロック記述をブロックする最初の ロックを取得します。取り出された情報は、 fcntl() に渡された flock 構造体内の情報に上書きされます。このロックが作成されるの を妨げるロックが見つからない場合は、構造体はこのシステムコール 呼び出しによっても変更されません。ただし、ロックタイプが F_UNLCK に設定されている場合は除きます。

F_SETLK
3 番めの引数 argstruct flock (前記を参照) へのポインタと解 釈して、それによって指定されるロック記述に従ってファイルセグメ ントロックを設定またはクリアします。 F_SETLK は、共有 (または 読取り) ロック (F_RDLCK) または排他的 (または書込み) ロック (F_WRLCK) を確立、ならびにいずれかのタイプのロックを解除 (F_UNLCK) するのに使用されます。共有ロックまたは排他的ロックが 設定できない場合、 fcntl() は EAGAIN でただちに戻ります。

F_SETLKW
このコマンドは F_SETLK と同じですが、共有ロックまたは排他的 ロックが他のロックによってブロックされる場合に、要求が満たされ るまでプロセスが待機する点が異なります。 fcntl() がある領域を 確保するために待機している間に捕捉されるべきシグナルを受信し て、シグナルハンドラが SA_RESTART (sigaction(2) を参照) を指定 していない場合、 fcntl() は中断されます。

共有ロックがファイルのあるセグメントに設定されている場合、他のプロセスは そのセグメントまたはその一部に共有ロックを設定できます。共有ロックは、保 護しているどの領域にも、他のプロセスが排他的ロックを設定するのを防止しま す。ファイル記述子が読取りアクセスで開かれていない場合、共有ロックの要求 は処理を失敗します。

排他的ロックは、保護している領域に他のプロセスが共有ロックまたは排他的 ロックを設定するのを防止します。ファイルが書込みアクセスで開かれていない 場合、排他的ロックの要求は失敗します。

l_whence の値は SEEK_SET, SEEK_CUR または SEEK_END で、これらは相対オフ セット l_start バイトが、それぞれファイルの先頭、現在位置、またはファイル の末尾から測定されることを指示します。 l_len の値はロックされる連続領域の バイト数です。 l_len が負の場合、 l_start は領域の終端を表しています。 l_pid フィールドは、ブロックするロックを保持しているプロセスのプロセス ID を返すために F_GETLK でのみ使用されます。 F_GETLK 要求が正常に完了すると l_whence の値は SEEK_SET になります。

ロックは現在のファイル末尾以降で開始したり、ファイル末尾を越えて延長する ことはできますが、ファイルの先頭より前で開始したり、ファイルの先頭を越え て延長することはできません。 l_len が 0 に設定されている場合、ロックはそ のファイルのファイルオフセットの可能な最大の値まで延長されます。 l_whencel_start がファイルの先頭を指しており、しかも l_len が 0 の場合はファイ ル全体がロックされます。アプリケーションがファイル全体をロックしようとし ているだけなら、 flock(2) システムコールの方がはるかに効率的です。

ファイル内の各バイトについて最大で 1 つのタイプのロックが設定されます。呼 び出しプロセスが F_SETLK 要求、または F_SETLKW 要求で指定した領域内に既存 のロックを保持しているとき、要求から正常に戻る前に、指定の領域内の各バイ トについて以前のロックタイプが新しいロックタイプで置き換えられます。共有 ロックと 排他的ロックのところで前述したように、別のプロセスが指定の領域内 にロックを保持しており、しかもそれらのロックのタイプが要求で指定されたタ イプと競合するとき、 F_SETLK 要求は失敗し、 F_SETLKW 要求はブロックしま す。

このインタフェースは、System V と IEEE Std 1003.1-1988 (‘‘POSIX.1’’) が要 求する不毛なセマンティクスに完全に従っています。つまり、あるプロセスが保 持している、あるファイルと結び付けられたすべてのロックは、そのファイルの 記述子の いずれかがそのプロセスによってクローズされたときに解除されます。 これは、サブルーチンライブラリがアクセスする可能性のあるファイル全てをア プリケーションが認識している必要があることを意味します。たとえば、パス ワードファイルを更新するアプリケーションが、更新を行うためにパスワード ファイルデータベースをロックし、レコードを取り出すために getpwnam(3) を呼 び出したとしましょう。 getpwnam(3) はパスワードデータベースをオープンし、 読み取り、そしてクローズするので、ロックは失われます。データベースをク ローズすると、ライブラリルーチンがデータベースへのロックを要求したことが ない場合でさえ、プロセスがデータベースに結び付けたすべてのロックが解放さ れてしまうのです。このインタフェースの別のさほど重要でないセマンティクス 上の問題は、ロックが fork(2) システムコールを使用して作成された子プロセス によって継承されないことです。 flock(2) インタフェースは、はるかに合理的 な last close セマンティクスを採用し、ロックが子プロセスによって継承され るようになっています。ライブラリを使用するときにロックの整合性を確実にす る、またはロックを子プロセスに渡したいアプリケーションについては flock(2) システムコールをお勧めします。

fcntl(), flock(2) および lockf(3) のロックは互換性があります。異なった ロックのインタフェースを使用するプロセスは、同じファイルを安全に使用する ことができます。しかしながら、同じプロセスの内部ではこれらのインタフェー スのうちの 1 つのみが使用されるべきです。 fcntl() を介してあるプロセスに よってあるファイルがロックされている場合、 flock(2) または lockf(3) を使 用している他のプロセスの視点からは、そのファイルの中のあらゆるレコードは ロックされているかのように見えます。また、その逆も同様です。ブロックする ロックを保持しているプロセスがファイル記述子を以前に flock(2) でロックし ていた場合、 fcntl(F_GETLK) は l_pid に −1 を入れて戻ります。

プロセスの、あるファイルに結び付けられたすべてのロックはそのプロセスが終 了するときに解除されます。

execve(2) の呼び出し前に取得されたすべてのロックは、新規プログラムがそれ らを解放するまで有効なままです。新規プログラムがロックについて知らないな らば、プログラム終了まで解放されません。

あるロックした領域を制御しているプロセスが、別のプロセスがロックした領域 をロックしようとして休眠状態にされる場合に、デッドロックが発生する可能性 があります。この実装では、ロックされた領域がアンロックされるまでの休眠が デッドロックを引き起こす可能性を検出すると、 EDEADLK エラーで失敗します。

戻り値

処理が正常に完了した場合、返される値は cmd に応じて次のようになります:

             F_DUPFD

新しいファイル記述子

F_GETFD
フラグの値 (下位ビットだけが定義されます)

F_GETFL
フラグの値

F_GETOWN
ファイル記述子所有者の値

その他
−1 以外の値

そうでない場合は -1 が返され、エラーを示すために errno が設定されます。

エラー

fcntl() システムコールは、次の場合に失敗します:

       [EAGAIN]

引数 cmd は F_SETLK であり、ロックのタイプ (l_type) は 共有ロック (F_RDLCK) 、または排他的ロック (F_WRLCK) で、ロックされるはずのファイルのセグメントは既に別のプ ロセスによって排他的にロックされています。または、タイ プが排他的なロックで、ロックされるファイルのセグメント の一部が既に別のプロセスによって共有ロックまたは排他的 ロックされています。

[EBADF]
fd
引数が有効なオープンファイル記述子ではありません。

引数 cmd が F_SETLK または F_SETLKW で、かつロックタイ プ (l_type) が共有ロック (F_RDLCK) のとき、 fd は読取 り用に開かれた有効なファイル記述子ではありません。

引数 cmd が F_SETLK または F_SETLKW で、かつロックタイ プ (l_type) が排他的ロック (F_WRLCK) のとき、 fd は書 込み用に開かれた有効なファイル記述子ではありません。

[EDEADLK]
引数 cmd が F_SETLKW であり、デッドロック条件が検出さ れました。

[EINTR]
引数 cmd が F_SETLKW であり、このシステムコールがシグ ナルによって割り込まれました。

[EINVAL]
cmd
が F_DUPFD で、 arg が負であるかまたは許容される最 大値より大きくなっています (getdtablesize(2) を参照)。

引数 cmd が F_GETLK, F_SETLK または F_SETLKW で、 arg が指すデータが有効でありません。

[EMFILE]
引数 cmd が F_DUPFD であり、プロセスについて許容される 最大数までファイル記述子が既に使用されています。 arg で指定された以上のファイル記述子は利用できません。

[ENOLCK]
引数 cmd が F_SETLK または F_SETLKW であり、ロック要求 またはアンロック要求を満たすことによって、システムが課 した限界を越える数のロックされた領域がシステム内にでき てしまいます。

[EOPNOTSUPP]
引数 cmd に F_GETLK, F_SETLK または F_SETLKW が指定さ れましたが、 fd はロックをサポートしていないファイルを 参照しています。

[EOVERFLOW]
引数 cmd に F_GETLK, F_SETLK または F_SETLKW が指定さ れましたが、 off_t の計算がオーバフローしました。

[EPERM]
cmd
引数は、 F_SETOWN であり、引数として指定されたプロ セス ID またはプロセスグループは、呼び出し側と異なる セッション内にあります。

[ESRCH]
cmd
引数は F_SETOWN であり、引数として指定されたプロセ ス ID が使用されていません。

さらに、 fd が (ソケット上で開いている記述子とは反対に) 端末デバイス上で 開いている記述子を参照する場合、 cmd で F_SETOWN を指定すると tcsetpgrp(3) と同じ理由で処理を失敗する可能性があり、 tcgetpgrp(3) で述べ たような理由で cmd で F_GETOWN を指定した場合に処理に失敗する可能性があり ます。

関連項目

close(2), execve(2), flock(2), getdtablesize(2), open(2), sigvec(2), lockf(3), tcgetpgrp(3), tcsetpgrp(3)

歴史

fcntl() システムコールは 4.2BSD で登場しました。

FreeBSD 10.0 January 12, 1994 FreeBSD 10.0

スポンサーリンク