デーモンの仕組み
デーモンはバックグラウンドで動き、terminalからインタラクティブに操作されることがないプロセスである。起動時に開始し、rootユーザやapache、postfixなどの特権ユーザにより動かされる。systemdで操作するcrondとかsshdとかのことである。
デーモンは一般的に、initプロセスの子プロセスとして動く、terminalから接続されないという2つの要件を満たしている。initプロセスとはシステム起動後にカーネルが最初に実行するプロセスでこのpidは1である。
以下のようにしてデーモンは起動される。
- fork()を呼び、デーモンとなる新しいプロセスを作る。
- デーモンの親プロセスがexit()を呼んで終了する。親プロセスがすぐに死に、デーモンはプロセスグループのリーダーにならない。
- setsid()を呼び、デーモンに新しいプロセスグループとセッションを与え、デーモンがリーダーになるようにする。これによりプロセスを制御するterminalがないことも保証できる。
- chdir()でワーキングディレクトリをrootディレクトリに変更する。これはデーモンが他のディレクトリを使用中にしないようにするため、adminにワーキングディレクトリをunmountされることを避けるためである。
- 全てのファイルディスクリプタを閉じる。機能的に必要であればそこは開けておく。
- ファイルディスクリプタの0(stdin)、1(stdout)、2(stderror)を開き/dev/nullにリダイレクトする。
これらに基づき、デーモン化するコードは以下のようになる。このコードはLinuxシステムプログラミング | Robert Love, ロバート ラブ, 千住 治郎より拝借した。
#include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <linux/fs.h> int main (void) { pid_t pid; int i; /* forkして新しいプロセスを作る */ pid = fork(); if (pid == -1) return -1; else if (pid != 0) exit(EXIT_SUCCESS); /* 新しいセッションとプロセスグループを作る */ if (setsid() == -1) return -1; /* ワーキングディレクトリをルートに変更 */ if (chdir("/") == -1) return -1; /* NR_OPENを使って全てのファイルディスクリプタを閉じる */ for (i = 0; i < NR_OPEN; i++) close(i); /* ファイルディスクリプタ 0, 1, 2を /dev/nullにリダイレクト */ open("/dev/null", O_RDWR); /* stdin */ dup(0); /* stdout */ dup(0); /* stderror */ return 0; }