switch 中的多个 fork() 会导致指数执行

发布于 2024-11-28 19:15:25 字数 2681 浏览 0 评论 0原文

我有一个程序,它根据 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

琉璃梦幻 2024-12-05 19:15:25

事实上,这就是正在发生的事情。

if(fork())result=execl(transportProtoSnd,transportProtoSnd,RTPport, NULL);
if(result<0){printf("ERRNO: %d\n", errno);exit(0);}

父进程分叉并立即执行(当然永远不会返回)。这就是 if 的作用。然后子进程测试一个虚假的结果值,并继续生成另一个程序 (i++)。

所以主要问题似乎是您在父级而不是子级中执行(这很奇怪)。您应该执行以下操作:

if(fork() == 0) {
    execl(transportProtoSnd,transportProtoSnd,RTPport, NULL);
    /* If it reaches this handle error. */
}

显然您应该检查 fork(2) 的返回码。

Actually, here's what is happening.

if(fork())result=execl(transportProtoSnd,transportProtoSnd,RTPport, NULL);
if(result<0){printf("ERRNO: %d\n", errno);exit(0);}

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:

if(fork() == 0) {
    execl(transportProtoSnd,transportProtoSnd,RTPport, NULL);
    /* If it reaches this handle error. */
}

Obviously you should be checking the return code of fork(2).

神爱温柔 2024-12-05 19:15:25

来自“fork”的手册页:

成功时,在父进程中返回子进程的 PID,在子进程中返回 0。

这意味着对于您的程序来说,父进程执行并且子进程继续循环以分叉其他进程......因此树,恕我直言。尝试反转 if 条件。

From the man-page of 'fork':

On success, the PID of the child process is returned in the parent, and 0 is returned in the child.

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.

丢了幸福的猪 2024-12-05 19:15:25

除了其他答案之外,您应该意识到您是通过这种方式创建僵尸的 - 至少如果您有一个长期运行的“父”程序。您应该记下 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 a wait(), waitid() or waitpid().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文