国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 服務(wù)器 > Linux服務(wù)器 > 正文

Linux的守護(hù)進(jìn)程簡介

2024-09-05 23:02:21
字體:
供稿:網(wǎng)友
1. 守護(hù)進(jìn)程簡介

守護(hù)進(jìn)程也稱精靈進(jìn)程是生存期長的一種進(jìn)程,它們常常在系統(tǒng)引導(dǎo)裝入時啟動,在系統(tǒng)管比時終止.精靈進(jìn)程沒有控制終端,它們是在后臺運(yùn)行的.守護(hù)進(jìn)程是一種很有用的進(jìn)程.Linux的大多數(shù)服務(wù)器就是用守護(hù)進(jìn)程實(shí)現(xiàn)的.比如,Internet服務(wù)器inetd,Web服務(wù)器httpd等.同時,守護(hù)進(jìn)程完成許多系統(tǒng)任務(wù).比如,作業(yè)規(guī)劃進(jìn)程crond,打印進(jìn)程lpd等.

所有精靈進(jìn)程都以超級用戶(用戶ID為0)的優(yōu)先權(quán)運(yùn)行.沒有一個精靈進(jìn)程具有控制終端—控制名稱設(shè)置為問號、終端前臺進(jìn)程組ID設(shè)置為-1.除update以外的所有精靈進(jìn)程都是組的首進(jìn)程,對話期的首進(jìn)程,是這些進(jìn)程組和對話期中的唯一進(jìn)程.的精靈進(jìn)程的父進(jìn)程都是init進(jìn)程.

守護(hù)進(jìn)程最重要的特性是后臺運(yùn)行.在這一點(diǎn)上DOS下的常駐內(nèi)存程序TSR與之相似.其次,守護(hù)進(jìn)程與其運(yùn)行前的環(huán)境隔離開來.這些環(huán)境包括未關(guān)閉的文件描述符,控制終端,會話和進(jìn)程組,工作目錄以及文件創(chuàng)建掩模等.這些環(huán)境通常是守護(hù)進(jìn)程從執(zhí)行它的父進(jìn)程(特別是shell)中繼承下來的.,守護(hù)進(jìn)程的啟動方式有其特殊之處.它可以在Linux系統(tǒng)啟動時從啟動腳本/etc/rc.d中啟動,可以由作業(yè)規(guī)劃進(jìn)程crond啟動,還可以由用戶終端(通常是shell)執(zhí)行.

2. 建立守護(hù)進(jìn)程關(guān)鍵步驟

創(chuàng)建一個守護(hù)進(jìn)程,有幾個關(guān)鍵的步驟,也有幾個地方需要注意,

幾個關(guān)鍵的步驟有:

1:清除文件創(chuàng)建權(quán)限

2:調(diào)用fork,然后使父進(jìn)程退出

3:調(diào)用setsid以創(chuàng)建一個新的會話,有三個目的使調(diào)用進(jìn)程 a:成為新會話的首進(jìn)程,b:成為新進(jìn)程的組長進(jìn)程,c:沒有控制終端

4:切換工作目錄

5:關(guān)閉不需要的文件描述符

6:某些守護(hù)進(jìn)程打開/dev/null使其具有文件描述符0,1,2這樣任何一個試圖讀標(biāo)準(zhǔn)輸入寫標(biāo)準(zhǔn)輸出或標(biāo)準(zhǔn)出錯的庫歷程都不會產(chǎn)生任何效果.

需要注意的地方

1:守護(hù)進(jìn)程沒有控制終端,不能與標(biāo)準(zhǔn)輸入輸出出錯進(jìn)行交互,不能使用printf,通常用syslog來解決守護(hù)進(jìn)程的打印信息

3. 建立守護(hù)進(jìn)程詳細(xì)步驟

1. 在后臺運(yùn)行.

為避免掛起控制終端將Daemon放入后臺執(zhí)行.方法是在進(jìn)程中調(diào)用fork使父進(jìn)程終止,讓Daemon在子進(jìn)程中后臺執(zhí)行.

if(pid=fork())

exit(0);//是父進(jìn)程,結(jié)束父進(jìn)程,子進(jìn)程繼續(xù)

2. 脫離控制終端,登錄會話和進(jìn)程組

有必要先介紹一下Linux中的進(jìn)程與控制終端,登錄會話和進(jìn)程組之間的關(guān)系:進(jìn)程屬于一個進(jìn)程組,進(jìn)程組號(GID)就是進(jìn)程組長的進(jìn)程號(PID).登錄會話可以包含多個進(jìn)程組.這些進(jìn)程組共享一個控制終端.這個控制終端通常是創(chuàng)建進(jìn)程的登錄終端.
控制終端,登錄會話和進(jìn)程組通常是從父進(jìn)程繼承下來的.我們的目的就是要擺脫它們,使之不受它們的影響.方法是在第1點(diǎn)的基礎(chǔ)上,調(diào)用setsid()使進(jìn)程成為會話組長:

setsid();

說明:當(dāng)進(jìn)程是會話組長時setsid()調(diào)用失敗.但第一點(diǎn)已經(jīng)保證進(jìn)程不是會話組長.setsid()調(diào)用成功后,進(jìn)程成為新的會話組長和新的進(jìn)程組長,并與原來的登錄會話和進(jìn)程組脫離.會話過程對控制終端的獨(dú)占性,進(jìn)程同時與控制終端脫離.

3. 禁止進(jìn)程重新打開控制終端

現(xiàn)在,進(jìn)程已經(jīng)成為無終端的會話組長.但它可以重新申請打開一個控制終端.可以通過使進(jìn)程不再成為會話組長來禁止進(jìn)程重新打開控制終端:

if(pid=fork())

exit(0);//結(jié)束第一子進(jìn)程,第二子進(jìn)程繼續(xù)(第二子進(jìn)程不再是會話組長)

4. 關(guān)閉打開的文件描述符

進(jìn)程從創(chuàng)建它的父進(jìn)程那里繼承了打開的文件描述符.如不關(guān)閉,將會浪費(fèi)系統(tǒng)資源,造成進(jìn)程所在的文件系統(tǒng)無法卸下以及引起無法預(yù)料的錯誤.按如下方法關(guān)閉它們:

for(i=0;i<= max;i ) close(i);

5. 改變當(dāng)前工作目錄

進(jìn)程活動時,其工作目錄所在的文件系統(tǒng)不能卸下.一般需要將工作目錄改變到根目錄.對于需要轉(zhuǎn)儲核心,寫運(yùn)行日志的進(jìn)程將工作目錄改變到特定目錄如/tmp,chdir("/")

6. 重設(shè)文件創(chuàng)建掩模

進(jìn)程從創(chuàng)建它的父進(jìn)程那里繼承了文件創(chuàng)建掩模.它可能修改守護(hù)進(jìn)程所創(chuàng)建的文件的存取位.為防止這一點(diǎn),將文件創(chuàng)建掩模清除:umask(0);

7. 處理SIGCHLD信號

處理SIGCHLD信號并不是的.但對于某些進(jìn)程,特別是服務(wù)器進(jìn)程往往在請求到來時生成子進(jìn)程處理請求.如果父進(jìn)程不等待子進(jìn)程結(jié)束,子進(jìn)程將成為僵尸進(jìn)程(zombie)從而占用系統(tǒng)資源.如果父進(jìn)程等待子進(jìn)程結(jié)束,將增加父進(jìn)程的負(fù)擔(dān),影響服務(wù)器進(jìn)程的并發(fā)性能.在Linux下可以簡單地將 SIGCHLD信號的操作設(shè)為SIG_IGN.

signal(SIGCHLD,SIG_IGN);

這樣,內(nèi)核在子進(jìn)程結(jié)束時不會產(chǎn)生僵尸進(jìn)程.這一點(diǎn)與BSD4不同,BSD4下顯式等待子進(jìn)程結(jié)束才能釋放僵尸進(jìn)程.

4. 參考代碼

1.

#include <signal.h>

#include <stdlib.h>

#include <syslog.h>

#include <fcntl.h>

#include <stdio.h>

#include <sys/resource.h>

void daemonize(const char *cmd)

{

int i, fd0, fd1, fd2;
pid_t pid;

struct rlimit rl;

struct sigaction sa;

/*

* Clear file creation mask.

*/

umask(0);

/*

Get maximum number of file descriptors.

*/

if (getrlimit(RLIMIT_NOFILE, &rl) < 0)

printf("%s: can't get file limit", cmd);

/*

* Become a session leader to lose controlling TTY.

*/

if ((pid = fork()) < 0)

printf("%s: can't fork", cmd);

else if (pid != 0) /* parent */

exit(0);

setsid();

/*

* Ensure future opens won't allocate controlling TTYs.

*/

sa.sa_handler = SIG_IGN;

sigemptyset(&sa.sa_mask);

sa.sa_flags = 0;

if (sigaction(SIGHUP, &sa, NULL) < 0)

printf("can't ignore SIGHUP");

if ((pid = fork()) < 0)

printf("%s: can't fork", cmd);

else if (pid != 0) /* parent */

exit(0);

/*

* Change the current working directory to the root so

* we won't prevent file systems from being unmounted.

*/

if (chdir("/") < 0)

printf("can't change directory to /");

/*

* Close all open file descriptors.

*/

if (rl.rlim_max == RLIM_INFINITY)

rl.rlim_max = 1024;

for (i = 0; i < rl.rlim_max; i )

close(i);

/*

* Attach file descriptors 0, 1, and 2 to /dev/null.

*/

fd0 = open("/dev/null", O_RDWR);

fd1 = dup(0);

fd2 = dup(0);

/*

* Initialize the log file.

*/

openlog(cmd, LOG_CONS, LOG_DAEMON);

if (fd0 != 0 || fd1 != 1 || fd2 != 2) {

syslog(LOG_ERR, "unexpected file descriptors %d %d %d",fd0, fd1, fd2);

exit(1);

}

syslog(LOG_DEBUG, "daem ok ");

}

int main()

{

daemonize("test");

while(1);//守護(hù)進(jìn)程所要干的事情

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 邹城市| 霸州市| 芮城县| 鄂托克旗| 瓦房店市| 蛟河市| 织金县| 溧水县| 互助| 永定县| 广东省| 临漳县| 宜州市| 南涧| 勃利县| 达孜县| 新化县| 万源市| 静宁县| 石景山区| 淮安市| 九寨沟县| 邛崃市| 临沂市| 安新县| 荆门市| 澎湖县| 唐河县| 剑河县| 邵阳县| 大埔区| 漠河县| 汨罗市| 开封市| 绥宁县| 香河县| 高青县| 吉隆县| 鄂伦春自治旗| 象山县| 湖口县|