Linux下開發-守護程式(daemon)

啊浪的部落格發表於2017-11-05

int daemon(void){
    pid_t pid = fork();
    if( pid != 0 ) exit(0);//parent

    //first children
    if(setsid() == -1){
       printf("setsid failed\n");
       assert(0);
       exit(-1);
    }

    umask(0);

    pid = fork();
    if( pid != 0) exit(0);
  
    //second children 
    chdir ("/");

    for (int i = 0; i < 3; i++){
        close (i);
    }

    int stdfd = open ("/dev/null", O_RDWR);
    dup2(stdfd, STDOUT_FILENO);
    dup2(stdfd, STDERR_FILENO);

    return 0;
}

第一次fork的作用是讓shell 認為本條命令已經終止,不用掛在終端輸入上。還有一個作用是為後面setsid服務。setsid的呼叫者不能是程式組組長(group leader). 此時父程式是程式組組長
    
setsid() 是本函式最重要的一個呼叫。它完成了daemon函式想要做的大部分事情。呼叫完整個函式。子程式是會話組長(sid==pid),也是程式組組長(pgid == pid),並且脫離了原來控制終端。到了這一步,基本上不管控制終端如何怎麼樣。新的程式都不會收到那些訊號

經過前面2個步驟,基本想要做的都做了。第2次fork不是必須的。也看到很多開源服務沒有fork第二次。fork第二次主要目的是。防止程式再次開啟一個控制終端。因為開啟一個控制終端的前臺條件是該程式必須是會話組長。再fork一次,子程式ID != sid(父程式的sid)。所以也無法開啟新的控制終端。



一次fort、孤兒程式





殭屍程式





兩次fork





守護程式與用&結尾的後臺執行程式的區別

1)守護程式已經完全脫離終端控制檯了,而後臺程式並未完全脫離終端,在終端未關閉前還是會往終端輸出結果
2)守護程式在關閉終端控制檯時不會受影響,而後臺程式會隨使用者退出而停止,需要在以nohug xxx & 格式執行才能避免影響
3)守護程式的會話組和當前目錄,檔案描述符都是獨立的。後臺執行只是終端進行了一次fork,讓程式在後臺執行,這些都沒改變。




終端訊號和程式

   //後臺程式讀取/寫入終端輸入產生下面兩個訊號,或者控制終端不存在情況讀取和寫入會產生
   signal(SIGTTOU, SIG_IGN);
   signal(SIGTTIN, SIG_IGN);

   //按CTRL-C ,CTRL-\ CTRL-Z會向前臺程式組傳送下面這些訊號
   signal(SIGINT,  SIG_IGN );
   signal(SIGQUIT, SIG_IGN );
   signal(SIGTSTP, SIG_IGN );
   
   //終端斷開,會給會話組長或孤兒程式組所有成員傳送下面訊號
   signal(SIGHUP,  SIG_IGN );

   還有有些訊號也可以由終端shell產生,需要關注
   signal(SIGCONT, SIG_IGN );
   signal(SIGSTOP, SIG_IGN );




相關文章