35.9. "fcntl" --- "fcntl" および "ioctl" システムコール
*******************************************************

======================================================================

このモジュールでは、ファイル記述子 (file descriptor) に基づいたファイ
ル制御および I/O 制御を実現します。 このモジュールは、 Unix のルーチン
である "fcntl()" および "ioctl()" へのインタフェースです。 これらのシ
ステムコールの完全な説明は、 *fcntl(2)* と *ioctl(2)* のUnix マニュア
ルページを参照してください。

このモジュール内の全ての関数はファイル記述子 *fd* を最初の引数に取りま
す。 この値は "sys.stdin.fileno()" が返すような整数のファイル記述子で
も、 "sys.stdin" 自体のような、純粋にファイル記述子だけを返す
"fileno()" メソッドを提供している "io.IOBase"  オブジェクトでもかまい
ません。

バージョン 3.3 で変更: 以前は "IOError" を送出していたこのモジュールの
操作が、 "OSError" を送出するようになりました。

このモジュールには、以下の関数が定義されています:

fcntl.fcntl(fd, cmd, arg=0)

   操作 *cmd* をファイル記述子 *fd* (または "fileno()" メソッドを提供
   しているファイルオブジェクト) に対して実行します。 *cmd* として用い
   られる値はオペレーティングシステム依存で、 "fcntl" モジュール内に関
   連する C ヘッダファイルと同じ名前が使われている定数の形で利用出来ま
   す。引数 *arg* は整数値か "bytes" オブジェクトをとります。引数が整
   数値の場合、この関数の戻り値は C 言語の "fcntl()" を呼び出した際の
   整数の戻り値になります。引数が bytes の場合には、 "struct.pack()"
   で作られるようなバイナリの構造体を表します。バイナリデータはバッフ
   ァにコピーされ、そのアドレスが C 言語の "fcntl()" 呼び出しに渡され
   ます。 呼び出しが成功した後に戻される値はバッファの内容で、 "bytes"
   オブジェクトに変換されています。 返されるオブジェクトは *arg* 引数
   と同じ長さになります。 この値は 1024 バイトに制限されています。 オ
   ペレーティングシステムからバッファに返される情報の長さが 1024 バイ
   トよりも大きい場合、大抵はセグメンテーション違反となるか、より不可
   思議なデータの破損を引き起こします。

   "fcntl()" が失敗した場合、 "OSError" が送出されます。

fcntl.ioctl(fd, request, arg=0, mutate_flag=True)

   この関数は "fcntl()" 関数と同じですが、引数の扱いがより複雑であると
   ころが異なります。

   パラメータ *request* は32ビットに収まる値に制限されます。 *request*
   引数として使うのに関係のある追加の定数は "termios" モジュールにあり
   、関連する C ヘッダファイルで使われているのと同じ名前が付けられてい
   ます。

   パラメタ *arg* は、整数、 ("bytes" のような) 読み出し専用のバッファ
   インタフェースをサポートするオブジェクト、読み書きバッファインタフ
   ェースをサポートするオブジェクトのどれかです。

   最後の型のオブジェクトを除き、動作は "fcntl()" 関数と同じです。

   可変なバッファが渡された場合、動作は *mutate_flag* 引数の値で決定さ
   れます。

   この値が偽の場合、バッファの可変性は無視され、読み出し専用バッファ
   の場合と同じ動作になりますが、上で述べた 1024 バイトの制限は回避さ
   れます -- 従って、オペレーティングシステムが希望するバッファ長まで
   であれば正しく動作します。

   *mutate_flag* が真 (デフォルト) の場合、バッファは (実際には) 根底
   にある "ioctl()" システムコールに渡され、後者の戻り値が呼び出し側の
   Python に引き渡され、バッファの新たな内容は  "ioctl()" の動作を反映
   します。この説明はやや単純化されています。というのは、与えられたバ
   ッファが 1024 バイト長よりも短い場合、バッファはまず 1024 バイト長
   の静的なバッファにコピーされてから "ioctl()" に渡され、その後引数で
   与えたバッファに戻しコピーされるからです。

   "ioctl()" が失敗すると、 "OSError" 例外が送出されます。

   以下に例を示します:

      >>> import array, fcntl, struct, termios, os
      >>> os.getpgrp()
      13341
      >>> struct.unpack('h', fcntl.ioctl(0, termios.TIOCGPGRP, "  "))[0]
      13341
      >>> buf = array.array('h', [0])
      >>> fcntl.ioctl(0, termios.TIOCGPGRP, buf, 1)
      0
      >>> buf
      array('h', [13341])

fcntl.flock(fd, operation)

   ファイル記述子 *fd* ("fileno()" メソッドを提供しているファイルオブ
   ジェクトも含む) に対してロック操作 *operation* を実行します。 詳細
   は Unix マニュアルの *flock(2)* を参照してください (システムによっ
   ては、この関数は "fcntl()" を使ってエミュレーションされています)。

   "flock()" が失敗すると、 "OSError" 例外が送出されます。

fcntl.lockf(fd, cmd, len=0, start=0, whence=0)

   本質的に "fcntl()" によるロッキングの呼び出しをラップしたものです。
   *fd* はロックまたはアンロックするファイルのファイル記述子で、 *cmd*
   は以下の値のうちいずれかになります:

   * "LOCK_UN" -- アンロック

   * "LOCK_SH" -- 共有ロックを取得

   * "LOCK_EX" -- 排他的ロックを取得

   *cmd* が "LOCK_SH" または "LOCK_EX" の場合、 "LOCK_NB" とビット OR
   にすることでロック取得時にブロックしないようにすることができます。
   "LOCK_NB" が使われ、ロックが取得できなかった場合、 "OSError" が送出
   され、例外は *errno* 属性を持ち、その値は "EACCES" または "EAGAIN"
   になります (オペレーティングシステムに依存します; 可搬性のため、両
   方の値をチェックしてください)。少なくともいくつかのシステムでは、フ
   ァイル記述子が参照しているファイルが書き込みのために開かれている場
   合、 "LOCK_EX" だけしか使うことができません。

   *len* はロックを行いたいバイト数、 *start* はロック領域先頭の
   *whence* からの相対的なバイトオフセット、 *whence* は
   "io.IOBase.seek()" と同じで、具体的には:

   * "0" -- ファイル先頭からの相対位置 ("os.SEEK_SET")

   * "1" -- 現在のバッファ位置からの相対位置 ("os.SEEK_CUR")

   * "2" -- ファイルの末尾からの相対位置 ("os.SEEK_END")

   *start* の標準の値は 0 で、ファイルの先頭から開始することを意味しま
   す。*len* の標準の値は 0 で、ファイルの終了までロックすることを表し
   ます。*whence* の標準の値も 0 です。

以下に (全ての SVR4 互換システムでの) 例を示します:

   import struct, fcntl, os

   f = open(...)
   rv = fcntl.fcntl(f, fcntl.F_SETFL, os.O_NDELAY)

   lockdata = struct.pack('hhllhh', fcntl.F_WRLCK, 0, 0, 0, 0, 0)
   rv = fcntl.fcntl(f, fcntl.F_SETLKW, lockdata)

最初の例では、戻り値 *rv* は整数値を保持しています; 二つ目の例では
"bytes" オブジェクトを保持しています。 *lockdata* 変数の構造体レイアウ
トはシステム依存です --- 従って "flock()" を呼ぶ方が良いでしょう。

参考:

  "os" モジュール
     もし "os" モジュールに "os.O_SHLOCK" と "os.O_EXLOCK" が 存在する
     場合 (BSD のみ)、 "os.open()" 関数は "lockf()" や "flock()" 関数
     を代替できます。
