守護進程代碼過程概要

(一)、守護進程的特徵

   #ps  -axj  其中:-a 顯示所有用戶所擁有的進程的狀態

                              -x 顯示沒有控制終端的進程狀態

                              -j 顯示與作業相關的的信息:會話ID、進程組ID、控制終端以及終端進程組ID

(二)守護進程的編程規則

(1)、編程規則

1.調用umask()將文件模式創建屏蔽字設置爲0.(文件權限——不要變更程序的初始文件權限mode

    由繼承提來的文件模式創建屏蔽字可能會拒絕設置某些權限。例如,若守護進程要創建一個組可讀、寫的文件,而繼承的文件模式創建屏蔽字可能屏蔽了這兩種權限,於是所要求的組可讀、寫就不能起作用。

例:umask(0);mode與上umask反碼

2.調用fork(),產生一個子進程,然後使父進程退出(exit),子進程變爲孤兒進程(init進程的子進程)

這樣可以實現:

  1)、如果該守護進程是作爲一條簡單shell命令啓動的,那麼父進程終止使得shell認爲這條命令已經執行完畢(騙了一下os)

  2)、子進程繼承了父進程組ID,但具有一個新的進程ID,這就保證了子進程不是一個進程組的組長進程

if ((pid = fork()) < 0)   perror("%s: can't fork");

else if (pid != 0)       exit(0);           /* parent */

3. 調用setsid()以創建一個新會話(因爲父進程退出了,父進程的會話也退出了)

這樣可以實現:  1)、成爲新會話的首進程

                2)、成爲一個新進程組的組長進程

                3)、沒有終端控制

例:setsid();

4.將當前的工作目錄更改爲根目錄

從父進程處繼承過來的當前工作目錄可能在一個裝配文件系統中。因爲守護進程通常在系統再引導之前是一直存在的,所以如果守護進程的當前工作目錄在一個裝配文件系統中,那麼該文件系統就不能被umount,這與裝配文件系統的原意不符

 if (chdir("/")< 0)     perror("can't changedirectory to /");

5、關閉不再需要的文件描述符(守護進程無輸入輸出,文件描述符繼承自父進程,守護進程不需要,全部關閉

這使守護進程不再持有從其父進程繼承過來的某些文件描述符(父進程可能是shell進程,或某個其它進程),可以使用getrlimit()函數來判定最高文件描述符值,並關閉直到該值的所有描述符

Shell指令:#ulimit  -a

 

if (rl.rlim_max == RLIM_INFINITY)        rl.rlim_max = 1024;//os只允許一個進程打開1024個文件

for (i = 0; i < rl.rlim_max; i++)    close(i);//系統調用

 

補充:資源限制

系統資源的限制可由getrlimit讀取,由setrlimit設置

#include <sys/resource.h>

int getrlimit(int resource, struct rlimit*r_limit);

int setrlimit(int resource, const structrlimit *r_limit);

其中:struct rlimit定義於sys/resource.h,至少包括下列兩個成員

      {  rlim_t  rlim_cur;    當前的軟限制(當前文件打開數>1024時,發出警告)

        rlim_t rlim_max;    硬限制(當前文件打開數>1024時,由OS殺死進程)

}

rlim_t是一個整數類型用於描述資源級別(typdefunsigned int rlim_t)

通常soft limit是一建議限制,意味着不應超越,如果超越會引起庫函數返回錯誤

    Hard limit是硬性限制,若超越意味着將導致系統發送信號以終結程序的運行

例:若超越CPU時間,將導致內核發送SIGXCPU

    若超越數據大小限制,將導致內核發送SIGSEGV

一個程序可以設置軟限制,一般軟限制小於hard limit

僅有具有superuser privileges的程序可以增大hard limit

 

可以被限制的資源被定義於sys/resource.h中,包括:

 

CPU使用量

數據段大小

文件大小(<4G)

打開文件數(一般1024)

每個進程用的堆棧大小

每個進程用的地   址空間,一般小於4G


返回值:Successful   0

              error       -1

6、某些守護進程打開/dev/null(空洞設備)使其具有文件描述符0stdin)、1stdout)和2stderr

這樣任何一個試圖讀標準輸入、寫標準輸出或標準出錯的庫例程都不會產生任何效果

因爲守護進程並不與終端設備相關聯,所以不能在終端設備上顯示其輸出,也無處從交互用戶那裏接收輸入。

 fd0= open("/dev/null", O_RDWR);// 0stdin)、1stdout)和2stderr)全部放進/dev/null(空洞設備)中

       fd1 = dup(0);

       fd2 = dup(0);

(2)、syslog設施(Linux/UNIX:消息寫入syslog設施——寫入log文件中)

守護進程存在的一個問題是如何處理出錯消息。因爲它本就不應該有控制終端,所以不能只是簡單地寫到標準錯誤上。也不希望所有守護進程都寫到控制檯(console)設備上,因爲在很多工作站上控制檯設備都運行着一個窗口系統。也不希望每個守護進程將它自己的出錯消息寫到一個單獨的文件中。所以,需要有一個集中的守護進程出錯記錄設施。BSD的syslog設施得到了廣泛的應用。大多數守護進程都使用這一設施。

有3種產生日誌消息的方法:

1)內核例程可以調用log函數。

    任何一個用戶進程都可以通過打開(open)並讀取(read)  /dev/klog設備來讀取這些消息。

2)大多數用戶進程(守護進程)調用syslog(3)函數來產生日誌消息,這使消息被髮送至UNIX域數據報套接字/dev/log

3)無論一個用戶進程是在此主機上,還是在通過TCP/IP網絡連接到此主機的其它主機上,都可以將日誌消息發向UDP 514端口。注意syslog函數從不產生這些UDP數據報,它們要求產生此日誌消息的進程進行顯式的網絡編程。

通常,syslogd守護進程讀取所有3種格式的日誌消息。此守護進程在啓動時讀一個配置文件---/etc/syslog.conf,該文件決定了不同種類的消息應送向何處

2、syslog設施的接口syslog函數

#include <syslog.h>

void openlog(const  char *ident,  int option,  int facility );   可選

voidsyslog(int priority,  const char *format, ...);              必須

void closelog(void);                                      可選

說明:調用openlog是可選的。如果不調用openlog,則在第一次調用syslog時,自動調用openlog

      調用closelog也是可選的,因爲它只是關閉曾被用於與syslogd守護進程進行通信的描述符

 

void syslog(int priority,  const char *format , ...);              必須

作用:產生一個日誌消息,默認打開/dev/log設備

參數:1)priority參數(級別)是facility和level的組合,它們可選取的值分別列於facility和level中 level值按優先級從最高到最低依次排列

      2)format參數(自定義的格式):

將format參數以及其它所有參數傳到vsprintf函數以便進行格式化。在format中,每個出現的%m字符都先被代換成與errno值對應的出錯消息字符串(strerror)


(四)、實現函數---daemon()

作用:使調用程序run in the background,進程成爲守護進程

函數:#include <unistd.h>//系統調用

           intdaemon(int nochdir, int noclose);

參數:

nochdir  若爲0,daemon()將調用進程的當前目錄更改爲“/ ”

            否則,當前進程的工作目錄無變化

noclose  若爲0,(關)daemon()redirects standard input, standard output and standard error to /dev/null;

            否則 no changes are made to these file descriptors.

返回值  //成功與否的標誌

On success daemon() returns 0.

If an error occurs, daemon() returns -1 andsets errno to any of the errors specified for the  fork  and setsid

發佈了141 篇原創文章 · 獲贊 108 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章