UNIX環境高階程式設計 閱讀第十三章 守護程序

2021-10-07 21:45:03 字數 3928 閱讀 5784

守護程序(daemon)是生存期長的一種程序。

常常在系統引導裝入時啟動,僅在系統關閉時才終止。

因為守護程序沒有控制終端,所以說它們是在後台執行的。

unix系統有很多守護程序,它們執行日常事務活動。

ps -ajx

選項-a顯示由其他使用者所擁有的程序的狀態,

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

-j顯示與作業有關的資訊:會話id、程序組id、控制終端以及終端程序組id。

uid:使用者id、程序id、父程序id、程序組id、會話id、終端名稱以及命令字串。

# ps -ajx

ppid pid pgid sid tty tpgid stat uid time command

0 1 1 1 ? -1 ss 0 26:22 /usr/lib/systemd/systemd --switched-root --system --deserialize 22

0 2 0 0 ? -1 s 0 0:00 [kthreadd]

2 4 0 0 ? -1 s< 0 0:00 [kworker/0:0h]

2 6 0 0 ? -1 s 0 4:56 [ksoftirqd/0]

2 7 0 0 ? -1 s 0 1:30 [migration/0]

2 8 0 0 ? -1 s 0 0:00 [rcu_bh]

2 9 0 0 ? -1 s 0 47:49 [rcu_sched]

2 10 0 0 ? -1 s< 0 0:00 [lru-add-drain]

2 11 0 0 ? -1 s 0 0:36 [watchdog/0]

2 12 0 0 ? -1 s 0 0:32 [watchdog/1]

2 13 0 0 ? -1 s 0 1:29 [migration/1]

2 14 0 0 ? -1 s 0 4:55 [ksoftirqd/1]

2 16 0 0 ? -1 s< 0 0:00 [kworker/1:0h]

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

在ps的輸出例項中,核心守護程序的名字出現在方括號中。

這個版本的linux使用乙個名為kthreadd的特殊核心程序來建立其它核心程序,所以kthreadd表現為其它核心程序的父程序。

對於需要在程序上下文執行工作但卻不被使用者層程序上下文呼叫的每乙個核心元件,通常有它自己的核心守護程序。

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

程序1通常是init。它是乙個系統守護程序,除了其他工作外,主要負責啟動各執行層次特定的系統服務。這些伺服器通常是在它們自己擁有的守護程序的幫助下實現的。

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

編寫守護程序程式時需要遵循一些基本規則,以防止產生不必要的互動作用。

首先要做的是呼叫umask將檔案模式建立遮蔽字設定為乙個已知值(通常是0)

由繼承得來的檔案模式建立遮蔽字可能會被設定為拒絕某些許可權。

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

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

呼叫setsid建立乙個新會話。建立會話時經過三個階段,(1)該程序變成新會話的會話首程序(session leader,會話首程序是建立該會話的程序)。此時,該程序是新會話中的唯一程序。(2)該程序成為乙個新程序組的組長程序。新程序組id是呼叫該程序的程序id。(3)該程序沒有控制終端。如果在呼叫setsid之前該程序有乙個控制終端,那麼這種聯絡也被切斷。

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

或者,某些守護程序還可能會把當前工作目錄更改到某個指定位置,並在此位置進行它們的全部工作。例如,行式印表機假離線守護程序就可能將其工作目錄更改到它們的spool目錄上。

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

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

void daemonize(const char *cmd)

定義int 型變數 i,fd0,fd1,fd2

定義pid型別變數,pid

定義rlimit結構體 r1

/include/uapi/linux/resource.h(用於linux的資源控制/計算的標頭檔案)原始碼中對rlimit的定義

struct rlimit ;

對的定義__kernel_ulong_t:typedef unsigned long __kernel_ulong_t; #本質是unsigned long型別

清除檔案建立遮蔽字 umask(0),將其置為0

得到檔案描述符的極限值

成為乙個會話的首程序,並關閉控制終端

確保未來開啟時不會被分配控制終端

改變當前工作目錄到root,這樣就不會阻止檔案系統被載入

關閉所有的檔案描述符

將檔案描述符0、1和2附加到/dev/null

初始化日誌檔案

守護程序沒有控制終端,所以不能寫到標準錯誤上

不能將所有守護程序都寫到控制台裝置上

不能每個守護程序寫乙個日誌檔案

需要乙個集中的守護程序出錯記錄設施,bsd的syslog

資料:終端、shell、tty 和控制台(console)有什麼區別?

linux rlimit 函式詳解

UNIX環境高階程式設計 第十三章 守護程序

守護程序 daemon 是生存期長的一種程序。它們常常在系統引導裝入時啟動,僅在系統關閉時才終止 生存期 因為它們沒有控制終端,所以說它們時在後頭執行的。unix系統有很多守護程序,它們執行日常事務活動。本章將說明守護程序的結構,以及如何編寫守護程序程式。因為守護程序沒有控制終端,我們需要了解在出現...

閱讀體會 UNIX環境高階程式設計

第一章第二章 2.3 unix系統實現 2.4 標準和實現地關係 2.5 限制 2.6 選項 2.7 功能測試巨集 2.8 基本系統資料型別 2.9 標準之間的衝突 2.10 小結 ps 之前一直苦惱於書讀過之後會忘記,某天,靈機一閃,在閱讀時把體會記錄下來不就好了,還能加深印象!於是最近就開始了把...

Unix環境高階程式設計 閱讀體會整理

二 steedhorse 我覺得當你自己還不知道怎麼看的時候,也只能一步一步看了。zlcqupt 哈哈,有人指點畢竟要快一點,現在這個社會,要快啊 steedhorse 呵呵,還是慢慢啃吧。對於初學者來說,常常看三本薄書不如啃一本厚書,入了門了就可以多讀些高階的薄書了。當然,隨著不斷地讀進去,自己也...