i have one, bad smelling problem :(
i have this code:
int main()
{
pid_t child, parent;
int status=0;
int i;
printf("parent = %d\n", getpid());
for(i=1; i<=5; i++){
if( (child = fork()) == 0){
sleep(i);
printf("i=%d, %d\n",i, getpid());
}
}
wait(0);
while( (parent = wait(&status)) > 0){
printf("Exit = %d, child = %d\n", status/256, parent);
}
}
and output is similar to:
1, 21320
2, 21321
Exit = 0, child = 21321
3, 21322
Exit = 0, child = 21322
4, 21323
Exit = 0, child = 21323
5, 21324
Exit = 0, child = 21324
And i think that wait(0) not waiting for all subprocess but only wait for first exit and write all (Exit = ...).
Is any way to do this:
1, 21320
2, 21321
3, 21322
4, 21323
5, 21324
Exit = 0, child = 21320
Exit = 0, child = 21321
Exit = 0, child = 21322
Exit = 0, child = 21323
Exit = 0, child = 21324
?
Here's a demo of the easiest way to produce the output in the order you asked for. It uses 3 loops: one to create the child processes, one to wait for them and collect their exit statuses, and one to print the exit statuses.
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#define NUMPROC 5
int main(void)
{
pid_t child[NUMPROC];
int status[NUMPROC];
int i;
printf("parent = %d\n", getpid());
for(i=0;i<NUMPROC;++i) {
if(fork() == 0) {
sleep(i);
printf("i=%d, %d\n",i, getpid());
_exit(0);
}
}
for(i=0;i<NUMPROC;++i)
child[i] = wait(&status[i]);
for(i=0;i<NUMPROC;++i)
printf("Exit = %d, child = %d\n", WEXITSTATUS(status[i]), child[i]);
}
This isn't a problem with wait()
, it's a matter of synchronization — or lack thereof. Each time you call fork()
, your child process sleeps for awhile, but the parent process continues executing. Your parent process finishes its fork loop and starts its wait loop while most of the children are still sleeping, so each time one of the children exits, the parent is already waiting for it. That's why the parent process is able to print its exit message immediately after each child exits.
If you want your parent process to wait for all the children to finish sleeping before entering the wait()
loop, you'll need to need to use an IPC synchronization mechanism, such as POSIX semaphores, to make the parent process block until all children have signaled that they're ready.
However, if your goal is simply to have all the exit messages appear on the screen after the child ID messages, you don't really need to delay the wait()
calls at all. Just change the wait
loop to store the status values in an array instead of immediately printing them, and then after the wait
loop finishes, run another loop to print the contents of the array.
You are correct. wait will return when any child exits. If you want to wait until all children have exited you can repeat the wait call in a while loop until it returns -1 and errno = ECHILD, which means no more children exist.
while (! (wait (0) == -1 && errno == ECHILD) ) ;
This loop is a little simplistic. You presumably want to check the result of your processes, and you should handle other errors that could occur.
wait (0)
waits for any child process to change status, not for all processes to change status. You have to store the pid-s of your child processes and then wait for each of them in a for loop:
i_am_child = 0;
my_i = 0;
for (i = 0; i < nr_children; ++i) {
child = fork ();
if (child == 0) { i_am_child = 1; my_i = i; break; }
childpid [i] = child;
}
if (i_am_child) {
// do what children are supposed to do, e.g. printf and sleep (my_i)
exit (0);
}
if (! i_am_child) // strictly, this line is not necessary, since children have exited
for (i = 0; i < nr_children; ++i) waitpid (childpid [i], &status, 0);
...
Make sure that the forks and waits are executed by the parent only!
As far as I see, the children should break
the first for loop immediately after the fork and not enter the second.
来源:https://stackoverflow.com/questions/22431386/linux-fork-and-wait