fork() 和 wait() 有两个子进程
我需要使用 fork()
和 wait()
函数来完成分配。我们正在对非确定性行为进行建模,如果存在多个可能的转换,则需要程序进行 fork()
。
为了尝试弄清楚 fork 和 wait 是如何工作的,我刚刚编写了一个简单的程序。我想我现在明白了调用是如何工作的,如果程序只分支一次就很好了,因为父进程可以使用单个子进程的退出状态来确定子进程是否达到接受状态。
正如您从下面的代码中看到的,我希望能够处理必须有多个子进程的情况。我的问题是,您似乎只能使用 _exit
函数设置状态一次。因此,如我的示例所示,父进程测试的退出状态显示第一个子进程发出 0 作为其退出状态,但没有有关第二个子进程的信息。
我尝试简单地不对拒绝执行_exit()
-ing,但随后该子进程将继续运行,实际上似乎有两个父进程。
抱歉胡扯,但如果有人能告诉我我的父进程如何获取多个子进程的状态信息,我将不胜感激,或者我会很高兴父进程只注意到子进程的接受状态,但在这种情况下,我将成功地需要退出具有拒绝状态的子进程。
我的测试代码如下:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
int main(void) {
pid_t child_pid, wpid, pid;
int status = 0;
int i;
int a[3] = {1, 2, 1};
for(i = 1; i < 3; i++) {
printf("i = %d\n", i);
pid = getpid();
printf("pid after i = %d\n", pid);
if((child_pid = fork()) == 0) {
printf("In child process\n");
pid = getpid();
printf("pid in child process is %d\n", pid);
/* Is a child process */
if(a[i] < 2) {
printf("Should be accept\n");
_exit(1);
} else {
printf("Should be reject\n");
_exit(0);
}
}
}
if(child_pid > 0) {
/* Is the parent process */
pid = getpid();
printf("parent_pid = %d\n", pid);
wpid = wait(&status);
if(wpid != -1) {
printf("Child's exit status was %d\n", status);
if(status > 0) {
printf("Accept\n");
} else {
printf("Complete parent process\n");
if(a[0] < 2) {
printf("Accept\n");
} else {
printf("Reject\n");
}
}
}
}
return 0;
}
I need to use the fork()
and wait()
functions to complete an assignment. We are modelling non-deterministic behavior and need the program to fork()
if there is more than one possible transition.
In order to try and work out how fork
and wait
work, I have just made a simple program. I think I understand now how the calls work and would be fine if the program only branched once because the parent process could use the exit status from the single child process to determine whether the child process reached the accept state or not.
As you can see from the code that follows though, I want to be able to handle situations where there must be more than one child processes. My problem is that you seem to only be able to set the status using an _exit
function once. So, as in my example the exit status that the parent process tests for shows that the first child process issued 0 as it's exit status, but has no information on the second child process.
I tried simply not _exit()
-ing on a reject, but then that child process would carry on, and in effect there would seem to be two parent processes.
Sorry for the waffle, but I would be grateful if someone could tell me how my parent process could obtain the status information on more than one child process, or I would be happy for the parent process to only notice accept status's from the child processes, but in that case I would successfully need to exit from the child processes which have a reject status.
My test code is as follows:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
int main(void) {
pid_t child_pid, wpid, pid;
int status = 0;
int i;
int a[3] = {1, 2, 1};
for(i = 1; i < 3; i++) {
printf("i = %d\n", i);
pid = getpid();
printf("pid after i = %d\n", pid);
if((child_pid = fork()) == 0) {
printf("In child process\n");
pid = getpid();
printf("pid in child process is %d\n", pid);
/* Is a child process */
if(a[i] < 2) {
printf("Should be accept\n");
_exit(1);
} else {
printf("Should be reject\n");
_exit(0);
}
}
}
if(child_pid > 0) {
/* Is the parent process */
pid = getpid();
printf("parent_pid = %d\n", pid);
wpid = wait(&status);
if(wpid != -1) {
printf("Child's exit status was %d\n", status);
if(status > 0) {
printf("Accept\n");
} else {
printf("Complete parent process\n");
if(a[0] < 2) {
printf("Accept\n");
} else {
printf("Reject\n");
}
}
}
}
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在我看来,基本问题似乎是您有一个
wait()
调用,而不是一个等待直到没有更多子项的循环。您也只能等待最后一个fork()
成功,而不是至少一个fork()
成功。如果您不希望进行正常的清理操作,例如刷新包括
stdout
在内的打开文件流,则应仅使用_exit()
。有时需要使用_exit()
;这不是其中之一。 (当然,在此示例中,您也可以简单地让子级返回,而不是直接调用exit()
,因为从main()
返回相当于使用 ,您会在main()
之外的函数中执行分叉等操作,然后exit()
通常是合适的。)但是,大多数情况下 ,代码的简化版本,可提供我想要的诊断。请注意,您的
for
循环跳过了数组的第一个元素(我的没有)。示例输出 (MacOS X 10.6.3):
注意,在某些(古董)版本的 Linux 上,您可能需要添加
#include
。我的经验是,即使这个答案是写出来的,这是没有必要的。 POSIX 2004 和 POSIX 2008 标准都表示这是不必要的(例如wait ()
和wait()< /code>
),但一些 Linux 手册页(例如
wait ()
位于 die.net,但不是等待(2)
在 man7.org)) 将其记录为必要的,并且 POSIX 1997
wait()
确实需要它。嗯嗯!It looks to me as though the basic problem is that you have one
wait()
call rather than a loop that waits until there are no more children. You also only wait if the lastfork()
is successful rather than if at least onefork()
is successful.You should only use
_exit()
if you don't want normal cleanup operations - such as flushing open file streams includingstdout
. There are occasions to use_exit()
; this is not one of them. (In this example, you could also, of course, simply have the children return instead of callingexit()
directly because returning frommain()
is equivalent to exiting with the returned status. However, most often you would be doing the forking and so on in a function other thanmain()
, and thenexit()
is often appropriate.)Hacked, simplified version of your code that gives the diagnostics I'd want. Note that your
for
loop skipped the first element of the array (mine doesn't).Example output (MacOS X 10.6.3):
Note that on some (antique) versions of Linux, you might need to add
#include <sys/types.h>
. My experience, even when this answer was written, is that it is unnecessary. Both the POSIX 2004 and POSIX 2008 standards say it is unnecessary (e.g.wait()
andwait()
), but some of the Linux manual pages (e.g.wait()
at die.net but notwait(2)
at man7.org)) document it as being necessary, and POSIX 1997
wait()
did require it. YMMV!将 wait() 函数放入循环中并等待所有子进程。如果没有更多子进程可用,wait 函数将返回 -1,并且 errno 将等于 ECHILD。
Put your wait() function in a loop and wait for all the child processes. The wait function will return -1 and errno will be equal to ECHILD if no more child processes are available.
Jonathan Leffler 的精彩示例,为了让您的代码在 SLES 上运行,我需要添加一个额外的标头以允许 pid_t 对象:)
brilliant example Jonathan Leffler, to make your code work on SLES, I needed to add an additional header to allow the pid_t object :)