daemon進程fork一次和fork兩次的區別?

  守護進程也稱爲精靈進程(Daemon),是運行在後臺的一種特殊的進程。它獨立於控制終端而且週期性的執行某種任務負等待處理某些發生的事件。由於他們沒有控制終端,因此說他們是在後臺運行的。shell

  守護進程的特色:session

    (1)Linux系統啓動時會啓動不少系統服務進程,守護進程沒有控制終端,不能直接和用戶交互。函數

    (2)其餘進程都是在用戶登陸或者運行程序時建立,在運行結束或用戶註銷時終止,但守護進程不受用戶登陸註銷的影響,只受開機關機的影響。進程

  守護進程存在的緣由:事件

    daemon函數存在的緣由是由於控制終端因爲某些緣由(如斷開終端鏈接)會發送一些信號的緣由。而接受處理這些信號的缺省動做會讓進程退出。這些信號會因爲終端敲一些特殊按鍵產生。io

  守護進程和後臺進程的區別:登錄

    (1)守護進程是後臺進程,但後臺進程不必定是守護進程後臺

    (2)守護進程運行是與終端無關的,是不能往終端上打消息的。終端

    (3)守護進程的會話和當前目錄,文件描述符都是獨立的。後臺運行只是終端進行了一次fork,讓程序在後臺執行。程序

  建立守護進程:

    建立守護進程最關鍵的一步是調用setsid函數建立了一個新的會話(session),併成爲session Leaser.

    #include<unistd.h>

    pid_t setsid(void);

    該函數調用成功時返回新建立的session的id(其實就是當前進程的id),出錯返回-1.注意,調用這個函數以前,當前進程不容許是進程組的Leader,不然該函數返回-1.要保證當前進程不是否是進程組的Leader也很容易,只要先fork再調用setsid就好了。fork建立的子進程和父進程在同一個進程組裏面,進程組的Leader必然是該組的第一個進程,因此子進程不多是改組的第一個進程,在子進程中調用setsid就不會有問題了。

  成功調用該函數的結果是:

    (1)建立一個新的session,當前進程稱爲session Leader,當前進程的id就是session的id。

    (2)建立一個新的進程組,當前進程稱爲進程租的Leader,當前進程的id就是進程租的id。

    (3)若是當前進程本來有一個控制終端,則他失去這個控制終端,稱爲一個沒有控制終端的進程。所謂失去進程終端是指,原來的進程終端仍然是可打開的,仍然能夠讀寫,但只是一個普通的打開文件而不是控制終端了。

  建立守護進程的步驟:

    (1)調用umask將文件模式建立屏蔽字設置爲0

    (2)父進程fork出子進程,而後子進程調用setsid,父進程直接退出(保證了子進程不是一個進程組的進程組長)

    (3)調用setsid建立一個新的會話(調用成功會使調用進程成爲會話的首進程,併成爲一個進程租的組長進程,調用進程沒有控制終端)

    (4)將當前工做目錄更改成根目錄

    (5)關閉不須要的文件描述符

    (6)忽略SIGCHLD信號。

  要知道在建立守護進程的時候fork一次和fork兩次的二者的區別,就要先知道第一次fork和第二次fork都起到什麼做用:

    (1)調用一次fork的做用:

      第一次fork的做用是讓shell認爲這條命令已經終止,不用掛在終端輸入上,還有就是爲了後面上的setsid服務,由於調用setsid函數的進程不能是組長進程,若是不fork出子進程,則此時的父進程是進程組長,就沒法調用setsid。當子進程調用完setsid函數以後,子進程是會話組長也是進程組組長,而且脫離了控制終端,此時,無論控制終端如何操做,新的進程都不會收到一些信號使得進程退出。

    (2)第二次fork的做用:

      雖然當前關閉了和終端的聯繫,可是後期可能會誤操做打開了終端。

      只有會話首進程能打開終端設備,也就是在fork一次,再把父進程退出,再次fork的子進程做爲守護進程繼續運行,保證了該精靈進程不是對話期的首進程,第二次不是必須的,是可選的,市面上有些開源項目也是fork一次。

相關文章
相關標籤/搜索