daemon()函數守護進程函數介紹

原文鏈接:daemon函數詳解原文鏈接

頭文件與函數原型

#include <unistd.h>
int daemon(int nochdir,int noclose)

創建守護進程前提條件

  1. 將進程的工作目錄修改爲"/"根目錄。daemon的參數nochdir爲0時,即可將工作目錄修改爲根目錄;
  2. 將標準輸入,輸出和錯誤輸出重定向到/dev/null daemon的參數noclose爲0時,輸入,輸出以及錯誤輸出重定向到/dev/null 。

返回值:成功返回0 錯誤返回1

deamon()函數解析

#include <unistd.h>
int main(int argc,char *argv[])
{
 if (daemon(0, 0)) {//調用glibc庫函數daemon,創建daemon守護進程
        perror("daemon");
        return -1;
    }
    子進程內容
}

int daemon( int nochdir, int noclose )
{
   pid_t pid;
   if ( !nochdir && chdir("/") != 0 )   //如果nochdir=0,那麼改變到"/"根目錄
       return -1;
   if ( !noclose )                      //如果沒有noclose=0,那麼開始輸入,輸出以及錯誤輸出重定向到/dev/null 
   {
     int fd = open("/dev/null", O_RDWR);//打開神奇的黑洞文件.

     if ( fd < 0 )
      return -1;
//每個進程都擁有自己fds文件描述符表,
//fdt->fd[0],fdt->fd[1],fdt->fd[2],
//表中fd[0],fd[1],和fd[2]文件句柄位置對應的fops文件操作函數集,分別與標準輸入,標準輸出,標準錯誤輸出相關聯
//所以用戶應用程序調用open函數打開文件時,默認都是以3索引爲開始句柄,也就是fd[3],故當前open返回的文件句柄最小值爲3

//dup2(unsigned int oldfd, unsigned int newfd)系統調用就是用oldfd的fops操作文件集file,複製到newfd所在處
//即:fdt->fd[newfd] = fdt->fd[oldfd];

     if ( dup2( fd, 0 ) < 0 || //使用字符設備/dev/null的fops函數操作集,替換0句柄對應的文件操作集.
     dup2( fd, 1 ) < 0 ||      //使用字符設備/dev/null的fops函數操作集,替換1句柄對應的文件操作集.
          dup2( fd, 2 ) < 0 )  //使用字符設備/dev/null的fops函數操作集,替換2句柄對應的文件操作集.
     {
       close(fd);
      return -1;
     }

 //如果替換成功,那麼鍵盤的任何操作將不會對該進程產生任何影響,因爲0,1,2句柄所在處的fops文件操作集已經都變成了,
 
//被重定向爲"/dev/null"空洞設備的fops.所以對0,1,2句柄的讀寫操作,也就是在對/dev/null設備作讀寫操作.
     close(fd); //關閉打開的/dev/null
  }
   pid = fork();//創建子進程.
   if (pid < 0)
    return -1;

   if (pid > 0)
    _exit(0);  //返回執行的是父進程,那麼父進程退出,讓子進程變成真正的孤兒進程.

               //ok,我們期望的daemon子進程執行到這裏了.
   if ( setsid() < 0 ) //設置session id.
     return -1;

   return 0;   //成功創建daemon子進程[luther.gliethttp].
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章