Unix環境高級編程筆記 :1三、守護進程

1 守護進程
    守護進程也稱精靈進程(daemon)是生存期較長的一種進程。它們經常在系統自舉時啓動,僅在系統關閉時才終止。
    由於沒的控制終端,因此它們是在後臺運行的。
 
二、守護進程特徵
    父進程ID爲0的各進程通用是內核進程,它們做爲系統自舉過程當中的一部分啓動
    內核進程是特殊的,通用存在於系統的整個生命週期。它們以超級用戶特權運行,無控制終端,無命令行。
 
    進程1一般是init,它是一個系統守護進程,負責啓動各運行層次特定的系統服務。
 
    portmap網絡端口映射服務
    syslogd守護進程把系統消息記入日誌的任何程序使用
    xinted 偵聽網絡接口,取得來自網絡的對各類網絡服務進程的請求。  nfsd lockd rpciod
    cron
 
三、編程規則
    1)umask將文件模式建立屏蔽字設置爲0    
    2)調用fork,而後使父進程退出
    3)調用setsid以建立一個新會話
    4) 將當前工做目錄更改成根目錄
    5)關閉再也不須要的文件描述符
    6)某些守護進程打開/dev/null使其具備文件描述符0、一、2,這樣任何一個試圖讀標準輸入、寫標準輸出或標準出錯的庫例程都不會產生任何效果。
    
 
daemonize.c  想初始化成爲一個守護進程的程序調用。    
#include <stdio.h>
#include <syslog.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
 
void daemonize(const char *cmd) {
int i,fd0,fd1,fd2;
pid_t pid;
struct rlimit r1;
struct sigaction sa;
 
umask(0);
 
if(getrlimit(RLIMIT_NOFILE,&r1) < 0) {
printf("%s:can`t get file limit",cmd);
exit(1);
}
if(pid=fork()) < 0) {
printf("%s:can`t fork",cmd);
} else if(pid !=0) {
exit(0);
}
 
setsid();
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if(sigaction(SIGHUP,&sa,NULL) <0) {
printf("%s:can`t ignore SIGHUP");
exit(1)
}
if((pid = fork)) < 0) {
printf("%s:can`t fork")
exit(1);
}
else if(pid != 0) {
exit(0)
}
 
if(chdir("/") < 0) {
printf("%s:can`t change directory to /");
exit(1);
}
 
if(r1.rlim_max == RLIM_INFINITY)
r1.rlim_max = 1024;
for(i=0;i<r1.rlim_max;i++) {
close(i);
}
 
 
fd0 = open("/dev/null",O_RDWR);
fd1 = dup(0);
fd2 = dup(0);
 
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);
}
}
 
#include <unistd.h>
int daemon(int nochdir,int noclose);
 
在建立精靈進程的時候,每每須要將精靈進程的工做目錄修改成"/"根目錄 
而且將標準輸入,輸出和錯誤輸出重定向到/dev/null 

daemon的做用就是當參數nochdir爲0時,將根目錄修改成工做目錄 
noclose爲0時,作輸入,輸出以及錯誤輸出重定向到/dev/null 
 
#include <unistd.h>
int main(int argc, char *argv[])
{
    ...
    if (daemon(0, 0)) {//調用glibc庫函數daemon,建立daemon守護進程
        perror("daemon");
        return -1;
    }
    好了執行到這裏的就是daemon的子進程了[luther.gliethttp].
    ...
}
 
四、出錯記錄
    三種方式產生日誌消息
    1)內核例程能夠調用log函數
    2)用戶進程(守護進程)調用syslog(3)函數以產生日誌消息
    3)在此主機上的一個用戶進程
 
    #include <syslog.h>
    openlog
    syslog
    closelog
    setlogmask
相關文章
相關標籤/搜索