一、守護進程是什么
守護進程是生存期很長的一種進程,可以說它是7*24小時工作的。(什么是7*24,一周7天,每天24小時,這不就是一年365天一直在工作嘛,還搞的這么詼諧,哈哈)。它們常常在系統引導裝入時啟動,僅在系統關閉時才終止。因為它們沒有控制終端,所以說它們是在后臺運行的,而且它沒法直接和用戶交互。當然在后臺運行的可不一定是守護進程哦。Unix下有很多守護進程,執行日常事務。守護進程是一種很有用的進程,Linux下的很多服務器大多是用守護進程實現的。比如Internet服務器inetd,Web服務器httpd等。
守護進程還有一個特點:其它進程都是在用戶登錄或運行程序時創建,在運行結束或用戶注銷時終止,但系統服務進程不受用戶登錄注銷的影響,它們一直在運行著。
我們用ps -axj來查看系統中的進程。-a顯示由其他用戶所擁有的進程的狀態,-x顯示沒有控制終端的進程,-j顯示與作業有關的信息(進程組ID,會話ID,控制終端,終端進程組ID)。守護進程通常以d為結尾。
由上述的進程中,TPGID為-1的都是沒有控制終端的進程,也是守護進程。還有像COMMAND那一列中,用[]括起來的進程名,都表示內核線程。這些線程在內核里創建,沒有用戶空間代碼,因此沒有程序文件名和命令行,以k開頭,表示Kernel。它自成進程組,自成會話。
進程1通常是init,它是一個系統守護進程。
二、創建守護進程
我們寫一個mydaemon:
步驟哈: 1.創建守護進程首先得,調用umask來將文件模式創建屏蔽字設置為0。
2.調用fork,使父進程退出。因為在這里,后面使用setid不允許進程為進程組id,因此得先將父進程exit。
3.調用setid創建一個新會話,成為會話首進程,成為進程組組長,沒有控制終端。這就是守護進程的特點吧。
4.將當前的工作目錄改為根目錄。你想想,如果你將守護進程的工作目錄設置為當前工作目錄而非根目錄,那么如果將這個目錄刪除后,就會導致嚴重的丟失問題。你的那個目錄將不能被刪除。
5.關閉不再需要的文件描述符。
守護進程實現:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
void mydaemon()
{umask(0 );if (fork() <= 0 ){}else {exit (0 );}setsid();signal(SIGCHLD,SIG_IGN);close(0 );close(1 );close(2 );chdir("/" );}int main()
{mydaemon();
while (1 );return 0 ;
}
運行結果:
這樣一個守護進程就寫好啦。當然庫里邊也實現了一個守護進程,daemon函數。
int daemon(int nochdir, int noclose);
這里nochdir表示不改變當前守護進程的目錄,noclose表示不關閉進程文件描述符。
當前我們是把工作目錄修改了,所以:
當我們都設置為0時,daemon(0,0);說明修改; 當我們都設置為1時,daemon(1,1);說明不修改;
三、為什么創建守護進程時有人fork兩次?
第二次fork的作用:雖然當前關閉了和終端的聯系,但是后期可能會誤操作打開了終端。只有會話首進程能打開終端設備,也就是再fork一次,再把父進程退出,再次fork的子進程作為守護進程繼續運行,保證了該精靈進程不是會話的首進程,第二次不是必須的,是可選的,市面上有些開源項目也是fork一次。(再次fork一次,保證daemon進程,之后不會打開tty設備)