守護進程

守護進程
進程組是一組進程的集合,進程組由進程組PID表示
每一個進程除了進程id以外,還必須有一個進程組id,即必須屬於某個進程組
每一個進程組都有一個組長,其進程id就做爲進程組id,它不受進程組長的退出影響
通常來講,一個終端通常是進程組長。linux

會話期是由一個或多個進程組組成的集合
一個會話期開始於用戶登陸,結束於用戶退出。在此期間用戶運行的的全部進程都屬於這個會話期。centos

建立守護進程基本步驟
1.建立子進程
在終端輸入命令執行用戶程序時,該進程成爲父進程,它此時受控制終端即建立該進程的控制終端控制,經過它建立子進程
讓子進程脫離該終端的控制:子進程執行守護進程須要執行的代碼,而後讓父進程退出,此時子進程的父進程變爲了系統的Init進程。
當父進程先於子進程退出,子進程成爲孤兒進程。
在linux系統中,每當系統發現一個孤兒進程後,就會自動由1號進程(init進程) 收養它。
每一個進程在建立時都有其自身的進程組、會話期及所屬的控制終端,當建立子進程時,子進程複製父進程的這些屬性,所以父子進程屬於同一個進程組、會話期及控制終端
2.讓子進程脫離該終端的控制。當執行setsid()系統調用,使其脫離原終端控制。它建立一個新的會話並讓調用它的進程成爲該會話的組長,主要的3個做用
2.1 讓進程擺脫原會話的控制
2.2 讓進程擺脫原進程組的控制
2.3 讓進程擺脫原控制終端的控制
setsid()系統調用
3.改變當前目錄爲根目錄
每一個進程在執行時,都保存當前執行目錄的信息。子進程也繼承父進程的該信息
因爲在進程運行過程當中,當前目錄所在的文件系統是不能卸載的,
這對之後的使用會形成諸多的麻煩(如用戶要對不使用的目錄進行卸載操做,因爲該目錄還在被守護進程使用,因此umount出錯,致使該目錄不能被卸載)
一般的作法是讓系統根目錄"/" 做爲守護進程的的當前工做目錄,會避免上述沒必要要的問題。固然,若是有特殊須要也能夠把當前工做目錄換成其它的路勁
4.修改文件權限掩碼
文件掩碼是指屏蔽掉文件權限中的對應位。好比,一個文件的權限掩碼是050,其對應的二進制碼爲000101000 表示屏蔽文件用戶組用戶讀和執行的權限
因爲新建子進程繼承父進程的文件權限掩碼,這就給該子進程操做文件帶來諸多麻煩,所以,把文件權限掩碼設置成0,即取消子進程對文件操做的限制,
從而大大加強該守護進程的靈活性,即調用umask(0)
5.關閉文件描述符
同文件掩碼同樣,新建的子進程從父進程繼承已經打開的文件描述符。這些被打開的文件描述符可能永遠不會被守護進程讀寫,但它們一樣耗費系統資源,
並且可能致使文件系統沒法卸載。既然守護進程與控制終端失去了聯繫,所以與控制終端相關的文件描述符就不會被使用,如:文件描述符爲 0,1,2(輸入,輸出和出錯)
等文件描述符就不會被使用,失去存在的意義,要關閉它們,可以使用close(fd)方法函數

示例spa

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

#define MAXFILE 65535
char *timestr();
int main(){
    pid_t pc;
    char wtr[100];
    int i,fd,len;
    char *buf ="hello everybody!";
    len=strlen(buf);
    pc=fork();
    if(pc<0){
        printf("fork err\n");
        exit(1);
    }
    if(pc>0) exit(0);
    

    setsid();
    chdir("/");
    umask(0);
    for(i=0;i<MAXFILE;i++){
        while(1){
            if(fd= open("/tmp/daemon.log",O_CREAT|O_WRONLY|O_APPEND,0600)<0){
                perror("open");
                exit(1);
            }
            sprintf(wtr, "%s-%s\n",buf,timestr());
            write(fd,wtr,strlen(wtr)+1);
            close(fd);
            sleep(2);
        }
        
    }
}

char *timestr(){
    time_t timep;
    static char timestr[50];
      struct tm *p;
      time(&timep);
      p = gmtime(&timep);
      sprintf(timestr,"%d:%d:%d", p->tm_hour, p->tm_min, p->tm_sec);
      return timestr;
}

運行後code

[root@centos1 c]# ./daemon
hello everybody!-11:39:41
[root@centos1 c]# ^C
[root@centos1 c]# tail -f /tmp/daemon.log
hello everybody!-11:39:43
hello everybody!-11:39:45
hello everybody!-11:39:47
hello everybody!-11:39:49
hello everybody!-11:39:51
hello everybody!-11:39:53
hello everybody!-11:39:55

 

目標blog

建立新會話繼承

頭文件進程

#include <unistd.h>;#include <sys/types.h>ci

函數原型資源

pid_t pid=setsid(void)

返回值

出錯,返回-1

成功,返回該進程組的pid

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息