創建 Daemon 程式

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

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

  1. fork() 後終止父行程,和呼叫的終端機(TTY)脫離關係
  2. setsid(), 成為會話組長(session leader)
  3. 忽略 SIGHUP 信號
  4. 再一次 fork() 並終止父行程
  5. 變更工作目錄(working directory)設定為根目錄(/)
  6. 將 umask 權限設置為 0
  7. 關閉所有檔案(file description),包含標準輸入,輸出與錯誤輸出(std in, std out and std err)。
  8. 將訊息記錄於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 程式。但基於要了解箇中原理與運用的靈活性,還是建議自己寫寫比較踏實。

 

延伸閱讀

1 則迴響於《創建 Daemon 程式

  1. 這邊好像有點問題,"和呼叫的終端機(TTY)脫離關係" 這個是跟 setsid 有關才對,fork 是避免zombie,另外還有setsid的process不能是process group leader的這兩個原因。

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *


九 − = 1

你可以使用這些 HTML 標籤與屬性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>