LoginSignup
5
4

More than 5 years have passed since last update.

LinuxFDイベント系のAPIまとめ

Last updated at Posted at 2018-06-15

今回libeventやlibevといった新しいイベント系APIを使う機会が出てきたので、まとめておきます。
深堀するとこうなるのが目に見えてるので、簡単な紹介だけ。

ここでいうイベントの流れ

  1. ファイルディスクリプタというものを作る。
  2. 待ち受け側はこのファイルディスクリプタでイベントを監視する。
  3. 通知側はこのファイルディスクリプタにイベントを通知する。
  4. 通知されたイベントを2が検知し、処理が実行される。

以降FDと書かれていたらファイルディスクリプタのことと思ってください。

スレッド間、プロセス間等でお話しするイメージですね。ものによってはイベント監視や通知自体をラップして使用者に意識させない作りになっています。
例えば…

  • libeventというOSSはイベント検知時に呼ばれる関数を登録する形式なので、利用者はイベント検知時に呼ばれる関数だけ作ればイベント処理実装完了!
  • timerfdというAPIはライブラリが勝手にタイマーイベントを発行してくれるので、待ち受け側だけ作ればタイマー処理実装完了!

こういったことは高級言語には当たり前かもしれませんが、OSSの用意もあり、自作でガリガリチューンアップも出来るFDイベントはC言語らしい機能だと思います。

1. ファイルディスクリプタ

色々あります。FDのイベント発行側が充実しているため、後で紹介するイベント監視が充実しているのか、それともその逆か?興味がある方は歴史を調べると面白いかもですね。

API 概要 備考
open /dev/console(標準出力)なんかはopenしてやりとりでしたね。確か。 通常ファイルに対してのみ行われるべき操作をデバイスファイルに対して行わない
socket 通信処理でまず習うであろうAPI。送受信に関するオプションがsetsockoptで色々と出来るので奥が深い(覗きはしない こういったオプションはOSS内で色々利用されているので、OSSコードを見ると思わぬ発見が
socketpair socketをサクッと使いたい時におすすめ。API一発で通信できます。 双方向通信出来る半面、2個FDを使うのが難点
eventfd ただただ通知をするためだけのAPI。カウンター式で、send時は数を送信(0だとFD未反応)、read側はカウンターが読める。 FD1つでいいので片方向ならこれを工夫して使った方がいいかも
timerfd 一定時間後にイベントを発行してくれる超絶便利API timerfdがない環境があるなら自作した方がいいですよレベルで好き
signalfd シグナルを拾うためのFDを作成する。mainの待ち受け内でシグナルも拾えるのは便利ですね。 シグナルの定義,シグナルハンドラーは制約があることに注意。 signalfdの参考
mq_open メッセージキューファイル用のopen処理 read/writeも専用APIで行います。
pipe forkしたプロセス間通信でも使用可能なFDを作成するAPI forkで利用できる代わりに単方向通信です。

※メッセージキュー:ファイル名を決めておいて、そのファイルを待ち受け側送信側互いにmq_openすれば通信が可能になる仕組み。
 UNIXドメインソケットでも似たようなことが出来ます。
fcntl等でoptionの変更が可能。blocking/non-blocking設定の参考

2. イベント監視

受信機能

API 概要
read, revc, etc 基本的なファイルディスクリプタの読み込み
mq_revc メッセージキューファイル経由での受信が可能なAPI。

イベント監視系機能

単純に受信をするだけだと1FDに1APIとなるので非効率。なのでFDをまとめて監視する機能があると便利。この機能が充実しています。

API 概要 個人的感想
select, pselect 古き良き定番API, Windowsにも対応 明確にFDを意識して利用するのがいい。毎回FD_ISSET等のAPIで確認作業をしなければいけないのが面倒
epoll selectの改良版、常にFDを設定しなおす手間を無くしたもの EPOLL_CTL_ADDすれば勝手に待ち受けにFDが追加されるので楽。個人の趣味としてはselectとどっこい
libevent 上記のようなイベント監視系のAPIをラップし、シンプルに使えるようにしたOSS コールバック形式なのが使いやすい。ただ、スレッドセーフでないためか繊細な印象。簡単なまとめ記事
libev 上記の高速対応版。API参考。ドキュメントはREADME⇒ここ
まずは「WHAT TO READ WHEN IN A HURRY」を、詳細は「FUNCTIONS CONTROLLING EVENT LOOPS」を参考にしてください。
ドキュメント類も充実しています。GPLで問題なければこちらを選択されるのが良さそう。
マルチスレッドで使用する場合はev_default_loop(0)ではなくev_loop_new, ev_loop, ev_unloopを使用します。

※poll, kqueue等は利用したことがないため省略

上記サンプルについて、色々あると思いますがlighttpdのfdevent_XXX.cを見るのがオススメです。全部まとまってますので。
OSSコードは多環境サポートの為複数処理を書くことになるため、各機能の保証付き実装が見ることが出来ます。

3. イベント発行

API 概要
write, send 基本的なファイルディスクリプタの書き込み
mq_send メッセージキューファイル経由での送信が可能なAPI

mqは別ですが、それ以外のFDはwriteが使えます。また、timerfdがFD兼イベント発行となっています。

その他

2018/06/19追記
FDじゃないけどpthread_condなんてのもありますね。
mutexと組み合わせて使うので、既にmutexで排他している時にはいいかもです。

参考

多重 I/Oに関する歴史 https://itkq.jp/blog/2017/05/10/linux-file-and-io/
各リンク

5
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4