守護進程

守護進程:Linux系統啓動時會啓動很多系統服務進程,這些系統服務進程沒有控制終端,不能直接和用戶交互。其它進程都是在用戶登錄或運行程序時創建,在運行結束或用戶註銷時終止,但系統服務進程不受用戶登錄註銷的影響,它們一直在運行着,這種進程稱作守護進程;

守護進程也稱精靈進程(Daemon),是運行在後臺的一種特殊進程。它獨立於控制終端並且週期性地執行某種任務或等待處理某些發生的事件。守護進程是一種很有用的進程。Linux的大多數服務器就是用守護進程實現的,比如,Internet服務器inetd,Web服務器httpd等,同時,守護進程完成許多系統任務,比如,作業規劃進程crond等。


特點如下:

1.守護進程是服務器運行的載體,一般網絡服務器必須以守護進程實現;

2.它命名週期只要提供服務,則是7*24時一直運行;

3.它與終端,用戶登錄與註銷無任何關係,其自成進程組自成會話;

4.它的父進程id==1,其爲孤兒進程;

5.其命名都以d結尾.

可用以下命令查看系統中的守護進程:

ps axj | grep -E 'd$'

用戶自己創建守護進程步驟:

1. 調用umask將文件模式創建屏蔽字設置爲0(能夠使用戶自定義權限設置正確,防止其與系統文件權限關聯).
2. 調用fork函數,父進程退出(exit)(若組長進程調用setsid()函數時,則不會成功,所以fork()子進程,父進程退出,從而保證當前運行的進程不是第一個運行的進程也就不爲組長進程).

3.調用setsid創建一個新會話。setsid會導致:1)調用進程成爲新會話的首進程;  2)調用進程成爲一個進程組的組長進程 ;3)調用進程沒有控制終端.(再次fork一次,保證daemon進程,之後不會打開tty設備)

4.將當前工作目錄更改爲根目錄(防止目錄變更).
5. 關閉不在需要的文件描述符(此時已於控制終端無關,不需要0、1、2等標準輸入輸出文件).
6. 忽略SIGCHLD信號.


介紹以上setsid函數:

#include <unistd.h>
pid_t setsid(void);    
返回值:調用成功時返回新創建的會話的id(即當前進程的id),出錯返回-1.

成功調用該函數的結果是:
1. 創建一個新的會話(Session ),當前進程成爲Session Leader,當前進程的id就是Session的id.
2. 創建一個新的進程組,當前進程成爲進程組的Leader,當前進程的id就是進程組的id.
3. 如果當前進程原本有一個控制終端,則它與這個控制終端脫離關係,成爲一個沒有控制終端的進程(所謂脫離控制終端是指,原來的控制終端仍然是打開的,仍然可以讀寫,但只是一個普通的打開文件已不是控制終端).

注意:調用這個函數之前,當前進程不允許是進程組的Leader,否則該函數返回-1,所以用fork()創建子進程即可以解決.

代碼實現:

#include <unistd.h>
#include <signal.h>
#include <stdlib.h>

void mydaemon()
{
	umask(0);    //設置權限 

	if(fork()>0)  //father    //fork父進程退出 
	{
		exit(1);
	}

	setsid();    //調用創建會話函數 

	chdir("/");   //更改目錄 

	close(0);     //關閉文件描述符 
	close(1);
	close(2);

	signal(SIGCHLD,SIG_IGN);    //忽略SIGCHLD函數 
} 
int main()
{
	mydaemon();
	//daemon(0,0);   //系統函數創建守護進程 

	while(1)
	{}
	return 0;
}

結果如下:


在系統文件proc中保存CPU進程內存的信息,可查看此守護進程當前工作目錄:


文件描述符:



也可以直接使用系統提供的函數創建守護進程:

int daemon(int nochdir,int noclode);
參數:若兩個參數都設爲0,則將當前工作目錄改爲根目錄下,文件描述符則寫入/dev/null下(/dev/null,Linux下黑洞,寫入這裏面的內容都會被丟棄).

結果如下:





在實現守護進程中,有時會fork()兩次,其與fork()一次的區別在於,fork()一次守護進程的pid、gid、sid都是相同的,表示當前進程自成會話自成進程組,fork()兩次,其pid與gid、sid不同的,表明此守護進程是屬於某一個會話與進程組的。雖然fork()一次使守護進程關閉了與終端聯繫,但是後期若誤操作再次打開終端(或與某一個終端關聯),而只有會話首進程可以打開終端設備,所以若在fork()一次,將父進程退出,再次fork子進程作爲守護進程繼續運行,但其已不是會話首進程也將不能在打開終端,所以兩次會使守護進程更加安全。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章