轉自:http://blog.csdn.net/analogous_love/article/details/52806722
一、引言 Daemon程式是一直啟動並執行服務端程式,又稱為守護進程。
本文介紹了在Linux下編寫Daemon程式的步驟,並給出了例子程式。
二、Daemon程式簡介 Daemon是長時間啟動並執行進程,通常在系統啟動後就運行,在系統關閉時才結束。一般說Daemon程式在後台運行,是因為它沒有控制終端,無法和前台的使用者互動。Daemon程式一般都作為服務程式使用,等待用戶端程式與它通訊。我們也把啟動並執行Daemon程式稱作守護進程。
三、Daemon程式編寫規則
編寫Daemon程式有一些基本的規則,以避免不必要的麻煩。
1、首先是程式運行後調用fork,並讓父進程退出。子進程獲得一個新的進程ID,但繼承了父進程的進程組ID。
2、調用setsid建立一個新的session,使自己成為新session和新進程組的leader,並使進程沒有控制終端(tty)。
3、改變當前工作目錄至根目錄,以免影響可負載檔案系統。或者也可以改變到某些特定的目錄。
4、設定檔案建立mask為0,避免建立檔案時許可權的影響。
5、關閉不需要的開啟檔案描述符。因為Daemon程式在後台執行,不需要於終端互動,通常就關閉STDIN、STDOUT和STDERR。其它根據實際情況處理。
另一個問題是Daemon程式不能和終端互動,也就無法使用printf方法輸出資訊了。我們可以使用syslog機制來實現資訊的輸出,方便程式的調試。在使用syslog前需要首先啟動syslogd程式,關於syslogd程式的使用請參考它的man page,或相關文檔,我們就不在這裡討論了。
四、一個Daemon程式的例子 編譯運行環境為Redhat Linux 8.0。
我們建立一個daemontest.c程式,檔案內容如下:
int daemon_init(void){ pid_t pid; if ((pid = fork()) < 0) return(-1); else if (pid != 0) exit(0); /* parent exit */ /* child continues */ setsid(); /* become session leader */ chdir("/"); /* change working directory */ umask(0); /* clear file mode creation mask */ close(0); /* close stdin */ close(1); /* close stdout */ close(2); /* close stderr */ return(0);}void sig_term(int signo){ if (signo == SIGTERM) /* catched signal sent by kill(1) command */ { syslog(LOG_INFO, "program terminated."); closelog(); exit(0); }}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
在實際項目中我是這麼做的:
if (isdaemon) { int pid; signal(SIGCHLD, SIG_IGN); //1)在父進程中,fork返回新建立子進程的進程ID; //2)在子進程中,fork返回0; //3)如果出現錯誤,fork返回一個負值; pid = fork(); if (pid < 0) { perror("fork"); exit(-1); } //父進程退出,子進程獨立運行 else if (pid > 0) { exit(0); } //之前parent和child運行在同一個session裡,parent是會話(session)的領頭進程, //parent進程作為會話的領頭進程,如果exit結束執行的話,那麼子進程會成為孤兒進程,並被init收養。 //執行setsid()之後,child將重新獲得一個新的會話(session)id。 //這時parent退出之後,將不會影響到child了。 setsid(); int fd; fd = open("/dev/null",O_RDWR,0); if (fd != -1) { dup2(fd,STDIN_FILENO); dup2(fd,STDOUT_FILENO); dup2(fd,STDERR_FILENO); } if (fd > 2) close(fd); }