(2.6)守護進程詳解、範例演示

一:普通進程運行觀察

//ps -eo pid,ppid,sid,tty,pgrp,comm,stat,cmd | grep -E 'bash|PID|nginx'

  //a)進程有對應的終端,如果終端退出,那麼對應的進程也就消失了;它的父進程是一個bash

  //b)終端被佔住了,你輸入各種命令這個終端都沒有反應;

二:守護進程基本概念

//守護進程 一種長期運行的進程:這種進程在後臺運行,並且不跟任何的控制終端關聯;

  //基本特點:

   //a)生存期長[不是必須,但一般應該這樣做],一般是操作系統啓動的時候他就啓動,操作系統關閉的時候他才關閉;

   //b)守護進程跟終端無關聯,也就是說他們沒有控制終端,所以你控制終端退出,也不會導致守護進程退出;

   //c)守護進程是在後臺運行,不會佔着終端,終端可以執行其他命令

 

 

  //linux操作系統本身是有很多的守護進程在默默的運行,維持着系統的日常活動。大概30-50個;

 

  //a)ppid = 0:內核進程,跟隨系統啓動而啓動,聲明週期貫穿整個系統;

  //b)cmd列名字帶[]這種,叫內核守護進程;

  //c)老祖init:也是系統守護進程,它負責啓動各運行層次特定的系統服務;所以很多進程的PPID是init。而且這個init也負責收養孤兒進程;

  //d)cmd列中名字不帶[]的普通守護進程(用戶級守護進程)

 

  //共同點總結:

  //a)大多數守護進程都是以超級 用戶特權運行的;

  //b)守護進程沒有控制終端,TT這列顯示?

   //內核守護進程以無控制終端方式啓動

   //普通守護進程可能是守護進程調用了setsid的結果(無控制端);

 三:守護進程編寫規則

//(1)調用umask(0);

   //umask是個函數,用來限制(屏蔽)一些文件權限的。

//(2)fork()一個子進程(脫離終端)出來,然後父進程退出( 把終端空出來,不讓終端卡住);固定套路

   //fork()的目的是想成功調用setsid()來建立新會話,目的是

   //子進程有單獨的sid;而且子進程也成爲了一個新進程組的組長進程;同時,子進程不關聯任何終端了;

 一些概念

(3.1)文件描述符:正數,用來標識一個文件。

//linux中三個特殊的文件描述符,數字分別爲0,1,2

   //0:標準輸入【鍵盤】,對應的符號常量叫STDIN_FILENO

   //1:標準輸出【屏幕】,對應的符號常量叫STDOUT_FILENO

     //2:標準錯誤【屏幕】,對應的符號常量叫STDERR_FILENO

  //類Unix操作系統,默認從STDIN_FILENO讀數據,向STDOUT_FILENO來寫數據,向STDERR_FILENO來寫錯誤;

   //類Unix操作系統有個說法:一切皆文件,所以它把標準輸入,標準輸出,標準錯誤 都看成文件。

   //與其說 把 標準輸入,標準輸出,標準錯誤 都看成文件 到不如說

   //象看待文件一樣看待 標準輸入,標準輸出,標準錯誤

       //象操作文件一樣操作 標準輸入,標準輸出,標準錯誤

  

  //同時,你程序一旦運行起來,這三個文件描述符0,1,2會被自動打開(自動指向對應的設備);

 

  //文件描述符雖然是數字,但是,如果我們把文件描述符直接理解成指針(指針裏邊保存的是地址——地址說白了也是個數字);

  //write(STDOUT_FILENO,"aaaabbb",6);

(3.2)輸入輸出重定向

//輸出重定向:我標準輸出文件描述符,不指向屏幕了,假如我指向(重定向)一個文件

   //重定向,在命令行中用 >即可;

 

  //輸入重定向 <

 (3.3)空設備(黑洞)

// /dev/null :是一個特殊的設備文件,它丟棄一切寫入其中的數據(象黑洞一樣);

 

  //----

  //守護進程雖然可以通過終端啓動,但是和終端不掛鉤。

   //守護進程是在後臺運行,它不應該從鍵盤上接收任何東西,也不應該把輸出結果打印到屏幕或者終端上來

   //所以,一般按照江湖規矩,我們要把守護進程的 標準輸入,標準輸出,重定向到 空設備(黑洞);

   //從而確保守護進程不從鍵盤接收任何東西,也不把輸出結果打印到屏幕;

  //int fd;

  //fd = open("/dev/null",O_RDWR) ;//打開空設備

  //dup2(fd,STDIN_FILENO); //複製文件描述符 ,像個指針賦值,把第一個參數指向的內容賦給了第二個參數;

  //dup2(fd,STDOUT_FILENO);

  //if(fd > STDERR_FILENO)

  // close(fd); //等價於fd = null;

(3.4)實現範例 

//守護進程可以用命令啓動,如果想開機啓動,則需要藉助 系統初始化腳本來啓動。

#include <stdio.h>
#include <stdlib.h>  //malloc
#include <unistd.h>
#include <signal.h>

#include <sys/stat.h>
#include <fcntl.h>

//創建守護進程
//創建成功則返回1,否則返回-1
int ngx_daemon()
{
    int  fd;

    switch (fork())  //fork()子進程
    {
    case -1:
        //創建子進程失敗,這裏可以寫日誌......
        return -1;
    case 0:
        //子進程,走到這裏,直接break;
        break;
    default:
        //父進程,直接退出 
        exit(0);         
    }

    //只有子進程流程才能走到這裏
    if (setsid() == -1)  //脫離終端,終端關閉,將跟此子進程無關
    {
        //記錄錯誤日誌......
        return -1;
    }
    umask(0); //設置爲0,不要讓它來限制文件權限,以免引起混亂

    fd = open("/dev/null", O_RDWR); //打開黑洞設備,以讀寫方式打開
    if (fd == -1) 
    {
        //記錄錯誤日誌......
        return -1;
    }
    if (dup2(fd, STDIN_FILENO) == -1) //先關閉STDIN_FILENO[這是規矩,已經打開的描述符,動他之前,先close],類似於指針指向null,讓/dev/null成爲標準輸入;
    {
        //記錄錯誤日誌......
        return -1;
    }

    if (dup2(fd, STDOUT_FILENO) == -1) //先關閉STDIN_FILENO,類似於指針指向null,讓/dev/null成爲標準輸出;
    {
        //記錄錯誤日誌......
        return -1;
    }

     if (fd > STDERR_FILENO)  //fd應該是3,這個應該成立
     {
        if (close(fd) == -1)  //釋放資源這樣這個文件描述符就可以被複用;不然這個數字【文件描述符】會被一直佔着;
        {
            //記錄錯誤日誌......
            return -1;
        }
    }

    return 1;
}

int main(int argc, char *const *argv)
{
    if(ngx_daemon() != 1)
    {
        //創建守護進程失敗,可以做失敗後的處理比如寫日誌等等
        return 1; 
    } 
    else
    {
        //創建守護進程成功,執行守護進程中要乾的活
        for(;;)
        {        
            sleep(1); //休息1秒
            printf("休息1秒,進程id=%d!\n",getpid()); //你就算打印也沒用,現在標準輸出指向黑洞(/dev/null),打印不出任何結果【不顯示任何結果】
        }
    }
    return 0;
}




 四:守護進程不會收到的信號:內核發給你,另外的進程發給你的;

(4.1)SIGHUP信號

  //守護進程不會收到來自內核的 SIGHUP 信號; 潛臺詞就是 如果守護進程收到了 SIGHUP信號,那麼肯定是另外的進程發給你的;

  //很多守護進程把這個信號作爲通知信號,表示配置文件已經發生改動,守護進程應該重新讀入其配置文件;

 

(4.2)SIGINT、SIGWINCH信號

  //守護進程不會收到來自內核的 SIGINT(ctrl+C),SIGWINCH(終端窗口大小改變) 信號;

 五:守護進程和後臺進程的區別

//(1)守護進程和終端不掛鉤;後臺進程能往終端上輸出東西(和終端掛鉤);

 //(2)守護進程關閉終端時不受影響,守護進程會隨着終端的退出而退出;

 //(3)......其他的,大家自己總結;

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章