Unix-system-calls-fcntl

提供:Dev Guides
移動先:案内検索

[top]#

[[File:]]

[[File:]]

|Web |This Site

  • 初心者向けのUnix *
  • 高度なUnix *

選択した読書

Copyright©2014 by finddevguides

  Home     References     Discussion Forums     About TP  

fcntl()-Unix、Linuxシステムコール

[[File:]] image :http://www.finddevguides.com/images/next.gif [next] image:http://www.finddevguides.com/add- this.gif [AddThisソーシャルブックマークボタン]

広告

NAME

fcntl-ファイル記述子の操作

概要

#include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd); int fcntl(int fd, int cmd, long arg); int fcntl(int fd, int cmd, struct flock* lock);

説明

*fcntl* ()は、開いているファイル記述子_fd_に対して以下に説明する操作のいずれかを実行します。 操作は_cmd_によって決定されます。

ファイル記述子の複製

Tag Description
*F_DUPFD *a

Find the lowest numbered available file descriptor greater than or equal to arg and make it be a copy of fd. This is different from* dup2*(2) which uses exactly the descriptor specified.

成功すると、新しい記述子が返されます。

詳細については、 dup (2)を参照してください。

ファイル記述子フラグ

次のコマンドは、ファイル記述子に関連付けられたフラグを操作します。 現在、このようなフラグが1つだけ定義されています: FD_CLOEXEC 、close-on-execフラグです。 FD_CLOEXEC ビットが0の場合、ファイル記述子は execve (2)を介して開いたままになり、そうでない場合は閉じられます。

Tag Description
F_GETFD Read the file descriptor flags.
F_SETFD Set the file descriptor flags to the value specified by arg.

ファイルステータスフラグ

各オープンファイルの説明には、 open (2)で初期化され、 fcntl (2)で変更された可能性のある特定の関連ステータスフラグがあります。 重複したファイル記述子( dup ()、 fcntl (F_DUPFD)、 fork ()などで作成)は、同じオープンファイル記述を参照するため、同じファイルステータスフラグを共有します。

ファイルステータスフラグとそのセマンティクスについては、 open (2)で説明されています。

Tag Description
F_GETFL Read the file status flags.
F_SETFL Set the file status flags to the value specified by arg. File access mode (O_RDONLY, O_WRONLY, O_RDWR) and file creation flags (i.e., O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) in arg are ignored. On Linux this command can only change the O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK flags.

Advisoryロック

*F_GETLK* 、 *F_SETLK* 、および *F_SETLKW* は、レコードロック(ファイルセグメントロックまたはファイル領域ロックとも呼ばれます)の存在を取得、解放、およびテストするために使用されます。 3番目の引数_lock_は、少なくとも次のフィールドを(不特定の順序で)持つ構造体へのポインタです。
struct flock { ... short l_type; /*Type of lock: F_RDLCK, F_WRLCK, F_UNLCK*/ short l_whence; /*How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END*/ off_t l_start; /*Starting offset for lock*/ off_t l_len; /*Number of bytes to lock*/ pid_t l_pid; /*PID of process blocking our lock (F_GETLK only)*/ ... };

この構造体の_l_whence l_start_、および_l_len_フィールドは、ロックするバイトの範囲を指定します。 _l_start_はロックの開始オフセットであり、次のいずれかに関連して解釈されます。ファイルの開始(_l_whence_が SEEK_SET の場合)。現在のファイルオフセット(_l_whence_が SEEK_CUR の場合);またはファイルの終わり(_l_whence_が SEEK_END の場合)。 最後の2つの場合、_l_start_は、ファイルの開始前にオフセットが存在しない限り、負の数にすることができます。 _l_len_は、ロックするバイト数を指定する負でない整数です(ただし、以下の注意事項を参照してください)。 ファイルの終わりを過ぎたバイトはロックされますが、ファイルの始まりの前のバイトはロックされません。 _l_len_に0を指定することには特別な意味があります。ファイルが大きくなっても、_l_whence_および_l_start_で指定された位置からファイルの終わりまでのすべてのバイトをロックします。

_l_type_フィールドを使用して、ファイルに読み取り( F_RDLCK )または書き込み( F_WRLCK )ロックを設定できます。 任意の数のプロセスがファイル領域で読み取りロック(共有ロック)を保持できますが、書き込みロック(排他ロック)を保持できるプロセスは1つだけです。 排他ロックは、共有と排他の両方の他のすべてのロックを除外します。 1つのプロセスは、ファイル領域に対して1つのタイプのロックのみを保持できます。新しいロックがすでにロックされている領域に適用される場合、既存のロックは新しいロックタイプに変換されます。 (新しいロックで指定されたバイト範囲が既存のロックの範囲と正確に一致しない場合、そのような変換には、既存のロックとの分割、縮小、または合体が含まれる場合があります。)

Tag Description
*F_SETLK * Acquire a lock (when l_type is* F_RDLCK or F_WRLCK*) or release a lock (when l_type is F_UNLCK) on the bytes specified by the l_whence, l_start, and l_len fields of lock. If a conflicting lock is held by another process, this call returns -1 and sets errno to EACCES *or EAGAIN*.
*F_SETLKW * As for* F_SETLK*, but if a conflicting lock is held on the file, then wait for that lock to be released. If a signal is caught while waiting, then the call is interrupted and (after the signal handler has returned) returns immediately (with return value -1 and errno set to EINTR).
*F_GETLK * On input to this call, lock describes a lock we would like to place on the file. If the lock could be placed,* fcntl*() does not actually place it, but returns F_UNLCK *in the l_type field of lock and leaves the other fields of the structure unchanged. If one or more incompatible locks would prevent this lock being placed, then fcntl*() returns details about one of these locks in the l_type, l_whence, l_start, and l_len fields of lock and sets l_pid to be the PID of the process holding that lock.

読み取りロックを設定するには、_fd_が読み取り用に開いている必要があります。 書き込みロックを設定するには、_fd_が書き込み用に開いている必要があります。 両方のタイプのロックを設定するには、ファイルを読み書き可能にして開きます。

明示的な F_UNLCK によって削除されるだけでなく、プロセスが終了するか、ロックが保持されているファイルを参照する_any_ファイル記述子を閉じると、レコードロックが自動的に解除されます。 これは悪いことです。つまり、何らかの理由でライブラリ関数がファイルのオープン、読み取り、クローズを決定したときに、プロセスが_/etc/passwd_や_/etc/mtab_などのファイルのロックを失う可能性があることを意味します。

レコードロックは、 fork (2)で作成された子には継承されませんが、 execve (2)で保持されます。

*stdio* (3)ライブラリによって実行されるバッファリングのため、そのパッケージ内のルーチンでのレコードロックの使用は避ける必要があります。代わりに *read* (2)および *write* (2)を使用してください。

強制ロック

(非POSIX。)上記のレコードロックは、アドバイザリまたは必須のいずれかであり、デフォルトでアドバイザリです。

アドバイザリロックは強制されず、連携するプロセス間でのみ役立ちます。

必須ロックはすべてのプロセスに適用されます。 プロセスが、互換性のない必須ロックを持つファイル領域に対して互換性のないアクセス( read (2)または write (2)など)を実行しようとすると、結果は O_NONBLOCK フラグが有効かどうかによって異なります開いているファイルの説明。 O_NONBLOCK フラグが有効でない場合、ロックが解除されるか、アクセスと互換性のあるモードに変換されるまで、システムコールはブロックされます。 O_NONBLOCK フラグが有効な場合、システムコールはエラー EAGAIN または* EWOULDBLOCK。*で失敗します。

強制ロックを使用するには、ロックするファイルを含むファイルシステムとファイル自体の両方で強制ロックを有効にする必要があります。 mount (8)の「-o mand」オプション、または mount (2)の MS_MANDLOCK フラグを使用して、ファイルシステムで強制ロックを有効にします。 強制ロックは、ファイルのグループ実行許可を無効にし、set-group-ID許可ビットを有効にすることで有効になります( chmod (1)および chmod (2)を参照)。

信号の管理

*F_GETOWN* 、 *F_SETOWN* 、 *F_GETSIG* 、および *F_SETSIG* は、I/O可用性シグナルを管理するために使用されます。
Tag Description
F_GETOWN Get the process ID or process group currently receiving SIGIO and SIGURG signals for events on file descriptor fd. Process IDs are returned as positive values; process group IDs are returned as negative values (but see BUGS below).
*F_SETOWN *a

Set the process ID or process group ID that will receive SIGIO and SIGURG signals for events on file descriptor fd. A process ID is specified as a positive value; a process group ID is specified as a negative value. Most commonly, the calling process specifies itself as the owner (that is, arg is specified as* getpid*()).

open (2)呼び出しでこのフラグを指定するか、 fcntl ()の F_SETFL コマンドを使用して)ファイル記述子に O_ASYNC ステータスフラグを設定すると、SIGIOシグナルが送信されます。そのファイル記述子で入力または出力が可能になるたび。 F_SETSIG を使用して、SIGIO以外のシグナルの配信を取得できます。 この許可チェックが失敗すると、シグナルは静かに破棄されます。

F_SETOWN で指定された所有者プロセス(グループ)にシグナルを送信すると、 kill (2)で説明したものと同じ許可チェックが行われます。送信プロセスは F_SETOWN を使用するプロセスです(ただし、以下のバグを参照) )。

ファイル記述子_fd_がソケットを参照している場合、 F_SETOWN は、帯域外データがそのソケットに到着したときに配信されるSIGURGシグナルの受信者も選択します。 (SIGURGは、 select (2)がソケットに「例外条件」があると報告する場合に送信されます。)

スレッドグループ(NPTLなど)をサポートするスレッドライブラリで実行されているマルチスレッドプロセスで F_SETSIG にゼロ以外の値が与えられた場合、 F_SETOWN に与えられた正の値は異なる意味を持ちます:プロセス全体を識別するプロセスID。プロセス内の特定のスレッドを識別するスレッドIDです。 したがって、 F_SETSIG が使用されている場合に適切な結果を得るには、 getpid ()ではなく gettid ()の結果を F_SETOWN に渡す必要がある場合があります。 (現在のLinuxスレッド実装では、メインスレッドのスレッドIDはプロセスIDと同じです。 つまり、このシナリオでは、シングルスレッドプログラムは gettid ()または getpid ()を等しく使用できます。)ただし、この段落のステートメントは、out-of-ソケット上のバンドデータ:このシグナルは、 F_SETOWN に指定された値に応じて、常にプロセスまたはプロセスグループのいずれかに送信されます。 また、Linuxはプロセスのキューに入れることができるリアルタイムシグナルの数に制限を課し( getrlimit (2)および signal (7)を参照)、この制限に達すると、カーネルはSIGIOを配信し、このシグナルは特定のスレッドではなくプロセス全体に配信されます。

F_GETSIG Get the signal sent when input or output becomes possible. A value of zero means SIGIO is sent. Any other value (including SIGIO) is the signal sent instead, and in this case additional info is available to the signal handler if installed with SA_SIGINFO.
F_SETSIG

Sets the signal sent when input or output becomes possible. A value of zero means to send the default SIGIO signal. Any other value (including SIGIO) is the signal to send instead, and in this case additional info is available to the signal handler if installed with SA_SIGINFO.

さらに、ゼロ以外の値を F_SETSIG に渡すと、シグナル受信者がプロセス全体からプロセス内の特定のスレッドに変更されます。 詳細については、 F_SETOWN の説明を参照してください。

ゼロ以外の値で F_SETSIG を使用し、シグナルハンドラーにSA_SIGINFOを設定すると( sigaction (2)を参照)、I/Oイベントに関する追加情報が_siginfo_t_構造体のハンドラーに渡されます。 _si_code_フィールドがソースがSI_SIGIOであることを示す場合、_si_fd_フィールドはイベントに関連付けられたファイル記述子を示します。 それ以外の場合、保留中のファイル記述子は示されず、通常のメカニズム( select (2)、 poll (2)、 read (2)と O_NONBLOCK セットなど)を使用して決定する必要がありますI/Oに使用できるファイル記述子。

リアルタイム信号(値> = SIGRTMIN)を選択することにより、同じ信号番号を使用して複数のI/Oイベントをキューに入れることができます。 (キューイングは利用可能なメモリに依存します)。 上記のように、シグナルハンドラにSA_SIGINFOが設定されている場合、追加情報が利用可能です。

これらのメカニズムを使用すると、プログラムはほとんどの場合 select (2)または poll (2)を使用せずに完全に非同期のI/Oを実装できます。

*O_ASYNC* 、 *F_GETOWN* 、 *F_SETOWN* の使用は、BSDおよびLinuxに固有です。 *F_GETSIG* および *F_SETSIG* はLinux固有です。 POSIXには非同期I/Oと_aio_sigevent_構造があり、同様のことを実現しています。これらは、GNU Cライブラリ(Glibc)の一部としてLinuxでも利用できます。

リース

*F_SETLEASE* および *F_GETLEASE* (Linux 2.4以降)は、_fd_によって参照されるファイルの呼び出しプロセスのリースの現在の設定を確立および取得するために(それぞれ)使用されます。 ファイルリースは、プロセス(「リースブレーカー」)が *open* (2)または *truncate* を試行したときに、リースを保持しているプロセス(「リースホルダー」)に(シグナルの配信を介して)通知されるメカニズムを提供します。 (2)そのファイル。

Tag

説明

*F_SETLEASE*

整数_arg_に指定されている次の値に応じて、ファイルリースを設定または削除します。

Tag Description
F_RDLCK Take out a read lease. This will cause the calling process to be notified when the file is opened for writing or is truncated. A read lease can only be placed on a file descriptor that is opened read-only.
F_WRLCK Take out a write lease. This will cause the caller to be notified when the file is opened for reading or writing or is truncated. A write lease may be placed on a file only if no other process currently has the file open.
*F_UNLCK * Remove our lease from the file.

プロセスは、ファイルに対して1種類のリースのみを保持できます。

リースは通常のファイルでのみ取得できます。 特権を持たないプロセスは、プロセスのファイルシステムUIDと一致するUIDを持つファイルのリースのみを取得できます。* CAP_LEASE *機能を持つプロセスは、任意のファイルのリースを取得できます。

*F_GETLEASE*
*F_RDLCK* 、 *F_WRLCK* 、または* F_UNLCK、*のいずれかを返すことにより、_fd_によって参照されるファイルに保持するリースのタイプを示します。それぞれ、呼び出しプロセスが読み取り、書き込み、またはファイル。 ( *fcntl* ()の3番目の引数は省略されています。)

プロセス(「リースブレーカー」)が open ()または truncate ()を実行して F_SETLEASE を介して確立されたリースと競合する場合、システムコールはカーネルによってブロックされ、カーネルはシグナルを送信します(デフォルトではSIGIO)。 リース所有者は、別のプロセスがファイルにアクセスするために必要なクリーンアップ(キャッシュバッファのフラッシュなど)を行うことでこの信号の受信に応答し、リースを削除またはダウングレードする必要があります。 リースは、_arg_を F_UNLCK として指定する F_SETLEASE コマンドを実行することにより削除されます。 現在ファイルの書き込みリースを保持しており、リースブレーカーが読み取りのためにファイルを開いている場合、リースを読み取りリースにダウングレードするだけで十分です。 これは、_arg_を F_RDLCK として指定する F_SETLEASE コマンドを実行することにより行われます。

リース所有者が_/proc/sys/fs/lease-break-time_で指定された秒数以内にリースのダウングレードまたは削除に失敗した場合、カーネルはリース所有者のリースを強制的に削除またはダウングレードします。

リースが自発的または強制的に削除またはダウングレードされ、リースブレーカーがシステムコールのブロックを解除していないと仮定すると、カーネルはリースブレーカーのシステムコールの続行を許可します。

リースブレーカーのブロックされた open ()または truncate ()がシグナルハンドラーによって中断された場合、システムコールはエラー EINTR で失敗しますが、他の手順は上記のように発生します。 open ()または truncate ()でブロックされている間にリースブレーカーがシグナルによって強制終了された場合、他の手順は上記のように発生します。 リースブレーカーが open ()の呼び出し時に O_NONBLOCK フラグを指定した場合、呼び出しはすぐにエラー EWOULDBLOCK で失敗しますが、上記のように他のステップが発生します。

リース所有者への通知に使用されるデフォルトのシグナルはSIGIOですが、これは F_SETSIG コマンドを使用して fcntl ()に変更できます。 F_SETSIG コマンド(SIGIOを指定するコマンドも)が実行され、シグナルハンドラーがSA_SIGINFOを使用して確立される場合、ハンドラーは_siginfo_t_構造体を2番目の引数として受け取り、この引数の_si_fd_フィールドは別のプロセスによってアクセスされたリースファイル。 (これは、呼び出し元が複数のファイルに対してリースを保持している場合に役立ちます)。

ファイルとディレクトリの変更通知(通知)

Tag

説明

*F_NOTIFY*

(Linux 2.4以降)_fd_またはそれに含まれるファイルが参照するディレクトリが変更されたときに通知を提供します。 通知されるイベントは、_arg_で指定されます。_arg_は、次のビットの0個以上の論理和で指定されるビットマスクです。

Bit

説明(ディレクトリ内のイベント)

*DN_MODIFY*

ファイルが変更されました(write、pwrite、

 

writev、truncate、ftruncate)

*DN_CREATE*

ファイルが作成されました(open、creat、mknod、

 

mkdir、link、symlink、rename)

*DN_DELETE*

ファイルがリンク解除されました(リンク解除、名前を変更

 

別のディレクトリ、rmdir)

*DN_RENAME*

この中でファイルの名前が変更されました

 

ディレクトリ(名前の変更)

*DN_ATTRIB*

ファイルの属性が変更されました

 

(chown、chmod、utime [s])

(これらの定義を取得するには、_GNU_SOURCE機能テストマクロを定義する必要があります。)

ディレクトリ通知は通常「1回限り」であり、アプリケーションはさらに通知を受信するために再登録する必要があります。 または、 DN_MULTISHOT が_arg_に含まれている場合、通知は明示的に削除されるまで有効です。

一連の F_NOTIFY 要求は累積的であり、_arg_のイベントは既に監視されているセットに追加されます。 すべてのイベントの通知を無効にするには、_arg_を0に指定して F_NOTIFY 呼び出しを行います。

通知はシグナルの配信を介して発生します。 デフォルトのシグナルはSIGIOですが、これは F_SETSIG コマンドを使用して fcntl ()に変更できます。 後者の場合、シグナルハンドラーは_siginfo_t_構造体を2番目の引数として受け取り(ハンドラーがSA_SIGINFOを使用して確立された場合)、この構造体の_si_fd_フィールドには、通知を生成したファイル記述子が含まれます(複数のディレクトリで通知を確立するときに便利です)。

特に DN_MULTISHOT を使用する場合は、複数の通知をキューに入れることができるように、リアルタイムシグナルを通知に使用する必要があります。

注:*新しいアプリケーションでは、_inotify_インターフェイス(カーネル2.6.13以降で使用可能)の使用を検討する必要があります。これは、ファイルシステムイベントの通知を取得するための優れたインターフェイスを提供します。 *inotify (7)を参照してください。

返り値

呼び出しが成功した場合、戻り値は操作によって異なります。

Tag Description
F_DUPFD The new descriptor.
F_GETFD Value of flags.
F_GETFL Value of flags.
F_GETOWN Value of descriptor owner.
F_GETSIG Value of signal sent when read or write becomes possible, or zero for traditional SIGIO behaviour.
All other commands
  Zero.

エラーの場合、-1が返され、_errno_が適切に設定されます。

エラー

Tag Description
EACCES *or EAGAIN* Operation is prohibited by locks held by other processes.
EAGAIN The operation is prohibited because the file has been memory-mapped by another process.
*EBADF * fd is not an open file descriptor, or the command was* F_SETLK or F_SETLKW* and the file descriptor open mode doesn’t match with the type of lock requested.
*EDEADLK * It was detected that the specified* F_SETLKW* command would cause a deadlock.
EFAULT lock is outside your accessible address space.
*EINTR * For* F_SETLKW*, the command was interrupted by a signal. For F_GETLK *and F_SETLK*, the command was interrupted by a signal before the lock was checked or acquired. Most likely when locking a remote file (e.g. locking over NFS), but can sometimes happen locally.
*EINVAL * For* F_DUPFD*, arg is negative or is greater than the maximum allowable value. For F_SETSIG, arg is not an allowable signal number.
*EMFILE * For* F_DUPFD*, the process already has the maximum number of file descriptors open.
ENOLCK Too many segment locks open, lock table is full, or a remote locking protocol failed (e.g. locking over NFS).
*EPERM * Attempted to clear the* O_APPEND* flag on a file that has the append-only attribute set.

ノート

*dup2* ()によって返されるエラーは、 *F_DUPFD* によって返されるエラーとは異なります。

カーネル2.0以降、 flock (2)と fcntl (2)によって設定されたロックの種類の間には相互作用はありません。

POSIX.1-2001では、l_len_を負にすることができます。 (もしそうなら、ロックによって記述される間隔は、_l_start-1までのバイトl_start + _ l_len_をカバーします。)これは、Linux 2.4.21および2.5.49以降のLinuxでサポートされています。

いくつかのシステムでは、struct flock_にさらにフィールドがあります(例: _l_sysid。 明らかに、ロックを保持しているプロセスが別のマシンに存在する場合、_l_pid_だけではあまり役に立ちません。

BUGS

一部のアーキテクチャ(特にx86)でのLinuxシステムコール規則の制限は、 F_GETOWN によって返される(負の)プロセスグループIDが-1〜-4095の範囲にある場合、戻り値が誤って解釈されることを意味します。システムコールのエラーとしてのglibc。つまり、 fcntl ()の戻り値は-1になり、_errno_には(正の)プロセスグループIDが含まれます。

Linux 2.4以前では、非特権プロセスが F_SETOWN を使用して、ソケットファイル記述子の所有者を呼び出し元以外のプロセス(グループ)として指定する場合に発生するバグがあります。 この場合、 fcntl ()は、所有者プロセス(グループ)が呼び出し側にシグナルを送信する許可がある場合でも、_errno_を EPERM に設定して-1を返すことができます。 このエラーが返されても、ファイル記述子の所有者が設定され、信号が所有者に送信されます。

準拠

SVr4、4.3BSD、POSIX.1-2001。 POSIX.1-2001で指定されている操作は、F_DUPFD、F_GETFD、F_SETFD、F_GETFL、F_SETFL、F_GETLK、F_SETLK、F_SETLKW、F_GETOWN、およびF_SETOWNのみです。

F_GETSIG、F_SETSIG、F_NOTIFY、F_GETLEASE、およびF_SETLEASEはLinux固有です。 (_GNU_SOURCEマクロを定義して、これらの定義を取得します。)

関連項目

[[File:]] image :http://www.finddevguides.com/images/next.gif [next] [[File:]]

広告

  
Advertisements