守護進程的設計與實現

轉載:http://blog.csdn.net/wanxiao009/article/details/5532929


守護進程是Linux中的後臺服務進程,一般都是在後臺運行的,它的生存期比較長。一般都是系統自舉時啓動,系統關閉時終止。

在Linux中,有一個系統與用戶交互的界面,成爲終端,很多進程的啓動和停止都與終端有很大的關係,一般我們在Linux下編寫的代碼都是在終端下執行或者停止的,但是守護進程突破了這種限制,它從被執行的時候開始運轉,直到系統關閉時才結束,用這種方法,可以爲我們的系統提供多種服務,所以是十分重要的。

要編寫一個守護進程一定要掌握守護進程的編程規則,以免出現一些不需要的交互作用,這裏交互作用的意思個人理解就是一個多個守護進程或進程之間存在一定的關係,從而在執行的時候影響到其他進程,應該理解是:每個守護進程之間都是透明的。

規則:

1.              調用umask將文件模式創建屏蔽字設爲0. 理由:繼承的文件模式有可能有所限制,導致某些讀寫權限的不可訪問

2.              調用fork,然後是父進程退出。理由:實際上是做到了進程與終端的脫離,父進程執行後被關閉,子進程後臺運行。

3.              在子進程裏創建一個新的會話。調用函數爲setsid。理由:守護進程需要完全脫離父進程的關係,包括進程組和會話的控制,個人理解就是子進程完全自立門戶的一個過程。

4.              將工作目錄更改爲根目錄。理由:父進程工作目錄在進程運行中是不能卸載的,修改工作目錄的目的是爲了守護進程在其他目錄下也能更好的工作,避免不必要的麻煩

5.              關閉不需要的文件描述符。理解:子進程繼承到了父進程的文件描述符,當然這些是多餘的,爲了節省資源,關閉。

 

 

守護進程的出錯記錄

       守護進程不像普通程序,在調試的時候可以使用gdb或是在編譯的時候出現在終端上的報錯原因和行號,所以在編寫守護進程的時候出錯處理就變得十分重要。

     所以守護進程就有它自己的出錯記錄方式,一般有三種方式產生出錯日誌:

1.  內核例程可以調用log函數,但是這一方式牽涉到內核,暫不研究

2.  調用syslog函數產生日誌消息,這個是我們要掌握的

3.  通過TCP/IP鏈接的進程可以將日誌消息發送到UDP端口514,需要網絡編程,也不討論

 

關於第二種方式的討論

      Syslog是Linux中的系統日誌管理服務,該機制決定的不同種類的信息發向何處,比如緊急消息就發送給系統管理員並在控制檯顯示,警告消息則發送到一個記錄文件中。該機制提供了3個函數接口,分別是openlog,syslog和closelog.

 

關於理論方面也就這些,用代碼來實現一個守護進程的例程纔是方便理解的

       代碼中先建立起來一個守護進程,然後再該守護進程中建立一個子進程,該子進程先暫停10S然後自動退出,並且由守護進程收集其子進程的退出消息。其中子進程和守護進程的退出消息都在/var/log/message中輸出。子進程退出後,守護進程循環停止,其時間間隔爲10S。


#include <stdio.h>  
#include <stdlib.h>  
#include <sys/types.h>  
#include <unistd.h>  
#include <sys/wait.h>  
#include <syslog.h>  
  
#define MAXFILE 65535  
  
int create_daemon()  
{  
    int i ;  
    setsid();  
    chdir("/");  
    umask(0);  
    for(i = 0 ;i < MAXFILE ; i++){  
        close (i);  
    }  
  
}  
  
int main(int argc , char **argv)  
{  
    pid_t child1,child2;  
  
    child1 = fork();  
    if(child1 < 0 )  
        perror("fork error");  
      
    else if(child1 > 0)  
        exit(1);  
      
    create_daemon();   
  
    child2 = fork();  
    if(child2 < 0)  
        perror("fork error");  
      
    else if(child2 == 0){  
        syslog(LOG_INFO,"child2 will sleep for 10s");  
        sleep(10);  
  
        syslog(LOG_INFO , "child2 will exit");  
        exit(0);  
    }  
    else{  
        waitpid(child2,NULL,0);  
        syslog(LOG_INFO,"child1 noticed that child2 has exited");  
  
        closelog();  
  
        while(1){  
            sleep(10);  
        }  
    }  
    return 0;  
}  



    編譯 運行 進程查看

[root@localhost daemon]# gcc daemon.c 
[root@localhost daemon]# ./a.out 
[root@localhost daemon]# ps -ef|grep a.out 
root      1322     1  0 10:31 ?        00:00:00 ./a.out
root      1339  2790  0 10:31 pts/1    00:00:00 grep a.out
[root@localhost daemon]# cat /var/log/messages

 

Apr 27 10:31:27 localhost a.out: child2 will sleep for 10s
Apr 27 10:31:37 localhost a.out: child2 will exit
Apr 27 10:31:37 localhost a.out: child1 noticed that child2 has exited

 

 

參考書籍 《UNIX環境高級編程》 《嵌入式Linux應用程序開發詳解》


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