13

From the man page of vfork():

vfork() differs from fork() in that the parent is suspended until the child makes a call to execve(2) or _exit(2). The child shares all memory with its parent, including the stack, until execve() is issued by the child. The child must not return from the current function or call exit(), but may call _exit().

Why should the child use an _exit() rather than simply calling exit()? I hope this is applicable to both vfork() and fork().

4 Answers4

12

As seen earlier, vfork does not allow the child process to access the parent's memory. exit is a C library function (that's why it's often written as exit(3)). It performs various cleanup tasks such as flushing and closing C streams (the files open through functions declared in stdio.h) and executing user-specified functions registered with atexit. All these tasks involve reading and writing to the process memory.

_exit exits without cleanup. It's directly a system call (which is why it's written as _exit(2)), typically implemented by placing the system call number in a processor register and executing a particular processor instruction (branching to the system call handler). This doesn't need to access the process memory, so it's safe to do after vfork.

After fork, there is no such restriction: the parent and child process are now completely autonomous.

  • vfork does not allow the child process to access the parent's memory? But i thought they share the same address space, so the child can access parents address space. Was that understanding wrong? – Navaneeth Sen Jan 04 '11 at 13:46
  • After fork, there is no such restriction: the parent and child process are now completely autonomous. Does that mean i can call an exit() from a child of a fork? – Navaneeth Sen Jan 04 '11 at 13:51
  • 1
    @Sen: The child is not allowed to access the parent's memory. If you try it, it might work, because the kernel will not protect you. But the effect might not be what you intend; for example, if your compiler decides to leave some value in a register, it won't be seen by the parent process. – Gilles 'SO- stop being evil' Jan 04 '11 at 19:15
  • @Sen: After a fork, you can do call exit or any other function. Every process starts after a fork (on Linux, even the initial process init is forked by the kernel). – Gilles 'SO- stop being evil' Jan 04 '11 at 19:16
3

exit do additional cleanup like calling functions registered by atexit hence it access data outside copied part. _exit performs syscall directly w/out any cleanup except in-kernel.

  • ... and it should be noted that fork() does copy everything, so you may be able to call exit(), and you can definitely return from the current function. – derobert Jan 03 '11 at 17:39
3

You have the child call _exit() to avoid flushing stdio (or other) buffers when the child process exits. Since the child process constitutes an exact copy of the parent process, the child process still has whatever the parent had in "stdout" or "stderr", the buffers from <stdio.h>. You can (and will, at inopportune times) get double outputs by calling exit(), one from the child process' atexit handlers, and one from the parent, when the buffers in the parent process get full, and get flushed.

I realize the above answer concentrates on stdio.h specifics, but that idea probably carries over to other buffered I/O, just as one of the answers above indicates.

1

exit() :- performs some cleanup task, like closing the i/o streams and many, and then returns to the kernel. _exit() :- directly comes to kernel (do not perform any cleanup task).

fork() : both parent and child have different file table, so the change done by child do not affect the environment parameters of parent, and vice versa .

vfork() : both parent and child uses the same file table, so the change done by child affects the environment parameters of parent. e.g. some variable var=10, now run var++ by child and then run parent, you can see the effect of var++ in the output of parent also.

As I said if you use exit() in vfork() then all the i/o is already closed. So then, even if parent runs correctly, you cant able to get the proper output, because all variables are flushed and all streams are closed.

Anthon
  • 79,293