美文网首页
Linux下使用fork创建多个子进程

Linux下使用fork创建多个子进程

作者: EVANMORE | 来源:发表于2018-03-26 20:14 被阅读398次

    Nginx软件实现了一个master进程,多个worker子进程的运行模型。现在我打算用C++来实现这种模型,一开始我是这么实现的,先创建一个worker类,

    class worker
    {
    public:
        worker()
        {
            int pid = fork();
            
            switch(pid)
            {
                case 0:
                    printf("[Worker]: Parent (%d) created child(%d). \n", getppid(), getpid());
                    // sleep for 2 seconds
                    sleep(2);
                    printf("[Worker]: with pid %d exit! \n", getpid());
                    break;;
                case -1:
                    printf("[Worker]: Fork failed!\n");
                    break;
                default:
                    break;
            }
        }
        ~worker()
        {
            printf("[Worker]: with pid %d destructed\n", getpid());
        }
    };
    

    然后创建一个main函数,使用for循环去创建三个worker对象

    int main()
    {
        std::vector<std::unique_ptr<worker>> workers;
        
        printf("[Master]: Proc Start with pid %d! \n", getpid());
        for (int i = 0; i < PROCESS_NUM; i++)
        {
            workers.push_back(std::make_unique<worker>());
        }
    }
    

    看上去理所应当的应该创建三个子进程,每个子进程等待两秒后就退出了,然而打出来的日志却明显不是我们所要的,

    [Master]: Proc Start with pid 7495!
    [Worker]: Parent (7495) created child(7496).
    [Worker]: Parent (7495) created child(7497).
    [Worker]: Parent (7495) created child(7498).
    [Worker]: with pid 7498 exit!
    [Worker]: with pid 7497 exit!
    [Worker]: with pid 7496 exit!
    [Worker]: Parent (7496) created child(7500).
    [Worker]: Parent (7497) created child(7499).
    [Worker]: Parent (7496) created child(7501).
    [Master]: Proc End with pid 7495!
    [Worker]: with pid 7495 destructed
    [Worker]: with pid 7495 destructed
    [Worker]: with pid 7495 destructed
    root@evan-VirtualBox:~/EvanWorkspace/sctp_socket/thundering_herd/build# [Worker]: with pid 7500 exit!
    [Worker]: with pid 7499 exit!
    [Worker]: with pid 7501 exit!
    [Worker]: Parent (7500) created child(7502).
    
    ...
    

    明显的创建了不止3个子进程,这是为什么呢?
    原因就出在worker的构造函数中,当判断出来是当前的是子进程的时候,等待两秒后的结束语句是break。

    • 子进程在fork函数调用完成后,相当于是从当前节点开始拷贝了一份代码在子进程中运行
    • 例如子进程7496运行到break后,退出worker构造函数,返回main函数的for循环;
    • 这个时候子进程7496的main函数喊剩余两次循环,所以7496作为父进程又创建了两个新的子进程7500/7501;
    • 如此循环递归下去;

    正确的方法是在worker的构造函数中判断出来是子进程之后,子进程的处理完成后调用exit(0)退出当前子进程,这样就能得到我们要的结果了。

        worker()
        {
            int pid = fork();
            
            switch(pid)
            {
                case 0:
                    printf("[Worker]: Parent (%d) created child(%d). \n", getppid(), getpid());
                    // sleep for 2 seconds
                    sleep(2);
                    printf("[Worker]: with pid %d exit! \n", getpid());
                    exit(0);;
                case -1:
                    printf("[Worker]: Fork failed!\n");
                    exit(0);
                default:
                    break;
            }
        }
    

    打印的结果如下

    [Master]: Proc Start with pid 7565!
    [Worker]: Parent (7565) created child(7566).
    [Worker]: Parent (7565) created child(7567).
    [Worker]: Parent (7565) created child(7568).
    [Worker]: with pid 7566 exit!
    [Worker]: with pid 7567 exit!
    [Worker]: with pid 7568 exit!
    [Master]: Proc End with pid 7565!
    [Worker]: with pid 7565 destructed
    [Worker]: with pid 7565 destructed
    [Worker]: with pid 7565 destructed
    

    这里还有问题,看最后的几行打印,实际上这里调用的析构函数销毁的是主进程中三个worker对象 ;

    相关文章

      网友评论

          本文标题:Linux下使用fork创建多个子进程

          本文链接:https://www.haomeiwen.com/subject/xfdxxftx.html