switch 中的多个 fork() 会导致指数执行
我有一个程序,它根据 i 执行多个程序。请参阅以下代码块:
for(i=0;i<5;i++){
switch(i){
case 0:
if(fork())result=execl(transportProtoSnd,transportProtoSnd,RTPport, NULL);
if(result<0){printf("ERRNO: %d\n", errno);exit(0);}
break;
case 1:
if(fork())result=execl(fecSnd,fecSnd,RTPport-1, nameOfTransportProto, NULL);
if(result<0){printf("ERRNO: %d\n", errno);exit(0);}
break;
case 2:
if(fork())result=execl(fecRcv,fecRcv,RTPport-2, nameOfTransportProto, NULL);
if(result<0){printf("ERRNO: %d\n", errno);exit(0);}
break;
case 3:
if(fork())result=execl(transportProtoRcv,transportProtoRcv, RTPport-3, NULL);
if(result<0){printf("ERRNO: %d\n", errno);exit(0);}
break;
}
}
问题是进程树看起来像:
0:00 \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
通过使用 vfork() 我得到了更好的行为:
0:00 \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
但实际上它应该看起来像:
0:00 udevd --daemon
0:00 \_ udevd --daemon
0:00 \_ udevd --daemon
IIRC vfork() 不使用父进程的状态。因此,我防止了 ps 树 1 中的指数分叉。但是,使用 vfork,每个子节点都会从父子节点演化而来,请参阅树 2。在我看来,通过使用 fork() 或 vfork() 树应该看起来像 ps 树 3。
亲切的问候
I have a program which executes multiple programs depending on i. See the following code block:
for(i=0;i<5;i++){
switch(i){
case 0:
if(fork())result=execl(transportProtoSnd,transportProtoSnd,RTPport, NULL);
if(result<0){printf("ERRNO: %d\n", errno);exit(0);}
break;
case 1:
if(fork())result=execl(fecSnd,fecSnd,RTPport-1, nameOfTransportProto, NULL);
if(result<0){printf("ERRNO: %d\n", errno);exit(0);}
break;
case 2:
if(fork())result=execl(fecRcv,fecRcv,RTPport-2, nameOfTransportProto, NULL);
if(result<0){printf("ERRNO: %d\n", errno);exit(0);}
break;
case 3:
if(fork())result=execl(transportProtoRcv,transportProtoRcv, RTPport-3, NULL);
if(result<0){printf("ERRNO: %d\n", errno);exit(0);}
break;
}
}
The problem is that the process tree looks like:
0:00 \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
By using vfork() i get a better behaviour:
0:00 \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
0:00 | \_ NfqCallTracking/NfqCallTracking 0 Tests/NfqVerdictOnly
But actually it should look like:
0:00 udevd --daemon
0:00 \_ udevd --daemon
0:00 \_ udevd --daemon
IIRC vfork() does not use the state of the parent process. Thus i prevent the exponential forking in ps tree 1. However using vfork each child evolves of the parent child, see tree 2. In my opinion by using fork() or vfork() the tree should look like the ps tree 3.
Kind Regards
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
事实上,这就是正在发生的事情。
父进程分叉并立即执行(当然永远不会返回)。这就是
if
的作用。然后子进程测试一个虚假的结果值,并继续生成另一个程序 (i++)。所以主要问题似乎是您在父级而不是子级中执行(这很奇怪)。您应该执行以下操作:
显然您应该检查 fork(2) 的返回码。
Actually, here's what is happening.
The parent forks and immediately execs (and never returns of course). That's what that
if
does. Then the child tests a bogus result value, and goes on to spawn another program (i++).So the main problem seems to be that you are execing in the parent instead of the child (which is pretty weird). You should be doing something like:
Obviously you should be checking the return code of
fork(2)
.来自“fork”的手册页:
这意味着对于您的程序来说,父进程执行并且子进程继续循环以分叉其他进程......因此树,恕我直言。尝试反转 if 条件。
From the man-page of 'fork':
Which mean for your program the the parent-process execls and the child-process continues the loop to fork the others... thus the tree, IMHO. Try to inverse the if-condition.
除了其他答案之外,您应该意识到您是通过这种方式创建僵尸的 - 至少如果您有一个长期运行的“父”程序。您应该记下
fork()
进程的 PID(可能在一个数组中),并执行wait()
、waitid()
或waitpid()
。Additionally to the other answers, you should be aware that you create zombies this way - at least if you have a long-running "parent" program. You should note the PID of the
fork()
ed processes, maybe in an array, and do await()
,waitid()
orwaitpid()
.