zoukankan      html  css  js  c++  java
  • linux系统编程之进程(五)

    今天继续学习系统编程,学习的主题还是进程,今天主要讨论的是守护进程相关的概念,开始进入正题:

    什么是守护进程:
     
     
     
    守护进程的创建步骤:
    在描述它之前,首先得先了解两个概念:进程组、会话期:
     
    而它里面有bash shell进程组,里面只有bash进程:
     
    这时,当我们在shell命令行中敲入如下命令:
    这时,会话期中又会多出一个进程组,如下:
    而一个会话期,实际上就对应一个终端,当我们打开多个虚拟终端时,可以用tty来查看终端数:
    守护进程是跟控制终端无关的,并且是在后台执行的,如果想让我们在shell中启动的进程变成守护进程,则应该将它放到会话期当中:
    那这时,我们需要一个创建新的会话期的函数,实际上是系统函数,它为setsid(),通过man来查看一下它的说明:
    这就意味着,我们在创建一个新的会话期之前,需要准备一个进程,保证该进程不是一个进程组组长,那如何保证呢?由于我们运行的shell命令的父进程可能是进程组组长,所以需要让父进程退出,这样就可以保证fork出来的子进程不是进程组组长,从而可以创建一个新的会话期了,总结一下上面说的流程:
    按照上面的步骤下面以具体代码来实现一个守护进程:
    #include <unistd.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <fcntl.h>
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <signal.h>
    
    
    #define ERR_EXIT(m) 
        do 
        { 
            perror(m); 
            exit(EXIT_FAILURE); 
        } while(0)
    
    int setup_daemon(void);
    
    int main(int argc, char *argv[])
    {
        return 0;
    }
    
    int setup_daemon(void)
    {
        pid_t pid;
        pid = fork();
        if (pid == -1)
            ERR_EXIT("fork error");
    
        if (pid > 0)//将父进程退出,保证子进程不是进程组组长
            exit(EXIT_SUCCESS);
    
        setsid();//如果走到这,代表是子进程,由于它不是一个进程组组长,所以可以创建一个新的会话期
        return 0;
        
    }

    当我们用setsid()创建一个新的会话期之后,会有一个什么样的影响呢,还是接着看它的说明介绍:

    也就是如下图所示:

     

    其实上面的程序就已经实现了一个守护进程,我们调用一下运行看下:

    编译运行:

    我们来查看下进程:

    守护进程通常是在系统运行而运行的,通常将当前目录改为根目录,因为有可能守护进程是在某个shell提示符下运行的, 那么当前目录就是shell提示符所在的目的, 就拿我们创建的这个守护进程而言,它的当前目录为:

    这样,系统管理员就无法umount这个目录,因为守护进程是学期在后期运行的,这个目录不应该作为它的环境,所以这就产生了创建守护进程的第四个步骤:

    修改代码:

    最后还有一个步骤:

    说明:/dev/null表示空设备,这里就是把日志记录到空设备里,就是不记录日志。】

    怎么做呢?先看代码:

    这时再运行,如果我们往屏幕输出内容,这时是看不到内容的,因为已经将标准输出重定向了空设备:

    说明:关于dup的知识,可参考博文:http://www.cnblogs.com/webor2006/p/3498443.html

    daemon:
    实际上linux上已经有现成的方法可以创建一个守护进程了,如下:
     
    我们使用一下它:
    在运行它之前,我们来看下现在应该有几个守护进程了:
    先将其都杀掉,以便来观察调用系统的创建守护进程是否成功:
    这时,再运行:
    对于系统的这个函数,都是传递的0,如果传递1会怎样呢?
    编译运行:
    实际上,对于我们写的守护进程,也可以模拟成跟系统调用方式一样,修改程序如下:
    #include <unistd.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <fcntl.h>
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <signal.h>
    
    
    #define ERR_EXIT(m) 
        do 
        { 
            perror(m); 
            exit(EXIT_FAILURE); 
        } while(0)
    
    int setup_daemon(int nochdir, int noclose);//模拟系统创建守护进程的函数声明
    
    int main(int argc, char *argv[])
    {
        setup_daemon(1, 1);//这时改用跟调用系统创建守护进程的自己实现的函数
        printf("test ...
    ");
        for (;;) ;
        return 0;
    }
    
    int setup_daemon(int nochdir, int noclose)
    {
        pid_t pid;
        pid = fork();
        if (pid == -1)
            ERR_EXIT("fork error");
    
        if (pid > 0)
            exit(EXIT_SUCCESS);
    
        setsid();
        if (nochdir == 0)//实现很简单,做下参数判断既可
            chdir("/");
        if (noclose == 0)
        {
            int i;
            for (i=0; i<3; ++i)
                close(i);
            open("/dev/null", O_RDWR);
            dup(0);
            dup(0);
        }
        return 0;
        
    }

    编译运行:

    提示:在创建守护进程时,不重定向至空设备其实对于开发期间便于调试,如果等程序发布了之后,就得重定向了!】

    好了,进程相关的东西就告一段落了,下节会继续探寻系统编程的其它东东,下节见!
  • 相关阅读:
    2有一个数组,数组中有13个元素,先将该数组进行分组,每3个元素为一组,分为若干组,最后用一个数组统一管理这些分组.(要动态创建数组).
    .通过分类为数组添加一个倒序的一个方法. 比如: 数组中元素为 @”aa”, @”bb”, @”cc”, @”dd”, @”ee”, 倒序完之后为: @”ee”, @”dd”,@”cc”,@”bb
    做⼀个班级信息程序,包含4个⾃定义的类:OurClass、Teacher、 Student、Person,并实现方法.
    NSDictionary使用小结(字典)
    学习block的主要目的 学会排序(升序,降序)
    myeclipse项目重新编译失败:清理项目缓存
    虚拟机无法ping通网络问题总结
    Jackson简单应用
    Spring Boot常见问题(二)Unable to start embedded container; nested exception is java.lang.NoSuchMethodError: org.apache.tomcat.util.scan.StandardJarScanner.setJarScanFilter(Lorg/apache/tomcat/JarScanFilter;
    Spring Boot常见问题(一)Maven依赖加载失败
  • 原文地址:https://www.cnblogs.com/webor2006/p/3514552.html
Copyright © 2011-2022 走看看