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

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> workers;
    
    printf("[Master]: Proc Start with pid %d! \n", getpid());
    for (int i = 0; i < PROCESS_NUM; i++)
    {
        workers.push_back(std::make_unique());
    }
}

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

[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创建多个子进程)