デーモン
Last Modified: Tue Dec 27 00:06:02 JST 2011

デーモン

デーモンとは、イベントを待ってスリープしているプロセスのことである。 イベントが発生すると、デーモンは目を覚まし、仕事をしてからまた眠るというわけである。 …じゃあプロセスっていったい何だろう。

プロセス

プロセスとは、実行中のプログラムのことを指す用語だ。 プロセスは、プログラム本体、データ、スタック、プログラムポインタ、スタックポインタ、すべてのレジスタ、その他プログラムの実行を支えている様々な情報によって構成されている。 なんのことやらさっぱり分からんという場合も、まあ気にしないで先に進んでほしい。

最近の OS は、だいたいマルチプロセスをサポートしている。 つまり、複数のプログラムを同時に実行できるようになっている。 とはいえ、コンピュータには1つの CPU しか搭載されていない。 たった1つの CPU で、複数のプロセスを同時にサポートするにはどうするか。 そのための仕組みがタイムシェアリングである。

いまコンピュータの上で、5つのプログラムが同時に実行中であるとしよう。 それぞれはプロセスという概念で管理されている。 プロセス A が最初に実行され、たとえば 50ms (20分の1秒)が過ぎたとしよう。 OS は割り当てられた時間が切れたと判断して、いったんプロセス A を凍結する。 そして次のプロセス B を実行に移す。 さらに 50ms が過ぎると、今度はプロセス B が凍結され、プロセス C が実行される。 こうして順に D、E のプロセスが実行され、ふたたびプロセス A の順番が回ってくる。 凍結されていたプロセス A は、そっくりそのまま復元されて、中断したところから再開される。 そして、割り当てられた 50ms を実行すると、またまた凍結されて次のプロセスへ順序を譲るのである。 このような切り替えは、十分に高速に行えば、まるでそれぞれのプロセスが同時に動作しているように見えるというわけである。

プロセスというのは、このような切り替えを行う上での単位となる重要な概念である。 FreeBSD を含めて Unix によって動作しているコンピュータは、常時 20 個ほどのプロセスが実行されている (ps コマンドを使えば、プロセスのリストを見ることができる)。 インターネットサーバとして利用されているマシンならば、200個とか500個にもおよぶプロセスが、せわしなくクライアントからの要求を処理しているはずだ。

このようなプロセス同士は、原則として互いに相手に干渉できない仕組みになっている。 たとえば個々のプロセスには、専用のメモリ空間が割り当てられ、他のプロセスからメモリにアクセスされたり、勝手に書き換えられたりできないよう、きちんとした保護機能が用意されている。 しかし、一方では保護機能のない資源もある。

たとえば、プリンタを使ってファイルを印字しようとしている2つのプロセスがあるとしよう。 プロセス A がファイルをオープンし、最初の2、3行を印字したところで割り当てられた 50ms が過ぎてしまったとしよう。 次のプロセス B が、やはりファイルをオープンし、自分で印字したい内容をプリンタに送りつける。 その結果、A と B の出力が完全に混じってしまうのである。 これではまともに印刷を行うことができない。

このような事故を防ぐために、様々な機構やプログラミングテクニックが存在するのだが、そのひとつにスプーリングという手法がある。
まずプリンタから印刷を行いたいプログラムは、スプールと呼ばれるディレクトリに、印刷したいファイルをコピーするというルールを作る。 そして、スプールにファイルが置かれると、それを選んでプリンタに送り込み、印字を完了させる専用のプログラムを用意する。 印刷プログラムは、スプールにコピーされたファイルを順番に処理するので、印字結果が混ざってしまうような事故は起こらないという寸法である。 この、「ファイルがコピーされたら印刷する」というプログラムこそが、デーモンと呼ばれる種類のプロセスなのである。

デーモンの種類

デーモンには色々な種類がある。 ちょっと ps の出力例をお目にかけよう。

% ps ax
  PID  TT  STAT      TIME COMMAND
    0  ??  DLs    0:00.80  (swapper)
    1  ??  Is     0:00.05 /sbin/init --
    2  ??  DL     0:01.74  (pagedaemon)
    3  ??  DL     0:00.00  (vmdaemon)
    4  ??  DL     6:25.20  (syncer)
   36  ??  Is     0:00.00 adjkerntz -i
   98  ??  Is     0:06.80 syslogd
  103  ??  Is     0:16.54 named
  108  ??  S<s    2:03.91 xntpd -p /var/run/xntpd.pid
  112  ??  Is     0:00.07 portmap
  124  ??  Is     0:00.15 mountd -r
  127  ??  Is     0:00.00 nfsd: master (nfsd)
  135  ??  Is     0:00.00 rpc.statd
  140  ??  I      0:00.22 nfsiod -n 4
  148  ??  Is     0:01.97 amd -p -a /net -c 1800 -k i386 -d srs.ne.jp -l syslog
  172  ??  Is     0:00.31 inetd
  175  ??  Is     0:11.37 cron
  179  ??  Is     0:09.85 sendmail: accepting connections on port 25 (sendmail)
  228  ??  Is     0:00.00 /usr/local/pgsql/bin/postmaster -D/usr/local/pgsql/da
  241  ??  I      0:54.29 /usr/local/bin/Wnn6/jserver
34541  ??  Ss     0:14.69 /usr/local/apache-1.3.6p/bin/httpd
42136  ??  Ss     0:03.07 telnetd
42137  p0  Ss     0:00.16 -tcsh (tcsh)
42149  p0  T      0:23.13 mule -nw daemon.txt
42225  p0  R+     0:00.00 ps -ax
  261  v0  Is+    0:00.01 /usr/libexec/getty Pc ttyv0
  262  v1  Is+    0:00.01 /usr/libexec/getty Pc ttyv1
  263  v2  Is+    0:00.01 /usr/libexec/getty Pc ttyv2
  240 con- I      0:00.00 /usr/local/bin/Wnn6/jserver

冗長な部分は省略しているが、だいたいこんな感じである。 上から順に紹介していこう。

swapper ページスワップを処理するデーモン
init 最初のプロセス。すべてのプロセスの親
pagedaemon ページングデーモン
vmdaemon 仮想メモリを管理するデーモン
syncer ディスクとキャッシュの同期を取るデーモン
adjkerntz BIOS のローカルタイムとシステムクロックを同期させるデーモン
syslogd エラーメッセージなどを記録するデーモン
named DNS サーバ (name daemon)
xntpd NTP を処理するデーモン
portmap RPC サーバ
mountd NFS マウントデーモン
nfsd NFS サービスサーバ
rpc.statd ホストステータス監視デーモン
nfsiod NFS 非同期I/O サーバ
amd オートマウントデーモン
inetd インターネットスーパーサーバ
cron コマンドスケジュールデーモン
sendmail メールデーモン
postmaster データベースサーバ
jserver かな漢字変換サーバ (Wnn)
httpd Web サーバ (Apache)
telnetd telnet サーバ
tcsh シェル
mule エディタ
ps このリストを表示しているプログラム
getty ターミナルを初期化し login を受け付けるプロセス

このマシンは個人専用で使っているため、ユーザプロセスといえば原稿を書いている自分のエディタぐらいしかないという片寄った例になってしまったが、 ほとんどがデーモンであることは分かっていただけると思う。

というわけで、デーモンと Unix は切っても切れない深い関係にある。 災厄をもたらす悪魔というよりは、守護神といったところだろう。 たとえば FreeBSD のマスコットは、fork にちなんだ三つ又の槍を手に持つデーモンである。 スニーカーを履いているのは、たぶん大学で生まれたことの名残なんじゃないかと思う。


[back to index]