ひとりアドベントカレンダー2015 第21日目 〜 PHPer でもデーモンになってみたい

  • このエントリーをはてなブックマークに追加
  • Pocket

21日目です!!

きょうも引き続きぺちぱーシリーズをお送りします。その名も 「PHPer でもデーモンになってみたい」です。デーモン(daemon)とは悪魔のこと、ではなくUNIX などのマルチタスク OS においてバックグラウンドプロセスとして動作するプログラムのことです。このプログラムを実行しているプロセスをデーモンプロセスと言ったりします。いわゆるサーバープログラムはデーモンであることが多いです。以下では PHP のプログラムをこのデーモンとして作ってみたいと思います。

デーモンプロセス

ものの本によるとデーモンとは以下の性質を全て満たすプロセスのことを言うそうです:

  • 親プロセスが init
  • 制御端末を持たない
  • プロセスグループのリーダーである
  • セッションリーダーではない
  • ルートディレクトリをカレントディレクトリとして稼働する
  • すべてのファイルディスクリプタをクローズしている

各言葉の意味は割愛させていただきますが、これらをPHPプログラムで満たしていきましょう。

 

親プロセスが init

プロセスを一回 fork() して親プロセスを殺します。親が死んだプロセスは init プロセスが引き取るのでこれが実現されます。

これを実行すると、

 となって、プロンプトが戻ってくる(2行目)のでバックグラウンドで動作していることがわかります。 

制御端末の切り離し

setsid() で新しいセッションを生成します。新しいセッションは制御端末から切り離されて制御端末を持たなくなります。

セッションリーダーでないようにする 

セッションの生成直後は、自分はそのセッションのリーダーである状態です。ここからもう一度 fork() をおこなってセッションリーダーではない状態にします。これを行う理由は、「制御端末を持たないセッションリーダーは制御端末をオープンすると、その制御端末がどのプロセスにも属していない場合、そのプロセスの制御端末になるという性質がある」からだそうです。現代的なシステムではこの性質はなく、必要ないらしいのですが念のためにやっておきます:

 ルートディレクトリをカレントディレクトリとする

これは chdir() でできますね:

 標準入出力を閉じる

制御端末が切り離されているので標準入出力が必要ありません。閉じておきましょう:

 しかし、「すべてのファイルディスクリプタをクローズ」してしまったら完全に入出力が断たれてしまってプロセスが存在していても情報のやり取りができませんね。正確には「親プロセスから継承した全てのオープンファイルディスクリプタをクローズ」というのが正しいようです。デーモンになったあとで必要なファイルをオープンします:

 まとめ

以上で、自分で書いた PHP のプログラムがデーモンになれました。デーモンプログラムは末尾に ‘d’ という文字がついていることが多いようです。普段使っている httpd や memcached などがそうなっていますね。それらのプログラムはこうやって起動しているのですね。もっとも、 PHP で書かれていはいないでしょうけども。PHP で実際に書いてみることで Unix のプロセスの仕組みが少しわかりました。

参考

今日書いたプログラムの全体はこちらです:

https://gist.github.com/maple-nishiyama/3766172f4b3eed393807

また、今回は以下の資料を参考にしました:

 

  • このエントリーをはてなブックマークに追加
  • Pocket

SNSでもご購読できます。

コメントを残す

*