linux高級環(huán)境編程--守護(hù)進(jìn)程

基本概念
  • Linux Daemon(守護(hù)進(jìn)程)是運行在后臺的一種特殊進(jìn)程。它獨立于控制終端并且周期性地執(zhí)行某種任務(wù)或等待處理某些發(fā)生的事件崖瞭。它不需要用戶輸入就能運行而且提供某種服務(wù),不是對整個系統(tǒng)就是對某個用戶程序提供服務(wù)胚吁。Linux系統(tǒng)的大多數(shù)服務(wù)器就是通過守護(hù)進(jìn)程實現(xiàn)的牙躺。常見的守護(hù)進(jìn)程包括系統(tǒng)日志進(jìn)程syslogd、 web服務(wù)器httpd腕扶、郵件服務(wù)器sendmail和數(shù)據(jù)庫服務(wù)器mysqld等孽拷。
  • 守護(hù)進(jìn)程一般在系統(tǒng)啟動時開始運行,除非強行終止半抱,否則直到系統(tǒng)關(guān)機都保持運行脓恕。守護(hù)進(jìn)程經(jīng)常以超級用戶(root)權(quán)限運行,因為它們要使用特殊的端口(1-1024)或訪問某些特殊的資源窿侈。
  • 一個守護(hù)進(jìn)程的父進(jìn)程是init進(jìn)程炼幔,因為它真正的父進(jìn)程在fork出子進(jìn)程后就先于子進(jìn)程exit退出了,所以它是一個由init繼承的孤兒進(jìn)程史简。守護(hù)進(jìn)程是非交互式程序乃秀,沒有控制終端,所以任何輸出圆兵,無論是向標(biāo)準(zhǔn)輸出設(shè)備stdout還是標(biāo)準(zhǔn)出錯設(shè)備stderr的輸出都需要特殊處理环形。
  • 守護(hù)進(jìn)程的名稱通常以d結(jié)尾,比如sshd衙傀、xinetd抬吟、crond等
編程規(guī)則
  • 在父進(jìn)程中執(zhí)行fork并exit推出-->確保不是進(jìn)程組組長進(jìn)程,進(jìn)程組組長统抬,就無法調(diào)用setsid火本;
  • 在子進(jìn)程中調(diào)用setsid函數(shù)創(chuàng)建新的會話-->沒有控制終端;
  • 在子進(jìn)程中調(diào)用chdir函數(shù)聪建,讓根目錄 ”/” 成為子進(jìn)程的工作目錄-->若掛載在文件系統(tǒng)中钙畔,該文件系統(tǒng)不能卸載;
  • 在子進(jìn)程中調(diào)用umask函數(shù)金麸,設(shè)置進(jìn)程的umask為0擎析;
  • 在子進(jìn)程中關(guān)閉任何不需要的文件描述符-->不需要父進(jìn)程的相關(guān)描述符。

為什么需要設(shè)置umask?

每個文件建立時有一個權(quán)限挥下,如755揍魂,umask命令用來設(shè)置限制新建文件權(quán)限的掩碼,表示在原有權(quán)限上刪除相應(yīng)的權(quán)限棚瘟。如文件原來的初始化權(quán)限是777现斋,那么執(zhí)行命令umask 022以后,該文件的權(quán)限將變?yōu)?55:如果該文件原來的初始化權(quán)限是666偎蘸,那么該文件的權(quán)限將變?yōu)?44庄蹋。
因為守護(hù)進(jìn)程一開始是從父進(jìn)程fork來瞬内,繼承來的umask可能會設(shè)置為拒絕一些權(quán)限,當(dāng)守護(hù)進(jìn)程要創(chuàng)建可讀可寫文件時限书,可能會因為權(quán)限不夠而無法發(fā)揮作用虫蝶。

先補充相關(guān)知識點

會話

會話是一個或多個進(jìn)程組的集合,進(jìn)程調(diào)用setsid()創(chuàng)建一個新會話倦西,如果該進(jìn)程不是一個進(jìn)程組的組長秉扑,將會發(fā)生以下:

image.png

會話的作用主要由以下三個,主要用于守護(hù)進(jìn)程中:

  • 使當(dāng)前進(jìn)程脫離原會話的控制
  • 使當(dāng)前進(jìn)程脫離原進(jìn)程組的控制
  • 使當(dāng)前進(jìn)程脫離原控制終端的控制

總結(jié)說就是非進(jìn)程組組長進(jìn)程創(chuàng)建會話后调限,該進(jìn)程稱為會話首進(jìn)程,并且成為新建進(jìn)程組的組長進(jìn)程误澳,新進(jìn)程組ID為該進(jìn)程ID耻矮,重要一點就是沒有控制終端。
創(chuàng)建會話一個條件就是非組長進(jìn)程忆谓,為了保證裆装,通常先調(diào)用fork,然后使父進(jìn)程終止倡缠,而子進(jìn)程繼續(xù)哨免,子進(jìn)程繼承了進(jìn)程組ID,而進(jìn)程ID又是新分配昙沦,保證了不是進(jìn)程組組長琢唾。
一個會話通常開始于用戶登錄,終止于用戶退出盾饮,期間所有的進(jìn)程都屬于這個會話采桃。一個會話一般包含一個會話首進(jìn)程、一個前臺進(jìn)程組和一個后臺進(jìn)程組丘损,控制終端可有可無普办;此外,前臺進(jìn)程組只有一個徘钥,后臺進(jìn)程組可以有多個衔蹲,這些進(jìn)程組共享一個控制終端

image.png

對守護(hù)進(jìn)程進(jìn)行總結(jié),守護(hù)進(jìn)程是脫離終端并在后臺運行的進(jìn)程呈础,需要脫離原控制終端舆驶,原進(jìn)程組,原會話而钞,因此要建立一個新的會話贞远,由于進(jìn)程組組長不能創(chuàng)建會話,需要先fork笨忌,確保進(jìn)程ID不是原會話ID和進(jìn)程組組長ID蓝仲;由于fork保留了父進(jìn)程的相關(guān)信息,如目錄和權(quán)限,由于守護(hù)進(jìn)行要更大的靈活性袱结,需要改變目錄和修改權(quán)限亮隙。同時,需要關(guān)閉原來不需要的文件描述符垢夹。過程:fork-->setsid-->chdir-->umask-->close

作業(yè)控制

Shell分前后臺來控制的不是進(jìn)程而是作業(yè)(Job)或者進(jìn)程組(Process Group)溢吻。一個前臺作業(yè)可以由多個進(jìn)程組成,一個后臺作業(yè)也可以由多個進(jìn)程組成果元,Shell可以同時運行一個前臺作業(yè)和任意多個后臺作業(yè)促王,這稱為作業(yè)控制(Job Control)

$ proc1 | proc2 &
$ proc3 | proc4 | proc5

其中proc1和proc2屬于同一個后臺進(jìn)程組,proc3而晒、proc4蝇狼、proc5屬于同一個前臺進(jìn)程組,Shell進(jìn)程本身屬于一個單獨的進(jìn)程組倡怎。這些進(jìn)程組的控制終端相同迅耘,它們屬于同一個Session,一個Session與一個控制終端相關(guān)监署。當(dāng)用戶在控制終端輸入特殊的控制鍵(例如Ctrl-C)時颤专,內(nèi)核會發(fā)送相應(yīng)的信號(例如SIGINT)給前臺進(jìn)程組的所有進(jìn)程。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

// 守護(hù)進(jìn)程初始化函數(shù)
void init_daemon()
{
    pid_t pid;
    int i = 0;

    if ((pid = fork()) == -1) {
        printf("Fork error !\n");
        exit(1);
    }
    if (pid != 0) {
        exit(0);        // 父進(jìn)程退出
    }

    setsid();           // 子進(jìn)程開啟新會話钠乏,并成為會話首進(jìn)程和組長進(jìn)程
    if ((pid = fork()) == -1) {
        printf("Fork error !\n");
        exit(-1);
    }
    if (pid != 0) {
        exit(0);        // 結(jié)束第一子進(jìn)程栖秕,第二子進(jìn)程不再是會話首進(jìn)程
    }
    chdir("/tmp");      // 改變工作目錄
    umask(0);           // 重設(shè)文件掩碼
    for (; i < getdtablesize(); ++i) {
       close(i);        // 關(guān)閉打開的文件描述符
    }

    return;
}

int main(int argc, char *argv[])
{
    int fp;
    time_t t;
    char buf[] = {"This is a daemon:  "};
    char *datetime;
    int len = 0;

    // 初始化 Daemon 進(jìn)程
    init_daemon();

    // 每隔一分鐘記錄運行狀態(tài)
    while (1) {
        if (-1 == (fp = open("/tmp/daemon.log", O_CREAT|O_WRONLY|O_APPEND, 0600))) {
          printf("Open file error !\n");
          exit(1);
        }
        len = strlen(buf);
        write(fp, buf, len);
        t = time(0);
        datetime = asctime(localtime(&t));
        len = strlen(datetime);
        write(fp, datetime, len);
        close(fp);
        sleep(60);
    }

    return 0;
}
出錯記錄

出錯記錄提出來主要是解決守護(hù)進(jìn)程的錯誤消息記錄問題,因為守護(hù)進(jìn)程沒有自己的終端顯示晓避,但若是每個守護(hù)進(jìn)程都維護(hù)一個自己記錄文件就很麻煩累魔,需要有一個集中的守護(hù)進(jìn)程出錯記錄設(shè)施。
在linux中使用syslog進(jìn)行記錄够滑。

后臺進(jìn)程job與守護(hù)進(jìn)程區(qū)別
后臺進(jìn)程一般不需要交互垦写,啟動時加一個 & 就可以,會輸出相應(yīng)的job ID.
對切換到后臺的進(jìn)程彰触,ps可以查看到梯投,也可以通過 jobs命令只查看所有后臺進(jìn)程。
而守護(hù)進(jìn)程永遠(yuǎn)都以后臺方式啟動况毅,ps -a無法查看到分蓖,ps xj輸出中TPGID為-1就是守護(hù)進(jìn)程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尔许,一起剝皮案震驚了整個濱河市么鹤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌味廊,老刑警劉巖蒸甜,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棠耕,死亡現(xiàn)場離奇詭異,居然都是意外死亡柠新,警方通過查閱死者的電腦和手機窍荧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來恨憎,“玉大人蕊退,你說我怎么就攤上這事°究遥” “怎么了瓤荔?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長钥组。 經(jīng)常有香客問我输硝,道長,這世上最難降的妖魔是什么者铜? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮放椰,結(jié)果婚禮上作烟,老公的妹妹穿的比我還像新娘。我一直安慰自己砾医,他們只是感情好拿撩,可當(dāng)我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著如蚜,像睡著了一般压恒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上错邦,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天探赫,我揣著相機與錄音,去河邊找鬼撬呢。 笑死伦吠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的魂拦。 我是一名探鬼主播毛仪,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼芯勘!你這毒婦竟也來了箱靴?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤荷愕,失蹤者是張志新(化名)和其女友劉穎衡怀,沒想到半個月后棍矛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡狈癞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年茄靠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝶桶。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡慨绳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出真竖,到底是詐尸還是另有隱情脐雪,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布恢共,位于F島的核電站战秋,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏讨韭。R本人自食惡果不足惜脂信,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望透硝。 院中可真熱鬧狰闪,春花似錦、人聲如沸濒生。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽罪治。三九已至丽声,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間觉义,已是汗流浹背雁社。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留晒骇,地道東北人歧胁。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像厉碟,于是被迫代替她去往敵國和親喊巍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容