13 - 守護進程
GitHub 地址git
1. 守護進程
守護進程 (daemoon) 是生存期長的一種進程。經常在系統引導裝入時啓動,僅在系統關閉時才終止。它們是在後臺運行的,沒有控制終端。UNIX 有不少守護進程,它們執行 平常事務活動 。github
2. 守護進程的特徵
內核進程:父進程 ID 爲 \(0\) 的各進程一般是內核進程,它們做爲系統引導裝入的一部分而啓動 。shell
內核守護進程:對於須要在進程上下文執行工做但卻不被用戶層進程上下文調用的每個內核組件,一般有它的內核守護進程 。編程
init 進程:是一個 系統守護進程 ,主要負責啓動各運行層次特定的系統服務 。spa
用戶層守護進程:init 進程啓動的系統服務一般是在它們本身擁有的守護進程的幫助下實現的,用戶層守護進程的父進程是 init 進程 。code
守護進程的特徵:繼承
- 大多數守護進程都是以超級用戶( root )特權運行
- 全部守護進程都沒有控制終端,其控制終端名設置爲問號
- 內核守護進程以無控制終端方式啓動
- 用戶層守護進程缺乏控制終端多是守護進程調用了 setsid 的結果
- 大多數用戶層守護進程都是進程組的組長進程以及會話的首進程,並且是這些進程組和會話中的惟一進程
3. 編程規則
編寫守護進程程序需遵循一些 基本規則:進程
- 調用 umask 將文件模式建立屏蔽字設置爲一個已知值(一般是 \(0\) )。由於由繼承得來的文件模式建立屏蔽字可能會被設置爲拒絕某些權限,而若是守護進程要建立文件,那麼它可能要設置特定的權限 。
- 調用 fork ,而後使父進程 exit 。這樣作有兩個緣由:
- 若是該守護進程是做爲一條 shell 命令啓動的,那麼父進程終止會讓 shell 認爲這條命令已經執行完畢,shell 能夠執行其餘命令,形式上作到了守護進程與終端控制的脫離
- 子進程繼承了父進程進程組 ID ,但得到了新的進程 ID,這就保證了子進程不是一個進程組的組長進程(使用 setsid 的先決條件 )
- 調用 setsid 建立一個新會話 。使調用進程:成爲新會話首進程、成爲一個新進程組的組長進程、沒有控制終端。( 在此可再次調用 fork ,終止父進程,繼續使用子進程中的守護進程,保證該守護進程不是會話首進程。 )
- 將當前工做目錄更改成根目錄。由於從父進程繼承過來的當前工做目錄可能在一個掛載的文件系統中,守護進程隨系統存在的特性使得此文件系統不能被卸載。也能夠將當前工做目錄更改到某個指定位置。
- 關閉文件描述符。
- 某些守護進程打開
/dev/null
使其具備文件描述符 \(0\) 、\(1\) 和 \(2\) ,這樣任何一個試圖讀標準輸入、寫標準輸出或標準錯誤的庫例程都不會產生任何效果。(由於守護進程並不與終端設備相關聯)
4. 單實例守護進程
爲了正常運做,某些守護進程會實現爲:在任一時刻只運行該守護進程的一個副本。例如,這種守護進程可能須要排他地訪問一個設備 。事務
文件和記錄鎖 機制爲一種方法提供了基礎,該方法保證一個守護進程只有一個副本在運行 。若是一個守護進程建立一個有固定名字的文件,並在該文件的總體上加一把寫鎖,那麼只容許建立一把這樣的寫鎖,在此以後建立寫鎖的嘗試都會失敗,這向後續守護進程副本指明已有一個副本在運行 。get