8.11 fcntl -- fcntl() および ioctl() システムコール

Unixプラットフォームで利用できます。

このモジュールでは、ファイル記述子 (file descriptor) に基づいた ファイル制御および I/O 制御を実現します。 このモジュールは、 Unix のルーチンである fcntl() および ioctl() へのインタフェースです。

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

このモジュールでは以下の関数を定義しています:

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

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

ioctl( fd, op, arg)
この関数は fcntl() 関数と同じですが、操作が通常ライブラリ モジュール termios で定義されており、引数の扱いがより 複雑であるところが異なります。

パラメタ arg は整数か、存在しない (整数 0 と等価なもの として扱われます) か、(通常の Python 文字列のような) 読み出し専用の バッファインタフェースをサポートするオブジェクトか、読み書き バッファインタフェースをサポートするオブジェクトです。

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

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

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

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

mutate_flag が与えられなかった場合、2.3 ではこの値は偽となります。 この仕様は今後のいくつかのバージョンを経た Python で変更される予定 です: 2.4 では、 mutate_flag を提供し忘れると警告が出されますが 同じ動作を行い、2.5 ではデフォルトの値が真となるはずです。

以下に例を示します:

>>> 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])

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

lockf( fd, operation, [length, [start, [whence]]])
本質的に fcntl() によるロッキングの呼び出しをラップ したものです。fd はロックまたはアンロックするファイルの ファイル記述子で、operation は以下の値:

のうちいずれかになります。

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

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

start の標準の値は 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 は整数値を保持しています; 二つ目の 例では文字列値を保持しています。lockdata 変数の構造体 レイアウトはシステム依存です -- 従って flock() を 呼ぶ方がベターです。

参考:

os:モジュール
os.open() 関数はロックフラグをサポートしていて lockf()flock()関数よりも多様な環境で利用でき、 よりプラットフォーム独立なロック機構を提供します。.
ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。