UNIX環境高級編程 第十三章:守護進程

守護進程(daemon)是生存期長的一種進程。它們常常在系統引導裝入時啓動,僅在系統關閉時才終止(生存期)。
因爲它們沒有控制終端,所以說它們時在後頭運行的。UNIX系統有很多守護進程,它們執行日常事務活動。
本章將說明守護進程的結構,以及如何編寫守護進程程序。因爲守護進程沒有控制終端,我們需要了解在出現問題時,daemon如何報告出錯情況。

1. 守護進程的特徵

先來看看一些常用的系統守護進程,以及它們是怎樣和進程組、控制終端和會話這三個概論相關聯的。
ps -axj
-a顯示由其他用戶所擁有的進程狀態(UNIX爲多用戶系統)
-x顯示沒有控制終端的進程;
-j顯示與作業有關的信息
PPID爲0的進程通常是內核進程,它們作爲系統引導裝入過程的一部分而啓動。(init是一個例外,它是一個由內核在引導裝入時啓動的用戶層次的命令)
內核進程是特殊的,通常存在於系統的整個生命週期中。它們以超級用戶特權運行,無控制終端、無命令行。
在ps輸出實例中,內核守護進程的名字出現在方框中,很多形式爲’k*d’的進程其中‘k’指kernel,‘d’指daemon。
對於需要在進程上下文執行工作但卻不被用戶層進程上下文調用的每一個內核組件,通常有它自己的內核守護進程。

2. 編程規則

在編寫守護進程程序時要遵循一些基本規則,以防止產生不必要的交換作用。
(1)首先要做的是調用umask將文件模式創建屏蔽字(文件權限用) 設置爲一個已知的值(通常是0)。由繼承得來的文件模式創建屏蔽字可能會被設置爲拒絕某些權限。
(2)調用fork,然後使父進程exit。實現了:第一,如果該守護進程是作爲一條簡單的shell命令啓動的,那麼父進程終止會讓shell認爲這條命令已經執行完畢。第二,雖然子進程繼承了父進程的進程組ID,但獲得了一個新的進程ID,這就保證了子進程不是一個進程組的組長進程。
(3)調用setsid創建一個會話。然後使調用進程稱爲新會話的首進程,稱爲一個新進程組的組長進程,沒有控制終端。
(4)將當前工作目錄更改爲根目錄。從父進程繼承過來的當前工作目錄可能在一個掛載的文件系統中。因爲守護進程一直存在,那麼該文件系統就不能被卸載。
(5)關閉不再需要的文件描述符。

3. 出錯記錄

守護進程存在的一個問題是如何處理出錯消息。因爲它本身就不應該有控制終端,所以不能只是簡單地寫到標準出錯上。我們不希望守護進程使用控制檯設備,因爲很多工作站的控制檯設備都運行着一個窗口系統,也不會希望每個守護進程都將出錯消息寫到單獨的文件中,管理這些文件很費事。所以需要一個集中的守護進程出錯記錄設施。

BSD的syslog設施得到了廣泛的應用,大多數守護進程都使用這一設施。
守護進程在啓動時讀一個配置文件,其文件名一般爲/etc/syslog.conf,該文件決定了不同種類的消息應送向何處。守護進程記錄日誌消息的實施是/dev/log,其接口是syslog函數:

#include <syslog.h>
void openlog(const char *ident,int optipn,int facility);
void syslog(int priority,const char *format,...);
void closelog(void);
int setlogmask(int maskpri);//用於設置進程的記錄優先級屏蔽字。

大多數syslog實現將消息短時間處於隊列中。如果在此段時間中有重複消息達到,那麼syslog守護進程不會把它記錄到日誌記錄中,而是會打印輸出一條類似“上一條消息重複了N此”的消息。

4. 單實例守護進程

爲了正常運作,某些守護進程(不是所有的都必須)會實現爲:在任意時刻只運行該守護進程的一個副本。
文件和記錄鎖機制爲這一種方法提供了基礎,該方法保障一個守護進程只有一個副本在運行。如果每一個守護進程創建一個固定名字的文件,並在該文件的整體上加一把鎖,那麼只允許創建一把這樣的鎖。在此後創建寫鎖的嘗試都會失敗,這向後續守護進程副本指明已有一個副本正在運行。

5. 守護進程的慣例

在UNIX系統中,守護進程遵循下列通用慣例:
(1)若守護進程使用鎖文件,那麼該文件通常存儲在/var/run目錄中。然而需要注意的是,守護進程可能需要具有超級用戶權限才能在此目錄下創建文件。鎖文件的名字通常是name.pid。
(2)若守護進程支持配置選項,那麼配置文件通常存放在/etc目錄中。配置文件的名字通常是name.conf。
(3)守護進程可以用命令行啓動,但通常他們是由系統初始化腳本之一(/etc/rc*或/etc/init.d/..)啓動的。如果在守護進程終止時,應當自動地重新啓動它,則我們可以在/etc/inittab(爲init進程的配置文件)中爲該守護進程包括respawn記錄項,這樣init就將重新啓動該守護進程。
(4)若一個守護進程有一個配置文件,那麼該守護進程啓動時會讀該文件,但在此之後一般就不會再查看它。若某個管理員更改了配置文件,那麼該守護進程可能需要配停止,然後再啓動,以使配置文件的更改生效。爲了避免此種麻煩,某些守護進程將捕捉SIGHUP信號,當他們接受到該信號時,重新讀配置文件。

6. 客戶進程-服務器進程模型

守護進程常常用作服務器進程。確實,我們可以稱syslogd進程爲服務器進程,用戶進程(客戶進程)用UNIX域數據報套接字向其發送消息。
一般而言,服務器進程等待客戶進程與其聯繫,提出某種服務類型的請求。例如,syslogd服務器進程提供的服務是將一條出錯消息記錄到日誌文件中。
在服務器進程中調用fork然後exec另一個程序來向客戶進程提供服務是很常見的。這些服務器進程通常管理着多個文件描述符:通信端點、配置文件、日誌文件和類似的文件。

小結:

(1)在大多數UNIX系統中,守護進程是一直運行的。
(2)爲了初始化我們自己的進程,使之作爲守護進程運行,需要謹慎的思索並理解第9章所說明的進程之間的關係。
(3)因爲守護進程沒有控制終端,本章還說明了守護進程記錄出錯消息的幾種方法。
(4)還討論了守護進程遵循的若干慣例,給出了幾個如何實現慣例的實例。

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