问题
I have a program with undefined behavior ( vfork() is used inappropriately ):
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
int main ( int argc, char *argv[] )
{
pid_t pid;
printf("___________befor fork______________.\n");
if((pid=vfork()) < 0)
perror("fork");
else if(pid > 0)
printf("parent\n");
else
printf("child\n");
printf("pid: %d, ppid: %d\n", getpid(), getppid());
//exit(0);
return 0;
}
If I use exit(0)
function instead return - output is:
___________befor fork______________.
child
pid: 4370, ppid: 4369
parent
pid: 4369, ppid: 2924
If I use return 0
- I get infinite output like this:
___________befor fork______________.
child
pid: 4455, ppid: 4454
parent
pid: 4454, ppid: 2924
___________befor fork______________.
child
pid: 4456, ppid: 4454
parent
pid: 4454, ppid: 2924
___________befor fork______________.
child
pid: 4457, ppid: 4454
parent
pid: 4454, ppid: 2924
and so on ...
I know that you can not use return
in the child after the vfork()
function.
But I don't understand why the parent does not end after return
call?
Thanks.
回答1:
It is not valid to return from the function in the child, because with vfork()
both the parent and child share the same stack and returning in the child will mess up the stack frame for the parent. Usually the call to main()
(in the start function) is followed by a call to exit()
or similar, so that call to exit()
in the child will overwrite the same stack space that the call to main()
was using (and is still using in the parent). So when the child does exit, the parent will return from vfork()
but the return address on the stack will likely be clobbered so it could return to any address or do anything at all.
Also, in the child, if you do not exec you should call _exit()
rather than exit()
. exit()
will flush the stdio output buffers but those same buffers are being managed by the parent, whereas _exit()
will just end the process.
回答2:
By returning in your child process you are causing undefined behavior, so anything can really happen.
It looks like you parent process works fine, but the child process, instead of exiting, restarts main
function.
回答3:
The current POSIX standard does not support vfork()
at all.
In the old (1997-ish) POSIX standard, the page for vfork() said:
The
vfork()
function has the same effect asfork()
, except that the behaviour is undefined if the process created byvfork()
either modifies any data other than a variable of typepid_t
used to store the return value fromvfork()
, or returns from the function in whichvfork()
was called, or calls any other function before successfully calling_exit()
or one of theexec
family of functions.
Your code is not calling either an exec
family function or _exit()
, so you invoke undefined behaviour, and anything that happens is legitimate.
You've just demonstrated why it is not usually sensible to use vfork()
. IMNSHO, it is in the same camp as gets()
; I know it exists but I would never use it voluntarily, and I'd be perfectly happy for the implementations to be:
pid_t vfork(void) { abort(); }
char *gets(char *buffer) { abort(); }
回答4:
you can see the definition of vfork in the kernel.org : http://www.kernel.org/doc/man-pages/online/pages/man2/vfork.2.html . it is a good explanation.
来源:https://stackoverflow.com/questions/7676619/difference-between-exit-and-return-after-vfork-call