Linux の daemon の作成

daemon は制御端末をもたないプロセスである.
ps すると daemon の TTY の項は ? になっている.

プロセスを daemon として動作させるには

  • 制御端末を切り離すために,setsid で新しいセッションを作成してセッション・リーダーになる
  • setsid を成功させるために,fork して親プロセスを exit して子プロセスで setsid を実行する
  • 制御端末がないから,標準入力,標準入出力,標準エラー出力を閉じる
  • 制御端末がないから,エラーをシステムロガーへ出力する
  • プロセスのカレントディレクトリがマウントされたファイルシステム上にないことを保証するために,カレントディレクトリを / に変更する
  • プロセスがファイルを作成するときに正しくパーミッションを設定するために,umask を 0 にリセットする

以上のことをすればよい.

サンプルコードは以下の通り.

#include 
#include 
#include 
#include 

int main(void)
{
    pid_t pid, sid;

    /* システムロガーへの接続を開始 */
    openlog(/* デーモンの名前 */, LOG_PID, LOG_DAEMON);

    /* 子プロセスの開始 */
    pid = fork();
    if ( pid < 0 ) {
        syslog(LOG_ERR, "fork");
        exit(EXIT_FAILURE);
    }

    /* 親プロセスを終了 */
    if ( pid > 0 ) exit(EXIT_SUCCESS);

    /* 新しいセッションを作成 */
    sid = setsid();
    if ( sid < 0 ) {
        syslog(LOG_ERR, "setsid");
        exit(EXIT_FAILURE);
    }

    /* カレントディレクトリを / に変更 */
    if ( chdir("/") < 0 ) {
        syslog(LOG_ERR, "chdir");
        exit(EXIT_FAILURE);
    }

    /* ファイル作成マスクをリセット */
    umask(0);

    /* 標準入力,標準出力,標準エラー出力を閉じる */
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);

    /* この daemon でやりたいことをやる */
    〜

    /* システムロガーへの接続を終了 */
    closelog();

    exit(EXIT_SUCCESS);
}
  • 参考

例題で学ぶLinuxプログラミング―GCCからRPMまでオープンソース・アプリケーション技術