1. 程式人生 > >linux守護程序小結

linux守護程序小結

建立守護程序步驟:

  1. 建立子程序父程序退出, 讓這個子程序變成孤兒程序, 防止產生殭屍程序

  2. 在子程序中建立新會話
    setsid函式用於建立一個新的會話,並使得當前程序成為新會話組的組長
    setsid函式能夠使程序完全獨立出來,從
    而脫離所有其他程序的控制。

  3. 改變當前目錄為根目錄
    防止當前目錄被刪除後, 不存在了, 引發程式的錯誤
    chdir();
    通常的做法是讓“/”或”/tmp”作為守護程序的當前工作目錄 。

  4. 重設檔案許可權掩碼
    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;
}

這是簡單的守護程序。 領卓教育