zoukankan      html  css  js  c++  java
  • 【linux高级程序设计】(第八章)进程管理与程序开发 5

    守候进程

    启动方式:

    •   在系统启动时由/etc/rd.d目录下的启动脚本启动
    •   利用inetd超级服务器启动
    •   有cron命令定时启动,以及在终端用nohup命令启动

    守护进程编程要点

    (1)屏蔽有关控制终端操作的信号,防止守护进程正常启动之前,控制终端受到干扰退出或挂起。

    for(i = 1; i <= 31; i++)
        signal(SIGTTOU, SIG_IGN); //忽略所有可以忽略的信号,STGSTOP和SIGKILL不能忽略

    (2)在后台运行,为了避免挂起控制终端。方法在进程中创建子进程,并使父进程终止。

    if(pid = fork())
        exit(0);      //父进程结束,子进程继续

    (3)脱离控制终端和进程组。用setsid()使子进程成为新的会话组长,彻底脱离从父进程继承下来的控制终端的影响

    setsid();

    (4)禁止进程重新打开控制终端。只有会话组长能够打开终端,再创建一个子进程,并让父进程退出,这样子进程就不是会话组长了。

    if(pid = fork())
        exit(0);      //父进程结束,子进程继续

    (5)关闭打开的文件描述符。一般,不需要从父进程那继承来的文件描述符。

    #define NOFILE 256  //不同系统有不同限制
    for(i = 0; i < NOFILE; i++)   //关闭打开的文件描述符
        close(i);

    (6)改变当前工作目录。进程活动时,其工作目录所在的文件系统不能卸载。故需要将守候进程的工作目录改变到合适的目录

    chdir("/tem");

    (7)重设文件创建掩码。防止修改守护进程所创建文件的存储权限

    umask(0);

    (8)处理SIGCHLD信号(子进程退出信号)。让系统帮助回收僵死进程资源

    signal(SIGCHLD, SIG_IGN);

    守候进程两种写日志信息的方式

    (1)进程直接与日志文件建立联系,即open一个文件,然后write写文件

    (2)使用日志守候进程syslogd

    void openlog (__const char *__ident, int __option, int __facility):打开当前程序与日志守候进程之间的联系。

      参数1:要向每个消息加入的字符串,一般为当前进程名

      参数2:描述已打开选项

      参数3:消息类型,决定将消息写入那个日志文件中

    void closelog(void):关闭与日志守候进程的联系

    void syslog (int __pri, __const char * __fmt, ...) :写一条日志信息

      参数1:决定日志级别 0系统不可用,1必须立刻报告的 2冲突 3错误 4警告 5普通担忧特殊标识 6消息 7调度级

      参数2:日志输出格式,类似printf的第二个参数

    int setlogmask (int __mask) :设置当前进程syslog()函数输出消息的默认优先级

    守候进程例子

    #include<unistd.h>
    #include<signal.h>
    #include<fcntl.h>
    #include<sys/syslog.h>
    #include<sys/param.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<stdio.h>
    #include<stdlib.h>
    
    int init_daemon(const char *pname, int facility)
    {
        int pid;
        int i;
        signal(SIGTTOU, SIG_IGN);  //处理可能的终端信号
        signal(SIGTTIN, SIG_IGN); 
        signal(SIGTSTP, SIG_IGN); 
        signal(SIGHUP, SIG_IGN); 
        
        if(pid = fork())  //创建子进程,父进程退出
            exit(EXIT_SUCCESS);
        else if(pid < 0)
        {
            perror("fork");
            exit(EXIT_FAILURE);
        }
        setsid(); //设置新会话组长
        if(pid = fork())  //创建子进程,父进程退出
            exit(EXIT_SUCCESS);
        else if(pid < 0)
        {
            perror("fork");
            exit(EXIT_FAILURE);
        }
        for(i = 0; i < NOFILE; ++i)     //关闭父进程打开的文件描述符
            close(i);
        open("/dev/null", O_RDONLY);  //对标准输入输出全部重定向到/dev/null
        open("/dev/null", O_RDWR);
        open("/dev/null", O_RDWR);
        
        chdir("/tmp");  //修改主目录
        umask(0);  //重新设置文件掩码
        signal(SIGCHLD, SIG_IGN);  //处理子进程退出
        openlog(pname, LOG_PID, facility);  //与守候进程建立联系,加上进程号,文件名
        return;
    }
    
    int main(int argc, char * argv[])
    {
        FILE *fp;
        time_t ticks;
        init_daemon(argv[0], LOG_KERN); //执行守候进程函数
        while(1)
        {
            sleep(1);
            ticks = time(NULL); //获取当前时间
            syslog(LOG_INFO, "%s", asctime(localtime(&ticks))); //写日志信息
        }
    }

    可以看到,守候进程在后台运行

    运行后我找不到日志写哪了?

    还有很奇怪的一点,之后每次我用ps aux|grep Daemon_exp 进程号都会加2 ?

  • 相关阅读:
    NLP-Progress记录NLP最新数据集、论文和代码: 助你紧跟NLP前沿
    深度学习、图像识别入门,从VGG16卷积神经网络开始
    反向传播神经网络极简入门
    R语言中的遗传算法详细解析
    模拟退火算法
    TensorFlow利用A3C算法训练智能体玩CartPole游戏
    伯克利推出「看视频学动作」的AI智能体
    深度强化学习资源介绍
    Introducing Deep Reinforcement
    库、教程、论文实现,这是一份超全的PyTorch资源列表(Github 2.2K星)
  • 原文地址:https://www.cnblogs.com/dplearning/p/4679925.html
Copyright © 2011-2022 走看看