• 创建服务的进程,进程死了会自动重启。


    #include "SVPType.h"
    
    #include <sys/wait.h>
    
    #include "SVPLog.h"
    
    #ifdef SVP_LOG_TAG
        #undef SVP_LOG_TAG
    #endif
    #define SVP_LOG_TAG     "procguard"
    
    int32_t main (int32_t argc, char* argv[]) {
        if (argc < 2) {
            exit(EXIT_FAILURE);
        }
    
        char strArg[256] = {0};
        snprintf(strArg, 256, "%s", argv[1]);
    GUARD_ACTIVE:
    
        if ( 0 == fork()) {
            if (execvp(argv[1], &argv[1]) == -1) {
                SVP_ERROR("execvp(%s) failed, error no = %d.", strArg, errno);
                exit(EXIT_FAILURE);
            }
    
            exit(EXIT_SUCCESS);
        } else {
            int32_t status = 0;
            pid_t pid = wait(&status);
    
            SVP_INFO("%s(%d) exit with status %d, restart after 50ms ...", strArg, pid, status);
            SVP_Sleep(50);
            goto GUARD_ACTIVE;
        }
    
        exit(EXIT_SUCCESS);
    }

    在execute函数中最先调用fork()函数,那fork()函数做了些什么呢?其实fork()函数创建了和当前进程基本一模一样的一个子进程。当控制转到内核中的fork代码之后,内核先分配新的内存块和内核数据结构,然后将原来的进程复制到新的进程中去。最后向运行进程中添加新的进程并且控制重新返回到进程中。开始可能觉得挺奇怪的,搞个基本差不多的进程干什么?其实看了后面的内容你就会知道,只要调用个execvp函数,子进程就变得完全不一样啦。好,现在我们就有两个进程了,并且它们的代码相同,都运行到

      pid=fork();//创建子进程

           这一步,那我们怎么判断哪个是父进程,哪个是子进程呢?其实在父进程中fork函数的返回值是子进程的进程ID,而在子进程中,fork返回的是0,所以我们通过fork的返回值就能判断父子进程了。下面进入switch部分,若fork返回-1,说明创建子进程失败,若是在子进程中,则调用execvp函数(其实execvp不是系统调用,而是一个库函数,它通过调用execve来调用内核服务)来执行指明的程序。那我们就来看看execvp这个函数干了些什么?

    result=execvp(])

          其中第一个参数指明了要执行的进程,如:“ls”,"ps"等等命令,而第二个参数则为指向要执行的命令及相关参数的字符串指针。通过调用execvp我们就能在一个进程中,执行像"ls"这样另外一个进程了。但是有一个问题需要注意,那就是execvp会清除当前进程,并加载由file指定的进程。也就是说,比如当"ls"执行完之后,execvp下面的那句perror是不会执行的,因为它早就被“ls”的代码替换掉了。这其实也就是我们为什么要创建子进程的原因。如果在父进程中调用execvp的话,我们做的这个shell程序就只能调用一条命令了。

          那我们就要想了,父进程这个时候在干嘛呢?其实在fork之后,父子进程是并行执行的,而我们想要的效果是父进程先等等,等子进程结束之后再继续执行。接下来的wait函数就满足了我们的愿望啦!

    pid=wait(&status)

          wait函数主要做两件事,首先wait暂停调用它的进程直到子进程结束,然后wait通过status取得子进程结束时传给exit的值。wait返回结束进程的PID,如果进程没有子进程或没有得到终止状态值,则返回-1。

          这样通过不断地创建子进程,用想要执行的程序代替子进程并且让父进程等待,最后执行完毕,回到父进程,我们也就模拟了一个shell程序啦。最后来说说,结束进程的函数exit。exit的话,它会先刷新所有的流,调用一些函数,执行当前系统定义的其他和exit相关的操作。最后,调用_exit这个内核操作,来进行释放内存,关闭相关文件这些善后工作。

  • 相关阅读:
    hadoop 动态调整mapred参数
    python 遍历hadoop, 跟指定列表对比 包含列表中值的取出。
    replay的意义
    c++ 异常 warning: 'MEMORY_UNIT_NAME' defined but not used
    c++ 异常 discards qualifiers 丢弃
    c++ 条件变量
    声明
    HibernateSessionFactory建立-使用ThreadLocal
    App Crawler使用教程
    loadrunner生成随机数用于Action参数中
  • 原文地址:https://www.cnblogs.com/yuguangyuan/p/9279189.html
Copyright © 2020-2023  润新知