守護進程

一:線路規程
先給一個簡單的栗子:
這裏寫圖片描述
我們在終端下按下字母aaaaaa在bash下會顯示aaaaa,但當我們按下組合鍵Ctrl-C,爲什麼卻沒有顯示Ctrl-C呢?
這就是線路規程乾的好事,那麼什麼是線路規程,簡單點說就是就是內核層面的過濾器.
這裏寫圖片描述
鍵盤輸入的數據被驅動程序提交給線路規程,當輸入的普通字符,線路規程不會做任何處理,默認讓它通過,而當輸入的是組合鍵時被解釋成信號.這就很容易解釋上面的現象.

二:shell分前後臺控制的不是進程而是作業.?
1:jobs查看所有的作業
這裏寫圖片描述
cat運行一個前臺進程,cat& 把前臺進程放到後臺運行,我們再觀察jobs此時作業的運行狀態是stopped
2:fg 加上作業號,表明把幾號作業放置前臺
這裏寫圖片描述
3:Ctrl+Z將前臺作業Stop,然後bg 加上作業號表明將作業放置後臺.
這裏寫圖片描述

三:守護進程
:Linux系統啓動時會啓動很多系統服務器進程,這些系統服務器進程沒有控制終端,不能直接集合用戶交互,其他進程都是在用戶登錄會運行程序時創建,在運行結束或用戶註銷時終止,但系統服務進程不受用戶登錄註銷的影響,它們一直在運行着.這種進程有一個名稱叫守護進程.
簡單點說守護進程
1:是不受用戶登錄(創建會話),和註銷(銷燬會話)的影響
2:與終端去關聯
3:自成會話

創建守護進程的關鍵是setsid函數
調用setsid函數創建一個新的Session,併成爲Session Leader.

#include<unistd.h>
pid_t setsid(void);

函數調用成功是返回新創建Session 的id(當前進程的id).出錯返回-1.注意,調用這個函數之前,當前進程不允許是進程組的Leader,否則該函數返回-1, 要保證當前進程不是進程組的Leader很容易,先fork然後再調用setsid就可以了.fork創建的子進程和父進程在同一個進程組中,進程組的Leader必然是改組的第一個進程,所以子進程不可能是改組的第一個進程,在子進程找那個調用setsid就不會有問題.

創建守護進程
1:調用umask將文件模式創建屏蔽字設置爲0;
2:調用fork,父進程退出
原因:
a:如果該守護進程是作爲一條簡單的shell命令啓動時,那麼父進程終止使得shell認爲該命令已經執行完畢
b:保證子進程不是一個進程組的組長進程
3:調用setsid創建一個新會話.setsid會導致
a:調用進程成爲新會話的首進程
b:調用進程成爲一個進程組的組長進程
c:調用進程沒有控制終端
4:將當前工作目錄改爲根目錄
5;關閉不需要的文件描述符
6:忽略SIGCHLD信號

驗證:

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
void mydaemon()
{
    umask(0);
    if(fork() >0)
    {
        exit(0);
    }
    else if(fork()<0)
    {
        return ;
    }
       setsid();
chdir("/");
      close(0);
      close(1);
      close(2);
      signal(SIGCHLD,SIG_IGN);
}
int main()
{
mydaemon();
    while(1)
    {
     sleep(1);
    }
    return 0;
}

這裏寫圖片描述
1:先進入proc查看守護進程
這裏寫圖片描述
2:然後進程守護進程
這裏寫圖片描述
3:我們再來查看文件描述符信息
這裏寫圖片描述

創建守護進程fork()一次和fork()兩次的區別?
第一次fork()的作用:
第一次fork的作用是讓shell認爲這條命令已經終止,不用掛在終端輸入上,還有一個作用是爲後面的setsid服務,setsid調用完後,子進程是會話組長又是進程組的組長,並且脫離控制終端
第二次fork()作用:
防止進程再次打開一個控制終端因爲再次打開一個控制終端的前提條件是該進程必須是會話的組長,再fork一次,子進程id !=sid,所以無法打開新的控制終端;

發佈了113 篇原創文章 · 獲贊 62 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章