EN JA
FCNTL(2)
FCNTL(2) FreeBSD System Calls Manual FCNTL(2)

名称

fcntlファイル制御

ライブラリ

Standard C Library (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 フラグ FD_CLOEXEC は、クリアされるので、ファイル記述子は、 execve(2) システムコールに渡ってオープンされたままであることです。
F_DUPFD_CLOEXEC
F_DUPFD に似ていますが、新しいファイル記述子に関連した FD_CLOEXEC フラグは、設定されるので、 execve(2) システムコールが実行するとき、ファイル記述子は、クローズされます。
F_DUP2FD
それは、次と機能的に同等です。

dup2(fd, arg)
F_DUP2FD_CLOEXEC
F_DUP2FD に似ていますが、新しいファイル記述子に関連した FD_CLOEXEC フラグが設定されます。

F_DUP2FDF_DUP2FD_CLOEXEC 定数は、移植性がないので、移植性を必要とするなら、それらを使用するべきではありません。 F_DUP2FD の代わりに dup2() を使用します。

F_GETFD
FD_CLOEXEC としてファイル記述子 fd に関連する close-on-exec フラグを取得します。 FD_CLOEXEC で論理積 (AND) された返された値が 0 であるなら、ファイルは、 exec() に渡ってオープンされたままとなり、そうでなければ、ファイルは、 exec() の実行時にクローズされます ( arg は、無視されます)。
F_SETFD
fd に関連する close-on-exec フラグを arg に設定します、ここで arg は、0 または前述のように FD_CLOEXEC です。
F_GETFL
下記のように記述子の状態フラグを取得します ( arg は、無視されます)。
F_SETFL
記述子の状態フラグを arg に設定します。
F_GETOWN
現在 SIGIOSIGURG シグナルを受信しているプロセス ID またはプロセスグループを取得します。プロセスグループは、負の値として返されます ( arg は、無視されます)。
F_SETOWN
SIGIOSIGURG シグナルを受信するようにプロセスまたはプロセスグループに設定します。プロセスグループは、負の値として arg を供給することによって指定され、そうでなければ、 arg は、プロセス ID として解釈されます。
F_READAHEAD
最も近いブロックサイズに丸められる、3 番目の引数 arg へのシーケンシャルアクセスのための先読みの量を設定するか、またはクリアします。 0 の値の arg は、先読みをオフにし、負の値は、システムデフォルトを復旧します。
F_RDAHEAD
3 番目の引数 arg が 0 でないなとき、128KB の先読みの量を設定する Darwin 対応物と同等です。 0 の値の arg は、先読みをオフにします。

F_GETFLF_SETFL のためのフラグは、次の通りです:

O_NONBLOCK
非ブロッキング入出力。 read(2) システムコールで読み込むべきデータが無い場合、または write(2) 操作がブロックするであろう場合に、読み込み呼び出しまたは書き込み呼び出しは、エラー EAGAIN で -1 を返します。
O_APPEND
各書み込みがファイルの末尾に追加されるようにします。 open(2)O_APPEND フラグに対応します。
O_DIRECT
読み書きにおけるキャッシュ効果を最小化または無くします。システムは、読み書きするデータのキャッシングを避けようとします。データのキャッシングが避けられない場合、データのキャッシュに対する影響を最小化します。注意せずに使用すると、本フラグは、劇的に性能を劣化させます。
O_ASYNC
たとえば、読み込むべきデータが用意できたときなど、入出力が可能になったときに SIGIO シグナルがプロセスグループに送信されるようにします。

いくつかのコマンドがアドバイザリ (advisory) ファイルロックを行うために利用可能です。それらは、すべて次の構造体で操作を行います:

struct flock { 
 off_t l_start; /* 開始オフセット */ 
 off_t l_len;  /* len = 0 は, ファイルの終りまでを意味する */ 
 pid_t l_pid;  /* ロック所有者 */ 
 short l_type;  /* ロックタイプ: 読み込み/書き込み等 */ 
 short l_whence; /* l_start のタイプ */ 
 int l_sysid; /* リモートシステム ID またはローカルの 
       ための 0 */ 
};

アドバイザリ (advisory) レコードロックに利用可能なコマンドは、次の通りです:

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_pidl_sysid フィールドは、そのプロセスを所有しているシステムのブロッキングロックとシステム ID を保持しているプロセスの ID をプロセスに返すために F_GETLK でのみ使用されます。ローカルシステムによって作成されたロックは、0 のシステム ID があります。 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_DUP2FD
arg と等しいファイル記述子。
F_GETFD
フラグの値 (下位ビットだけが定義されています)。
F_GETFL
フラグの値。
F_GETOWN
ファイル記述子所有者の値。
その他
-1 以外の値。

そうでなければ、-1 の値が返され、エラーを示す値が errno に設定されます。

エラー

fcntl() システムコールは、次の場合に失敗します:
[ EAGAIN]
引数 cmd が、 F_SETLK であり、ロックのタイプ ( l_type) が、共有ロック ( F_RDLCK、) または排他的ロック ( F_WRLCK) で、ロックされるファイルのセグメントが、既に別のプロセスによって排他的にロックされています。または、タイプが排他的なロックで、ロックされるファイルのセグメントの一部分が既に別のプロセスによって共有ロックまたは排他的ロックされています。
[ EBADF]
fd 引数が有効なオープンされたファイル記述子ではありません。

引数 cmd が、 F_DUP2FD であり、 arg が有効なファイル記述子ではありません。

引数 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 が (ソケットでオープンされた記述子とは対象的に) 端末デバイスでオープンされた記述子を参照しているなら、 F_SETOWNcmd が、 tcsetpgrp(3) のような同じ理由のために失敗するかもしれず、 F_GETOWNcmd が、 tcgetpgrp(3) で述べたような理由で失敗するかもしれません。

規格

F_DUP2FD 定数は、移植性がありません。それは、AIX と Solaris との互換性を提供します。

歴史

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

F_DUP2FD 定数は、 FreeBSD 7.1 ではじめて登場しました。

February 8, 2013 FreeBSD