守護進程
進程組是一組進程的集合,進程組由進程組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 |