守護程序與孤兒程序

2021-08-22 05:52:07 字數 3195 閱讀 4195

基本定義

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

孤兒程序:乙個父程序退出,而它的乙個或多個子程序還在執行,那麼那些子程序將成為孤兒程序。孤兒程序將被init程序(程序號為1)所收養,並由init程序對它們完成狀態收集工作。

殭屍程序:乙個程序使用fork建立子程序,如果子程序退出,而父程序並沒有呼叫wait或waitpid獲取子程序的狀態資訊,那麼子程序的程序描述符仍然儲存在系統中。這種程序稱之為僵死程序。

在說明fork函式時,子程序是在父程序呼叫fork後生成的。子程序將其終止狀態返回給父程序。但是如果父程序在子程序之前終止,又將如何呢?對於父程序已經終止的所有程序,它們的父程序都改變為init程序。我們稱這些程序由init程序收養。操作過程:在乙個程序終止時,核心逐個檢查所有活動程序,以判斷它是否是正要終止程序的子程序,如果是,則該程序的父程序id就更改為1(init程序的id)。這種處理方法保證了每個程序有乙個父程序。

如果子程序是在父程序之前終止,那麼父程序又如何能在做相應檢查時得到子程序的終止狀態呢?如果子程序完全消失了,父程序在最終準備好檢查子程序是否終止時是無法獲取它的終止狀態的。核心為每個終止子程序儲存了一定量的資訊,所以當終止程序的父程序呼叫wait或waitpid時,可以得到這些資訊。這些資訊至少包括程序id、該程序的終止狀態以及該程序使用的cpu時間總量。核心可以釋放終止程序所使用的所有儲存區,關閉其所有開啟檔案。乙個已經終止、但是其父程序尚未對其進行善後處理(獲取終止子程序的有關資訊、釋放它仍占用的資源)的程序被稱為殭屍程序。

最後乙個要考慮的問題是:乙個由init程序收養的程序終止時會發生什麼?它會不會變成乙個殭屍程序?對此問題的回答是「否」,因為init被編寫成無論何時只要乙個子程序終止,init就會呼叫乙個wait函式取得其終止狀態。這樣也就防止了在系統中塞滿殭屍程序。當提及「乙個init的子程序」時,這指的可能是init直接產生的程序,也可能是父程序已終止,由init收養的程序。

守護程序的特徵

系統程序依賴於作業系統的實現。父程序id為0的各程序通常是核心程序,它們作為系統引導裝入過程的一部分而啟動。(init是個例外,它是乙個由核心在引導裝入時啟動的使用者層次的命令)。核心程序是特殊的,通常存在於系統的整個生命期中。它們以超級使用者特權執行,無控制終端,無命令列。

在ps的輸出例項中,核心守護程序的名字出現在方括號中。該版本的linux使用乙個名為kthreadd的特殊核心程序來建立其他核心程序,所以kthreadd表現為其他核心程序的父程序。對於需要在程序上下文執行工作但卻不被使用者層程序上下文呼叫的每乙個核心元件,通常有它自己的核心守護程序。例如,在linux中:

kswapd守護程序也被稱為記憶體換頁守護程序。它支援虛擬記憶體子系統在經過一段時間後將髒頁慢慢寫回磁碟來**這些頁面。

flush守護程序在可用記憶體達到設定的最小閾值時將髒頁面沖洗至磁碟。它也定期地將髒頁面沖洗回磁碟來減少在系統出現故障時發生的資料丟失。

sync_supers守護程序定期將檔案系統元資料沖洗至磁碟。

jbd守護程序幫助實現了ext4檔案系統中的日誌功能。

程序1通常是init,它是乙個系統守護程序,除了其他工作外,主要負責啟動各執行層次特定的系統服務。

rpcbind守護程序提供將遠端過程呼叫程式號對映為網路埠號的服務。rsyslogd守護程序可以被由管理員啟用的將系統訊息記入日誌的任何程式使用。可以在一台實際的控制台上列印這些訊息,也可以將它們寫到乙個檔案中。

inetd守護程序偵聽系統網路介面,以便取得來自網路的對各種網路服務程序的請求。

cron守護程序在定期安排的日期和時間執行命令。許多系統管理任務是通過cron每隔一段固定的時間就執行相關程式而得以實現的。atd守護程序與cron類似,它允許使用者在指定的時間執行任務,但是每個任務它只執行一次,而非在定期安排的時間反覆執行。sshd守護程序提供了安全的遠端登入和執行設施。

大多數守護程序都以超級使用者(root)特權執行。所有的守護程序都沒有控制終端。其終端名設定為問號。

守護程序程式設計規則

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

(1)呼叫umask將檔案模式建立遮蔽字設定為乙個已知值(通常是0)。由繼承得來的檔案模式建立遮蔽套接字可能會被設定為拒絕某些許可權。如果守護程序要建立檔案,那麼它可能要設定特定的許可權。例如,若守護程序要建立組可讀、組可寫的檔案,繼承的檔案模式建立遮蔽字可能會遮蔽上述兩種許可權中的一種,而使其無法發揮作用。另一方面,如果守護程序呼叫的庫函式建立了檔案,那麼將檔案模式建立遮蔽字設定為乙個限制性更強的值(如007)可能會更明智,因為庫函式可能不允許呼叫者通過乙個顯式地函式引數來設定許可權。

(2)呼叫fork,然後使其父程序exit。這樣做實現了以下幾點。第一,如果該守護程序是作為一條簡單的shell命令啟動的,那麼父程序終止會讓shell認為這條命令已經執行完畢。第二,雖然子程序繼承了父程序的程序組id,但獲得了乙個新的程序id,這就保證了子程序不是乙個程序組的組長程序。

(3)呼叫setsid建立乙個新會話。使呼叫程序:(a)稱為新會話的首程序(b)稱為新程序組的組長程序(c)沒有控制終端

(4)將當前目錄更改為根目錄。從父程序處繼承過來的當前工作目錄可能在乙個掛載的檔案系統中。因為守護程序通常在系統再引導之前是一直存在的,所以如果守護程序的當前工作目錄在乙個掛載檔案系統中,那麼該檔案系統就不能被解除安裝。

(5)關閉不再需要的檔案描述符。這使守護程序不再持有從父程序繼承來的任何檔案描述符(父程序可能是shell程序,或某個其他程序)。可以使用open_max函式或getrlimit函式來判定最高檔案描述符值,並關閉直到該值的所有描述符。

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

下面是**:

#include"apue.h"

#include#include#includevoid daemonize(const char *cmd)

}int main()

孤兒程序 孤兒程序組 守護程序

1.孤兒程序的定義 定義1 該程序組的每個成員的父程序要麼是該組的成員,要麼在其它會話中。定義2 乙個程序不是孤兒程序組的條件是 該組有乙個程序,其父程序在屬於同一會話的另乙個組中。只要能夠滿足上面其中的任乙個定義,則此程序組就是孤兒程序組。可能讀起來比較拗口,看圖 1 中的例子可能會清楚點。圖 1...

孤兒程序 殭屍程序 守護程序

1.孤兒程序 如果父程序先退出,子程序還沒退出,那麼子程序將被託孤給init程序 1號程序 這時子程序的父程序就是init程序 1號程序 其實還是很好理解的.2.殭屍程序 如果我們了解過linux程序狀態及轉換關係,我們應該知道程序這麼多狀態中有一種狀態是僵死狀態,就是程序終止後進入僵死狀態 zom...

linux程序系列 6 守護程序與孤兒程序

守護程序是生存期長的一種程序,它們常常在系統引導裝入時啟動,系統關閉時終止。守護程序有如下幾個特點 1.所有的守護程序都是以超級使用者 使用者id為0的root使用者 的優先權執行 2.守護程序沒有控制終端,一直在後台執行 3.守護程序的父程序都是init程序 1號程序 什麼是孤兒程序呢?父程序結束...