はじめに
ファイルディスクリプタ(Windowsではファイルハンドル)は、プロセスや実行ファイルにとって外部の資源にアクセスしたりアクセスされたりする際に使用される抽象的なインターフェースです。
今日のプログラムは必ずと言っていいほど外部とのインターフェースを持っていますが、新しいディスクリプタや効率的な使い方がそれほど明確ではなかったりします。
当連載では、ファイルディスクリプタに関する調査・試行錯誤した結果、新しいディスクリプタを使用した感想や効率的な管理方法など、独断と偏見と誤解とたくさんのサンプルを記載します。
今回使用している環境は、Fedora11とRedHatEL5.3を使用しています。主に連載の第4回まではFedoraを、それ以外ではRedHatEL5.3を使用しています。Fedoraのカーネルバージョンは2.6.29.4-167、glibcのバージョンは2.10.1-2です。Ubuntuの(現時点での)最新版9.04では、提供カーネルバージョンが2.6.28を採用しているらしいので、私は試していませんが、おそらく利用できると思います。RedHatは商用版なので、CentOSでも大丈夫でしょう。
連載概要
この連載は、次のような内容について述べていく予定です。
連載目次
- 第1回:ファイルディスクリプタの概要
- 第2回:イベント用ディスクリプタ「eventfd」の特徴
- 第3回:タイマー用ディスクリプタ「timerfd」の特徴
- 第4回:シグナル用ディスクリプタ「signalfd」の特徴
- 第5回:多重I/O「Multiplex I/O」の種類の特徴、使い方、性能差
- 第6回:シグナル駆動I/Oの特徴、使い方
- 第7回:非同期I/O「Asynchronous I/O」の使い方と性能差
- 第8回:ファイルディスクリプタパッシングの特徴、使い方
サンプルプログラムは100行前後程度までは画面に記載します。全プログラムは圧縮してページ上部よりダウンロード可能にします。make
コマンドでコンパイルできます。i386/x86_64環境で動作確認済みです。
プログラムのボリューム上、エラー処理や引数チェックなどを省いているので、あらかじめご了解ください。また使用法を誤るとシステムに重大な影響を与える可能性があります。利用する場合は責任のとれる環境において実行するよう、お願いします。
当トピックでは、実際にプログラムを通して動作確認や性能測定を行うことで、個人的な見解を述べさせていただきます。あくまで個人的な感想に基づいているので、反論や指摘などあるかと思います。指摘や質問などは大歓迎なので、その際はぜひご連絡ください。可能な限りの対応に努めます。
ファイルディスクリプタの概要
ファイルディスクリプタはファイル操作を汎用的に行うために使用する整数値ですが、UNIX/Linuxではそれ以外も対象として操作できるよう、抽象的な作りになっています。
ファイル操作用のファイルディスクリプタで有名なもので言うと、stdin
、stdio
、stderr
が挙げられます。しかし、printf
系の関数群に設定するstdin
、stdio
、stderr
について、これらはFILE構造体へのポインタであり、ファイルディスクリプタをラップしているので、本来のファイルディスクリプタと同じではありません。
stdin
、stdio
、stderr
に相当する実際のファイルディスクリプタの値は、それぞれ0、1、2になり、プログラムが実行時にこの3個のディスクリプタが開かれ、プログラム停止時に閉じられます。
それ以外のファイルディスクリプタはプログラムで意識的に生成し責任を持って閉じる必要があります。主に下記の関数によってディスクリプタを生成します。
open(2)
、creat(2)
:ファイルおよびデバイスが対象socket(2)
、socketpair(2)
、accept(2)
:ソケットが対象pipe(2)
:パイプが対象
上記の生成方法に沿って生成されたファイルディスクリプタは、read(2)
およびwrite(2)
の関数によって統一的に操作出来ます。
Unixの祖である、Ken Thompsonのスペルミスであることが、有力な説です。
一方ではabbreviationではないかという意見もあるそうです。
新しいファイルディスクリプタについて
今までのファイルディスクリプタは、ファイル・デバイス・ソケット・パイプを対象にしていました。しかし新たなカーネルとglibによって、今回、新たに3個のファイルディスクリプタが追加されました。
- イベント(eventfd)
- タイマー(timerfd)
- シグナル(signalfd)
イベントの発生を待ったり通知したりする際に使用するファイルディスクリプタです。基本的な動作は名前なしパイプと同じです。親子プロセスやスレッド間で使用できます。
設定された時間がタイムアップしたことを通知するファイルディスクリプタです。
シグナルが通知されたことを検知する為のファイルディスクリプタです。既存ではシグナルハンドラで実装されていましたが、ディスクリプタ経由で検知可能となりました。
まとめ
今回は、ファイルディスクリプタの概要について解説しました。次回は、新たに追加された3個のファイルディスクリプタの中から、イベント用ファイルディスクリプタ「eventfd
」を取り上げ、使用法や特徴、既存のファイルディスクリプタとの違いについて、説明していきたいと思います。