linux守護程序小結
建立守護程序步驟:
-
建立子程序父程序退出, 讓這個子程序變成孤兒程序, 防止產生殭屍程序
-
在子程序中建立新會話
setsid函式用於建立一個新的會話,並使得當前程序成為新會話組的組長
setsid函式能夠使程序完全獨立出來,從
而脫離所有其他程序的控制。 -
改變當前目錄為根目錄
防止當前目錄被刪除後, 不存在了, 引發程式的錯誤
chdir();
通常的做法是讓“/”或”/tmp”作為守護程序的當前工作目錄 。 -
重設檔案許可權掩碼
umask(0)
建立檔案許可權 = mode & ~umask(0)
= 0664 & 0777
= 0664
umask(0777)
建立檔案許可權 = mode & ~umask(0777)
= 0664 & 0000
= 0000
umask(0113)
建立檔案許可權 = mode & ~umask(0113) 001 001 011
= 0777 & 0664
= 0664
5.關閉檔案描述符
fdtablesize = getdtablesize();
for (fd = 0; fd < fdtablesize; fd++)
close(fd);
摺疊建立子程序,父程序退出
這是編寫守護程序的第一步。由於守護程序是脫離控制終端的,因此,完成第一步後就會在Shell終端裡造成一程式已經執行完畢的假象。之後的所有工作都在子程序中完成,而使用者在Shell終端裡則可以執行其他命令,從而在形式上做到了與控制終端的脫離。
在Linux中父程序先於子程序退出會造成子程序成為孤兒程序(也稱殭屍程序),而每當系統發現一個孤兒程序時,就會自動由1號程序(init)收養它,這樣,原先的子程序就會變成init程序的子程序。
摺疊在子程序中建立新會話
這個步驟是建立守護程序中最重要的一步,雖然它的實現非常簡單,但它的意義卻非常重大。在這裡使用的是系統函式setsid,在具體介紹setsid之前,首先要了解兩個概念:程序組和會話期
程序組:是一個或多個程序的集合。程序組由程序組ID來唯一標識。除了程序號(PID)之外,程序組ID也是一個程序的必備屬性。每個程序組都有一個組長程序,其組長程序的程序號等於程序組ID。且該程序組ID不會因組長程序的退出而受到影響。
會話週期:會話期是一個或多個程序組的集合。通常,一個會話開始於使用者登入,終止於使用者退出,在此期間該使用者執行的所有程序都屬於這個會話期。
接下來就可以具體介紹setsid的相關內容:
(1)setsid函式作用:
setsid函式用於建立一個新的會話,並擔任該會話組的組長。呼叫setsid有下面的3個作用:
讓程序擺脫原會話的控制
讓程序擺脫原程序組的控制
讓程序擺脫原控制終端的控制
那麼,在建立守護程序時為什麼要呼叫setsid函式呢?由於建立守護程序的第一步呼叫了fork函式來建立子程序,再將父程序退出。由於在呼叫了fork函式時,子程序全盤拷貝了父程序的會話期、程序組、控制終端等,雖然父程序退出了,但會話期、程序組、控制終端等並沒有改變,因此,這還不是真正意義上的獨立開來,而setsid函式能夠使程序完全獨立出來,從而擺脫其他程序的控制。
摺疊改變當前目錄為根目錄
這一步也是必要的步驟。使用fork建立的子程序繼承了父程序的當前工作目錄。由於在程序執行中,當前目錄所在的檔案系統(如"/mnt/usb")是不能解除安裝的,這對以後的使用會造成諸多的麻煩(比如系統由於某種原因要進入單使用者模式)。因此,通常的做法是讓"/"作為守護程序的當前工作目錄,這樣就可以避免上述的問題,當然,如有特殊需要,也可以把當前工作目錄換成其他的路徑,如/tmp。改變工作目錄的常見函式式chdir。
摺疊重設檔案許可權掩碼
檔案許可權掩碼是指遮蔽掉檔案許可權中的對應位。比如,有個檔案許可權掩碼是050,它就遮蔽了檔案組擁有者的可讀與可執行許可權。由於使用fork函式新建的子程序繼承了父程序的檔案許可權掩碼,這就給該子程序使用檔案帶來了諸多的麻煩。因此,把檔案許可權掩碼設定為0,可以大大增強該守護程序的靈活性。設定檔案許可權掩碼的函式是umask。在這裡,通常的使用方法為umask(0)。
摺疊關閉檔案描述符
同文件許可權碼一樣,用fork函式新建的子程序會從父程序那裡繼承一些已經打開了的檔案。這些被開啟的檔案可能永遠不會被守護程序讀寫,但它們一樣消耗系統資源,而且可能導致所在的檔案系統無法卸下。
在上面的第二步之後,守護程序已經與所屬的控制終端失去了聯絡。因此從終端輸入的字元不可能達到守護程序,守護程序中用常規方法(如printf)輸出的字元也不可能在終端上顯示出來。所以,檔案描述符為0、1和2 的3個檔案(常說的輸入、輸出和報錯)已經失去了存在的價值,也應被關閉。通常按如下方式關閉檔案描述符:
===============================
for(i=0;i<MAXFILE;i++)
close(i);
===============================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char * argv[])
{
int data = 100;
int fd;
int fdtablesize ;
pid_t pid;
pid = fork();
if(pid < 0)
{
perror("fork");
exit(-1);
}
else if(pid > 0) // parent process
{
exit(0);
}
setsid();
chdir("/tmp");
umask(0);
fdtablesize = getdtablesize();
for(fd = 0;fd< fdtablesize;fd++)
{
close(fd);
}
while(1)
{
system("date >>log.txt");
sleep(1);
}
return 0;
}
這是簡單的守護程序。 領卓教育