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

首頁 > 學院 > 操作系統 > 正文

服務器編程入門(12) 守護進程

2024-06-28 13:27:04
字體:
來源:轉載
供稿:網友
服務器編程入門(12) 守護進程

摘要:

    在之前的《服務器編程入門(5)linux服務器程序規范》中,我們提到過將服務器程序后臺化,這就是本節將要討論的守護進程. 

    本節主要關注一下問題:  

    1 什么是守護進程?

    2 守護進程的啟動方法有哪些?

    3 如何創建一個守護進程?


1 什么是守護進程?

在后臺運行,且不與任何控制終端關聯的進程。

守護進程不與作業控制、終端會話管理、終端產生信號等發生交互,也可以避免在后臺運行的守護進程非預期地輸出到終端。

兩個特點:

  • 守護進程執行中的信息不顯示在任何一個終端上
  • 守護進程不被終端產生的無用信號所中斷

在理解更多關于守護進程的概念之前,我們先了解一下進程、進程組、會話期和控制終端的關系

  • 每一個進程有一個進程ID,每個進程都屬于一個進程組
  • 每個進程組有一個組長進程組長進程的ID等于進程組ID
  • 會話期是一個或多個進程組的集合,一個會話期可以有一個單獨的控制終端(其中,只有一個前臺進程組可以控制終端的交互)
  • 從shell中啟動的每個進程將繼承一個終端,以便進程與用戶交互,同時繼承父進程的會話期和進程組ID,因此子進程會受發給該會話期或進程組的信號的影響。

守護進程與普通進程的區別如下圖所示:

守護進程

 


2 守護進程的啟動方法有哪些?
  1. 在系統啟動階段,許多守護進程又系統初始化腳本啟動。這些腳本通常位于/etc目錄或以/etc/rc開頭的某個目錄中。由這些腳本啟動的守護進程一開始時就擁有超級用戶特權。
  2. 許多網絡服務器由inetd超級服務器啟動。
  3. cron守護進程按照規則定期執行一些程序。由它啟動執行的程序同樣作為守護進程運行。
  4. at命令用于指定將來某個時刻運行程序,由它啟動的程序同樣作為守護進程。
  5. 從用戶終端或前臺或后臺啟動。

3 使用庫函數daemon創建守護進程

首先我們使用庫函數daemon創建守護進程,然后研究一下守護進程的創建過程,并實現一個守護進程化函數,達到和庫函數daemon相同的效果。

函數:daemon

聲明:

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

作用:通過在服務器程序中調用它,可以把一個普通進程轉變為守護進程。

參數說明:

If nochdir is zero, daemon()  changes  the  PRocess’s  current  working directory to the root directory ("/"); otherwise,

If  noclose is zero, daemon() redirects standard input, standard output and standard error to /dev/null; otherwise,  no  changes  are  made  to these file descriptors.

Demo:

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <time.h>#include <fcntl.h>#include <string.h>#include <error.h>int main(int argc, char* argv[]) {    time_t t;    int fd;        // 將當前進程變成守護進程    if (daemon(0, 0) == -1) {        perror("daomon error");        exit(EXIT_FAILURE);    }    while(1) {        //這時工作目錄已經被daemon函數切換到了系統根目錄下        fd = open("daemon.log", O_WRONLY|O_CREAT|O_APPEND, 0644);           if (fd == -1) {            perror("open daemon.log error");            exit(EXIT_FAILURE);        }        t = time(0);        char *buf = asctime(localtime(&t));        write(fd, buf, strlen(buf));     //向daemon.log文件中寫入當前時間        close(fd);        sleep(60);    // 每隔60s寫入一次    }}

運行截圖:

image

執行ps命令發現,并沒有名為testDaemon的守護進程,主要原因是daemon函數會將當前工作目錄切換到/目錄下,而普通用戶沒有權限在系統根目錄創建文件。

所以實際上出錯在fd = open("daemon.log", O_WRONLY|O_CREAT|O_APPEND, 0644); 這里,又因為守護進程是不和當前終端交互的,所以沒有看到報錯信息。

現在我們切換到root用戶執行程序,運行截圖:

image

 


4 創建守護進程過程分析,用自己實現的myDaemon函數創建守護進程

守護進程創建過程:

守護進程創建流程

代碼實現:

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <time.h>#include <fcntl.h>#include <string.h>#include <error.h>#include <signal.h>#define MAXFD 64extern int daemon_proc;int myDaemon(int ,int );int main(int argc, char* argv[]) {    time_t t;    int fd;        if (myDaemon(0, 0) == -1) {        perror("daomon error");        exit(EXIT_FAILURE);    }    while(1) {        fd = open("daemon.log", O_WRONLY|O_CREAT|O_APPEND, 0644);        if (fd == -1) {            perror("open daemon.log error");            exit(EXIT_FAILURE);        }        t = time(0);        char *buf = asctime(localtime(&t));        write(fd, buf, strlen(buf));        close(fd);        sleep(60);    }    fprintf(stderr,            "Hello world!/n");}int myDaemon(int nochdir, int noclose) {    int i;    pid_t pid;    if ( (pid = fork()) < 0 )        return -1;    else if (pid) {        /* parent terminated */        _exit(0);    }    /* child 1 continues... */    if (setsid() < 0)     /* become session leader */        return -1;    signal(SIGHUP, SIG_IGN);    /* ignore SIGHUP singal */    if ( (pid = fork()) < 0 )        return -1;    else if (pid) {        _exit(0);         /* child 1 terminated */    }    /* child 2 continues... */    daemon_proc = 1;      /* use syslog instead of fprintf to stderr */        if (nochdir == 0)        chdir("/");           /* change working directory */        if (noclose == 0) {        /*close off file descriptors*/        for (i = 0; i < MAXFD; i++)            close(i);            /* redirect stdin, stdout, and stderr to /dev/null */        open("/dev/null", O_RDONLY);        open("/dev/null", O_RDWR);            open("/dev/null", O_RDWR);    }    umask(0);}

 

運行截圖:

image

 

 

 

 

參考資料:

《UNIX網絡編程 卷1:套接字聯網API(第3版)》

linux系統編程之進程(八):守護進程詳解及創建,daemon()使用Linux內核中的進程組及會話
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 江油市| 江都市| 兴和县| 布尔津县| 大渡口区| 江阴市| 老河口市| 肇东市| 安宁市| 鄢陵县| 广宗县| 南召县| 紫阳县| 达日县| 富平县| 合江县| 兴城市| 弥勒县| 靖宇县| 中江县| 石柱| 绥德县| 辽中县| 建湖县| 平度市| 琼结县| 廊坊市| 宣城市| 苍山县| 双牌县| 上林县| 泸西县| 浏阳市| 淳安县| 长葛市| 三河市| 建德市| 兴城市| 体育| 镇宁| 永仁县|