創建 Daemon 程式

Daemon 的原意其實就是小精靈(或是小惡魔),一般人是看不見的。而 Daemon 程式是指常駐在 Linux(或 Unix/Unix-Like)作業系統背景中執行的行程,無法被使用者直接操作或控制。這些 Daemon 可能是個 Server 在等待與處理 Client 端的請求,也可能是系統的維護程式。

行程在執行過程中將自己轉換為 daemon 一般而言要經過以下幾個步驟:

  • fork() 後終止父行程,和呼叫的終端機(TTY)脫離關係
  • setsid(), 成為會話組長(session leader)
  • 忽略 SIGHUP 信號
  • 再一次 fork() 並終止父行程
  • 變更工作目錄(working directory)設定為根目錄(/)
  • 將 umask 權限設置為 0
  • 關閉所有檔案(file description),包含標準輸入,輸出與錯誤輸出(std in, std out and std err)。
  • 將訊息記錄於log

以下簡單的程式修改自 Richard Stevens 書中的範例。

#include <stdlib.h>
#include <syslog.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#define MAXFD   64

void
daemon_init(const char *pname, int facility)
{
    int     i;
    pid_t   pid;

    if ( (pid = fork()) != 0)
        exit(0);            /* parent terminates */

    /* 1st child continues */
    setsid();               /* become session leader */

    signal(SIGHUP, SIG_IGN);
    if ( (pid = fork()) != 0)
        exit(0);            /* 1st child terminates */

    /* 2nd child continues */
    chdir("/");             /* change working directory */

    umask(0);               /* clear our file mode creation mask */

    for (i=0; i<MAXFD; i++)
        close(i);

    openlog(pname, LOG_PID, facility);
}

int main()
{
    int ii = 10;
    daemon_init("TEST", 0);

    while(ii) {
        syslog(LOG_INFO, "daemon example ... %d", ii--);
        sleep(10);
    }

    exit(0);
}

即便現在 Linux 標準函式庫已經有函式 int daemon(int nochdir, int noclose); 可以經由呼叫後輕鬆的轉換為 daemon 程式。但基於要了解箇中原理與運用的靈活性,還是建議自己寫寫比較踏實。

###延伸閱讀

  • Unix network programming. volume1. 2/e – Richard Stevens
  • Linux Daemon Writing HOWTO

书籍推荐