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对象 ;
网友评论