壊れたメガネ

ホッチキスの達人の意識の高いブログ。

php-eject で加速する大規模 Eject サービス

こんなの作りました

github oasynnoum/php-eject

能書き

今朝、なんとはなしにネットしていたらEjectコマンドユーザー会なるものが目に入って来ました。
なんぞこれ?と見てみたら、

CD-ROMドライブ読み出し専用ドライブや読み取り・書き込み機能が故障した光学ドライブと、 どのLinuxにもほぼ標準で搭載されているEjectコマンドを用いて、 排出されたCDトレイに何かをさせるユーザーの集いです。

とあります。なるほど面白い。
LT資料やデモ動画なんかも楽しい。というか物凄いいろんなところ出てるなと活動実績を見て驚きました。
僕もなんかできないかと考えましたが、これからPCばらしてCDドライブ取り出して工作する気にはとてもなれませんでした。というかアイディアがないし、あんな工作する腕もないし眠かったし無理だろと早々と諦めました。
しかしアイディアに共感した者としてはなんかやりたい、 だけど苦労はしたくないという思いを抱きながらEjectコマンドユーザー会の GitHub リポジトリを眺めてました。
サンプルの PHP コードを眺めていると eject は以下のように行われていました。
github Eject-Command-Users-Group/minimum-sample.php

exec('/usr/sbin/eject -T /dev/sr0');

実装方法としてはとってリ早い exec のコール。しかし、 PHP の exec の実装は popen(3) を用いています。
github php-src/TSRM/tsrm_virtual_cwd.h
このため、内部的に eject を実装するのに比べ、いくらかオーバーヘッドが生じます。
man popen(3) によると、

FILE popen(const char command, const char *type);
(中略)
popen() 関数は、プロセスをオープンする。具体的には、パイプを生成し、フォークを行い、 シェルを起動する。

とあります。つまり、「パイプを生成し、フォークを行い、 シェルを起動」というあたりがオーバーヘッドになり、大規模な eject サービスではこれがボトルネックになりうると考えられます。 そこで僕は eject を PHP に組み込もうと考えるに至りました。 php-eject の実装はシンプルで、ほとんどが eject(1) の実装をパクリ、元い、コピペしたものです。

ビルド・インストール

$ git clone https://github.com/oasynnoum/php-eject.git
$ cd php-eject
$ phpize
$ ./configure [--enable-eject]
$ make
$ make test
$ [sudo] make install

Eject!

$ php -a
Interactive shell

php > eject_toggle_tray("cdrom");
php > eject_close_tray("cdrom");