本次將記錄有關Linux守護進程的概念及其用法。
守護進程是我們通常說的Daemon進程,是後台服務進程,通常獨立於控制終端並周期性地執行任務或等待事件。守護進程常在系統引導裝入時啟動,在系統關閉時終止。在Linux中,每一個從終端啟動並執行進程都會依附於這個終端,當終端被關閉時,進程會自動關閉。但是守護進程就能突破這種限制,如果想讓某個進程不因為使用者或終端的變化而受到影響,則應該把這個進程變成守護進程。
編寫守護進程的步驟:
1.建立子進程,退出父進程
退出父進程後,子進程變成孤兒進程,由1號進程(init進程)收養。
關鍵代碼如下:
pid = fork();
if (pid > 0)
{
exit(0);
}
2.在子進程中建立新會話
先介紹兩個概念:進程組和交談群組
進程組是一個或多個進程的集合,由進程組ID唯一標識。每個進程組都有組長進程,組長的進程號就是進程組ID,且該進程組ID不會因組長進場的退出而受到影響。
交談群組是一個或多個進程組的集合,通常來說,會話始於使用者登入,終止於使用者退出。
接下來重點介紹setsid函數,它是建立守護進程的最重要一環。setsid函數用於建立一個新的會話,並擔任交談群組的組長。setsid函數的作用有3點
(1)讓進程擺脫原交談群組的控制
(2)讓進程擺脫原進程組的控制
(3)讓進程擺脫原控制終端的控制
為什麼要執行setsid函數呢?原因是,之前我們利用fork函數建立子進程的時候,把父進程的交談群組、進程組、控制終端等資訊都複製過來了,雖然父進程退出了,但是子進程還是會保留這些資訊的。所以我們需要執行setsid函數來改變這些資訊,進行“越獄”。
prototype : pid_t setsid(void)
return : 該進程組ID —— success
-1 —— failure
3.改變目前的目錄為根目錄
一般子進程繼承父進程的目前的目錄環境下的檔案系統是不能卸載的,對以後使用可能會有麻煩(如系統需要進入單一使用者模式)。通常的做法是把根目錄“/”作為守護進程的當前工作目錄。
4.重設檔案許可權掩碼
子進程繼承父進程的許可權掩碼,帶來不便,一般把掩碼重設為0,較為靈活。
5.關閉檔案描述符
子進程會從父進程那裡繼承一些已經開啟了的檔案,它們在消耗著系統資源。由於子進程已經脫離了終端的控制,檔案描述符為0、1、2的檔案(輸入、輸出、報錯)也失去了存在價值,應被關閉。
摘自《嵌入式Linux應用程式開發詳解》的常式如下:
#include <stdio.h><br />#include <stdlib.h><br />#include <string.h><br />#include <fcntl.h><br />#include <sys/types.h><br />#include <unistd.h><br />#include <sys/wait.h></p><p>#define MAXFILE 65535</p><p>int main(void)<br />{<br /> pid_t pc;<br /> int i, fd, len;<br /> char *buf = "This is a Dameon/n";<br /> len = strlen(buf);</p><p> pc = fork(); //第一步<br /> if (pc < 0)<br /> {<br /> printf("error fork/n");<br /> exit(1);<br /> }<br /> else if (pc > 0)<br /> {<br /> exit(0);<br /> }</p><p> setsid(); //子進程在運行,第二步<br /> chdir("/"); //第三步<br /> umask(0); //第四步<br /> for (i = 0; i < MAXFILE; i++) //建立守護進程完成<br /> {<br /> close(i);<br /> }</p><p> for (;;)<br /> { //以下正式進行守護進程工作,每隔10s往dameon.log寫入一條語句<br /> if((fd = open("/tmp/dameon.log", O_CREAT | O_WRONLY | O_APPEND, 0600)) < 0)<br /> {<br /> perror("open");<br /> exit(1);<br /> }</p><p> write(fd, buf, len+1);<br /> close(fd);<br /> sleep(10);<br /> }<br />}
編譯運行後,執行tail -f /tmp/dameon.log 即可查詢到該檔案周期性更新的效果。
執行 ps -ef | grep daemon 即能查詢到守護進程的狀態。
本節完。