zoukankan      html  css  js  c++  java
  • 守护进程

    简介

    守护线程在系统启动时运行,在系统终止时退出,没有控制终端,只在后台作为一个服务默默运行

    编写规则

    1.调用umask()设置文件创建时的权限规则
    2.调用fork, 然后使父进程exit
    3.调用setsid创建一个新会话
    4.将系统根目录设置为当前工作目录
    5.关闭不再需要的文件描述符
    6.将0,1,2标准输入输出重定向到/dev/null

    出错记录

    void openlog(const char *ident, int option, int facility)

    ident会被记录在日志内, 作为与其它进程记录的区分

    void syslog(int priority, const char *format, ...);

    priority表示等级, 如消息/警告/出错等;
    第二个参数表示可以进行格式化, 所有%m字符被会被自动替换成strerror(errno)表示的字符串

    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <syslog.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <sys/resource.h>
     
    void daemonize(const char *cmd){
        int i,fd0,fd1,fd2;
        pid_t pid;
        struct rlimit rl;
        struct sigaction sa;
     
        umask(0);
     
        if(getrlimit(RLIMIT_NOFILE,&rl) < 0){
            perror("getrlimit failed");
            exit(1);
        }
     
        if((pid=fork()) <0 ){
            perror("fork failed");
            exit(1);
        }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){
            perror("sigaction failed");
            exit(1);
        }
        if((pid=fork())<0){
            perror("fork failed");
            exit(1);
        }else if(pid != 0)
            exit(0);
     
        if(chdir("/")<0){
            perror("chdir error");
            exit(1);
        }
     //关闭所有打开的文件描述符, 包括stdin/stdout/stderr
        if(rl.rlim_max == RLIM_INFINITY)
            rl.rlim_max=1024;
        for(i=0;i<rl.rlim_max;i++)
            close(i);
     //由于上面已经关闭所有文件描述符, 所以新建文件描述符时会从0开始计数, 于是fd0=0,依次fd1=1,fd2=2
        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 description %d %d %d", fd0, fd1, fd2);
            exit(1);
        }
    }
     
    int main(){
       daemonize("io.c");
       return 0; 
    

    单例模式

    单例模式: 一个软件在系统只能运行一个实例, 不能同时运行两个或多个
    方法: 创建一个文件并加锁, 第一个实例运行时没问题, 第二实例运行时会因为对文件加锁失败而退出

    #include <unistd.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <syslog.h>
    #include <string.h>
    #include <errno.h>
    #include <stdio.h>
    #include <sys/stat.h>
     
    #define LOCKFILE "/var/run/daemon.pid"
    #define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
     
    int lockfile(int fd){
        struct flock fl;
     
        fl.l_type=F_WRLCK;
        fl.l_start=0;
        fl.l_whence=SEEK_SET;
        fl.l_len=0;
        return(fcntl(fd,F_SETLK,&fl));
    }
     
    int already_running(){
        int fd;
        char buf[16];
     
        fd=open(LOCKFILE,O_RDWR|O_CREAT,LOCKMODE);
        if(fd<0){
            syslog(LOG_ERR,"can't open %s: %s",LOCKFILE,strerror(errno));
            exit(1);
        }
     
        if(lockfile(fd)<0){
            if(errno==EACCES || errno == EAGAIN){
                close(fd);
                return 1;
            }
            syslog(LOG_ERR,"can't lock %s: %s",LOCKFILE,strerror(errno));
            exit(1);
        }
        ftruncate(fd,0);
        sprintf(buf,"%ld",(long)getpid());
        write(fd,buf,strlen(buf)+1);
        return 0;
    }
     
    int main(){
        int ret;
        ret=already_running();
    //第二个实例会打印already running,然后退出
        if(ret == 1){
            printf("already running 
    ");
            exit(0);
        }
    //第一个实例一直运行
        while(1){
            printf("from %ld 
    ",(long)getpid());
            sleep(2);
        }
        return 0;
    }
    

    单线程单例守护进程

    如果守护线程的文件是锁文件, 一般存储在/var/run目录, 名称的形式多为name.pid
    如果文件是配置文件, 一般存储在/etc目录, 名称的形式为name.conf
    当配置文件修改后, 需手动发送sighup信号给后台进程: kill -SIGHUP xxx

    #include <unistd.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <syslog.h>
    #include <string.h>
    #include <errno.h>
    #include <stdio.h>
    #include <signal.h>
    #include <sys/stat.h>
    #include <sys/resource.h>
     
    #define LOCKFILE "/var/run/daemon.pid"
    #define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
    void daemonize(const char *cmd){ //同上
        ... 
    }
     
    int lockfile(int fd){ //同上
        ...
    }
     
    int already_running(){ //同上
       ...
    }
     
    void reread(){
        int fd;
        fd=open(LOCKFILE,O_RDONLY);
        if(fd<0){
            syslog(LOG_ERR,"can't open %s: %s",LOCKFILE,strerror(errno));
            exit(1);
        }
        char buf[100]={0};
        int nread;
        if((nread=read(fd,buf,100))>0)
            syslog(LOG_INFO,"file content change to %s",buf);
    }
    void sigterm(int signo){
        syslog(LOG_INFO,"got SIGTERM; exiting");
        exit(0);
    }
    void sighup(int signo){
        syslog(LOG_INFO,"Re-reading configuration file");
        reread();
    }
    int main(){
        char *cmd="daemonize test";
        daemonize(cmd);
     
        if(already_running()){
            syslog(LOG_ERR,"daemon already running");
            exit(1);
        }
     
        struct sigaction sa;
        sa.sa_handler=sigterm;
        sigemptyset(&sa.sa_mask);
        sigaddset(&sa.sa_mask,SIGHUP);
        sa.sa_flags=0;
        if(sigaction(SIGTERM,&sa,NULL)<0){
            syslog(LOG_ERR,"can't catch SIGTERM: %s",strerror(errno));
            exit(1);
        }
        sa.sa_handler=sighup;
        sigemptyset(&sa.sa_mask);
        sigaddset(&sa.sa_mask,SIGTERM);
        sa.sa_flags=0;
        if(sigaction(SIGHUP,&sa,NULL)<0){
            syslog(LOG_ERR,"can't catch SIGHUP: %s",strerror(errno));
            exit(1);
        }
     
    //业务写这里
        while(1){
            sleep(5);
        }
        exit(0);
    }
    
  • 相关阅读:
    2013-2014-2(复变函数56)
    2015-2016-1(实变函数56)
    2014-2015-2(常微分方程64, 数学分析提高64)
    2015-2016-2(点集拓扑56, 点集拓扑56)
    2016-2017-2(点集拓扑56, 点集拓扑56)
    2016-2017-1(实变函数56, 点集拓扑56)
    2017-2018-1(实变函数56, 点集拓扑56)
    2013-2014 指导2014届毕业生8名(48)
    2015-2016 指导2016届毕业生8名(48)
    2014-2015 指导2015届毕业生8名(48)
  • 原文地址:https://www.cnblogs.com/cfans1993/p/5643357.html
Copyright © 2011-2022 走看看