歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

守護進程

13.1 簡介

守護進程(daemon)是生存期長的一種進程。它們常常在系統引導裝入時啟動,僅在系統關閉時才終止。因為它們沒有控制終端,所以說它們是在後台運行的。UNIX系統有很多守護進程,他們執行日常事務活動。

13.2 守護進程的特征

系統進程依賴於操作系統實現。父進程ID為0的各進程通常是內核進程,它們作為系統引導裝入過程的一部分而啟動。(init是個例外,它是一個由內核在引導裝入時啟動的用戶層次的命令。)內核進程是特殊的,通常存在於系統的整個生命期中。它們以超級用戶特權運行,無控制終端,無命令行。在ps的輸出實例中,內核守護進程的名字出現在方括號中。

對於需要在進程上下文執行工作但卻不被用戶層進程上下文調用的每一個內核組件,通常有它自己的內核守護進程。如Linux中:

2 Kswapd守護進程也稱為內存換頁守護進程。它支持虛擬內存子系統在經過一段時間後將髒頁面慢慢地寫回磁盤來回收這些頁面

2 Flush守護進程在可用內存達到設置的最小阈值時將髒頁面沖洗至磁盤。它也定期地將髒頁面沖洗回磁盤來減少在系統出現故障時發生的數據丟失。多個沖洗守護進程可以同時存在,每個寫回的設備都有一個沖洗守護進程。

2 Sync_supers守護進程定期將文件系統元數據沖洗至磁盤

2 Jdb守護進程幫助實現了ext4文件系統中的日志功能

上面的四個進程是內核守護進程

Init進程是一個系統守護進程,除了其他工作外,主要負責啟動各運行層次特定的系統服務。這些服務通常是它們自己擁有的守護進程的幫助下實現的。

Rpcbind守護進程提供將遠程調用(Remote ProcedureCall,RPC)程序號映射為網絡端口號的服務。Rsyslogd守護進程可以被由管理員啟用的將系統消息記入日志的任何程序使用。可以在一台實際的控制台上打印這些消息,也可以將他們寫到一個文件中。

Inet守護進程,它偵聽系統網絡接口,以便取得來自網絡的對各種網絡服務進程的請求。Nfsd,nfsiod,lockd,rpciod,rpc.idmapd,rpc.statd和rpc.mountd守護進程提供對網絡文件(Network File System,NFS)的支持。

上面的三個是用戶級守護進程

2 Cron守護進程在定期安排的日期和時間執行命令。許多系統管理任務是通過cron每隔一段固定的時間就運行相關程序而得以實現的

2 Atd守護進程與cron類似,它允許用戶在指定的時間執行任務,但是每個任務它只執行一次,而非在定期安排的時間反復執行

2 Cupsd守護進程是個打印假脫機進程,它處理對系統提出的各個打印請求

2 Ssh守護進程提供了安全的遠程登錄和執行設施

注意:大多數的守護進程都以超級用戶(root)特權運行。所有的守護進程都沒有控制終端,其終端名設置為問號。內核守護進程以無控制終端方式啟動。用戶層守護進程缺少控制終端可能是守護進程調用了setsid的結果。大多數用戶層守護進程都是進程組的組長進程以及會話的首進程,而且是這些進程組和會話組和會話中的唯一進程(rsyslogd是一個例外)。最後,應當引起注意的是用戶層守護進程的父進程是init進程。

13.3 編程規則

在編寫守護進程程序時,需要遵循一些基本規則,以防止產生不必要的交互作用。下面先說明這些規則,然後給出一個按照這些規則編寫的函數daemonize。

2 首先要做的是調用umask將文件模式創建屏蔽字設置為一個已知值(通常是0)。由繼承得來的文件模式創建屏蔽字可能會被設置為拒絕默寫權限。如果守護進程要創建文件,那麼他可能要設置特定的權限。如若守護進程要創建組可讀、組可寫的文件,繼承的文件模式創建屏蔽字可能會屏蔽上述兩種權限中的一種,而使其無法發揮作用。另一方面,如果守護進程調用的庫函數創建了文件,那麼將文件模式創建屏蔽字設置為一個限制性更強的值(如007)可能會更明智,因為庫函數可能不允許調用者通過一個顯示的函數參數來設置權限。

2 調用fork,然後使父進程exit。這樣做實現了下面幾點:

n 如果該守護進程是作為一條簡單的shell命令啟動的,那麼父進程終止會讓shell認為這條命令已經執行完畢

n 雖然子進程繼承了父進程的進程組ID,但獲得了一個新的進程ID,這就保證了子進程不是一個進程組的組長進程。這是下面setsid調用的先決條件。

2 調用setsi創建一個新會話。然後執行一些步驟來使調用進程:

n 成為新會話的首進程

n 成為一個新進程組的組長進程

n 沒有控制終端

2 將當前目錄更改為根目錄。從父進程處繼承過來的當前工作目錄可能在一個掛載的文件系統中。因為守護進程通常在系統再引導之前是一直存在的,所以如果守護進程的當前工作目錄在一個掛載文件系統中,那麼該文件系統就不能被卸載。

或者,某些守護進程可能會把當前工作目錄更改到某個指定位置,並在此位置進型他們的全部工作。如,形式打印機假脫機守護進程就可能將其工作目錄更改到他們的spool目錄上。

2 關閉不在需要的文件描述符。這使守護進程不再持有從其父進程繼承來的任何文件描述符(父進程可能是shell進程,或某個其他進程)。可以使用open_max函數或getrlimit函數來斷定最高文件描述符值,並關閉直到該值的所有描述符。

2 某些守護進程打開/dev/null使其具有文件描述符0、1、2,這樣,任何一個試圖讀標准輸入、寫標准輸入或標准錯誤的庫例程都不會產生任何效果。因為守護進程並不與終端設備相關聯,所以其輸出無處顯示,也無處從交互式用戶那裡接收輸入。即使守護進程是從交互式會話啟動的,但是守護進程是在後台運行的,所以登錄會話的終止並不影響守護進程。如果其他用戶在同一終端設備上登錄,則不希望在該終端上見到守護進程的輸出,用戶也不期望他們在終端上的輸入被守護進程讀取。

守護進程在一個孤兒進程組中,它不是會話首進程,因此沒有幾乎被分配到一個控制終端。

13.4 出錯記錄

守護進程存在的一個問題是如何處理出錯消息。因為它本就不應該有控制終端,所以不能只是簡單的寫到標准錯誤上。我們不希望所有守護進程都寫到控制台設備上,因為在很多的工作站上,控制台設備都運行著一個窗口系統。我們也不希望每個守護進程將它自己的出錯信息寫到一個單獨的文件中。對任何一個系統管理人員而言,如果關系哪一個守護進程寫到哪一個記錄文件中並定期地檢查這些文件,那麼一定會使他感到頭痛。故需要一個集中的守護進程出錯記錄設施

自BSD依賴,BSD的syslog設施得到廣泛的應用。大多數守護進程都是用這一設施。

產生日志的方法有3種:

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

2 大多數用戶進程(守護進程)調用syslog(3)函數來產生日志消息。調用相關序列,使消息被發送至UNIX域數據報套接字/dev/log

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

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

13.5 單實例守護進程

為了正常運行,某些守護進程會實現為,在任一時刻只運行該守護進程的一個副本。如這種守護進程可能需要安排它訪問一個設備。對cron守護進程而言,如果同時有多個實例運行,那麼每個副本都可能試圖開始某個預定的操作,於是造成該操作的重復執行,這很可能導致出錯。

如果守護進程需要訪問一個設備,而該設備驅動程序有時會阻止要想多次打開/dev目錄下相應的設備節點的嘗試。這就限制了在一個時刻只能運行守護進程的一個副本。但是如果沒有這種設備可供使用,那麼我們就需要自行處理。

文件和記錄鎖機制為一種方法提供了基礎,該方法保證一個守護進程只有一個副本在運行。如果每一個守護進程創建一個固定名字的文件,並在該文件的整體上加一把鎖,那麼只允許創建一把這樣的鎖。在此之後創建寫鎖的嘗試都會失敗,這向後續守護進程副本指明一個副本正在運行。

文件和記錄鎖提供了一種方便的互斥機制。如果守護進程在一個文件的整體上得到一把寫鎖,那麼在該守護進程終止時,這把鎖將被自動刪除。這就簡化了復原所需的處理,去除了對以前守護進程實例需要進行清理的有關操作。

13.6 守護進程的慣例

在UNIX系統中,守護進程遵循下列慣例。

2 若守護進程使用鎖文件,那麼該文件通常存儲在/var/run目錄中。然而需要注意的是,守護進程可能需要具有超級用戶權限才能在此目錄下創建文件。鎖文件的名字通常是name.pid,其中,name是該守護進程或服務的名字。如cron守護進程鎖文件的名字是/var/run/crond.pid

2 若守護進程支持配置選項,那麼配置文件通常放在/etc目錄中。配置文件的名字通常是name.conf,其中,name是該守護進程或服務的名字。如syslogd守護進程的配置文件通常是/etc/syslog.conf

2 守護進程可用命令行啟動,但通常它們是由系統初始化腳本之一(/etc/rc*或/etc/init.d/*)啟動的。如果在守護進程終止時,應當自動地重新啟動它,則我們可在/etc/inittab中為該守護進程包括respawn記錄項,這樣,init就將重新啟動該守護進程。(假定系統使用System V風格的init命令)

2 若一個守護進程有一個配置文件,那麼當該守護進程啟動時會讀該文件,但在此之後一般就不會在查看它。若某個管理員更改了配置文件,那麼該守護進程可能需要被停止,然後再啟動,以使配置文件的更改生效。為了避免此種麻煩,某些守護進程並不與終端相結合,它們或是無控制終端的會話首進程,或是孤兒進程組的成員,所以守護進程沒有理由期望接受SIGHUP。於是,守護進程可以安全地重復使用SIGHUP。

13.7 客戶進程-服務器進程模型

守護進程常常用作服務器進程。用戶進程(客戶端進程)用UNIX域數據報套接字向其發送消息。

一般而言,服務器進程等待客戶進程與其聯系,提出某種類型的服務要求。

客戶進程與服務器進程通信可以是單向的,也可以是雙向的。單向指:客戶進程向服務器進程發送服務請求後,服務器進程則不向客戶進程回送任何消息。雙向指:客戶進程向服務器進程發送請求,服務器進程則向客戶進程回送應答。

在服務器進程中調用fork然後執行exec另一個程序來向客戶進程提供服務較常見。這些服務器進程通常管理著多個文件描述符:通信端點、配置文件、日志文件和類似的文件。最好的情況下,讓子進程中的這些文件描述符保持打開狀態並無大礙,因為他們很可能不會被子進程中執行的程序所使用,尤其是那些與服務器端無關的程序。最壞的情況下,保持它們的打開狀態會導致安全問題——被執行的程序可能有一些惡意行為,如更改服務器端配置文件或欺騙客戶端程序使其認為正在與服務器端通信,從而獲取未經授權的信息。

解決此問題的一個簡單方法是對所有被執行程序不需要的文件描述符設置執行時關閉(close-on-exec)標志。

Copyright © Linux教程網 All Rights Reserved