守護進程(相似Windows的服務):一般被定義爲一個後臺進程,並且它不屬於任何一個終端會話(terminal session)。許多系統服務由守護程序實施;如網絡服務,打印等。 python
下面介紹下守護進程的基本編碼過程以及python的對應實現: shell
1. 調用 fork 並使父進程退出(exit)( 若父進程退出,子進程還沒有結束,則子進程會被init進程領養,也就是說init進程將成爲該子進程的父進程)。這一步驟的目的在於。首先,若是守護進程是經過一個簡單的shell命令創建的,那麼在父進程終止的時候shell會認爲命令已經結束了繼而結束守護進程。其次,子進程繼承獲得父進程的groupID同時也得到了一個新的進程號,因此咱們必須得保證子進程不能擔任groupleader(關於進程組與會話先看這篇Blog)的角色,這是下一步setsid 操做的前提。 網絡
注:此步驟是使得進程在後臺運行 session
pid = os.fork() if pid > 0 sys.exit(0)
2. 調用 setsid 建立一個新的會話(當進程是會話的領頭進程時setsid()調用失敗並返回(-1)。setsid()調用成功後,返回新的會話的ID,調用setsid函數的進程成爲新的會話的領頭進程,並與其父進程的會話組和進程組脫離。因爲會話對控制終端的獨佔性,進程同時與控制終端脫離)。有三個步驟將會執行: 函數
注:此步驟將使得進程脫離控制終端、登陸會話以及進程組。 編碼
os.setsid()3. 接下來要作的被稱爲umask( 文件的默認權限,補碼),這一步驟會將文件建立掩碼重置爲0( 由於是補碼,因此0爲權限最大)。這一步的緣由是守護進程繼承(inherited)獲得的文件掩碼有可能會拒絕某些特定的文件操做權限。若是守護進程想要建立文件,那有可能它須要設置特定的文件操做權限。例如,若是守護進程想要建立容許組讀和寫(group-readand group-write)權限的文件,但繼承獲得的文件建立掩碼屏蔽了這個權限,則建立操做不會成功。
os.umask(0)
4. 將當前的工做目錄切換到系統根目錄下。由於從父進程集成來的當前工做目錄多是一個被掛載的文件系統。由於守護進程一般是直到系統重啓的時候纔會退出,若是守護進程的工做目錄在一個掛載的文件系統上,那麼這個文件系統就不能被卸載(unmounted)。 spa
有的守護進程可能會將當前的工做目錄切換到一些特定的路徑,在這些路徑下它們將完成它們的工做。例如,lineprinter spoolingdaemons 一般將工做目錄切換爲spool目錄。 .net
os.chdir("/")5. 在基於SystemV的系統中,有建議再一次調用fork 並使父進程退出。而新產生的進程將會成爲真正的守護進程( 這意味着一 個非會話組頭領進程永遠不能從新得到控制終端 )。這一步驟將保證守護進程不是一個sessionleader,進而阻止它獲取一個控制終端。或者另外一種阻止守護進程獲取控制終端的方案是任意時刻打開一個終端設備的時候確保指定O_NOCTTY。
注:此步驟將禁止進程從新打開控制終端。 code
pid = os.fork() if pid > 0 sys.exit(0)6. 一些沒必要要的文件描述符將會被關閉。這個步驟將阻止守護進程保持從父進程集成到的任何已經打開的文件描述符(也多是shell或其餘進程)。咱們可使用 open_max 函數或 getrlimit 函數來查找當前優先級最高的文件描述符並關閉此描述符之下的全部其餘描述符。
注:保持打開的描述符將會佔用系統資源並可能使某些文件不能被卸載。 blog
7. 有一些守護進程將打開文件描述符0, 1, 2 指向 /dev/null ,這樣一來全部試圖從標準輸入、輸出及錯誤讀取守護進程信息的操做都不能成功。由於守護進程當前已經不與任何終端設備相關聯,沒有地方顯示其輸出或接受用戶的輸入。即便守護進程是從一個交互式session建立的,守護進程也將運行在後臺,任何終端的登陸與終止將不會影響守護進程。若是有其餘用戶經過當前的終端登陸,咱們也不但願守護進程的輸出出如今終端上,而且該用戶的任何輸入也不會被守護進程接收。
1. http://edison0951.iteye.com/blog/610727
2. http://blog.csdn.net/dysj4099/article/details/18219411