What is the difference between fork()
and vfork()
? Does vfork()
return like fork()
.
问题:
回答1:
The intent of vfork
was to eliminate the overhead of copying the whole process image if you only want to do an exec*
in the child. Because exec*
replaces the whole image of the child process, there is no point in copying the image of the parent.
if ((pid = vfork()) == 0) {
execl(..., NULL); /* after a successful execl the parent should be resumed */
_exit(127); /* terminate the child in case execl fails */
}
For other kinds of uses, vfork
is dangerous and unpredictable.
With most current kernels, however, including Linux, the primary benefit of vfork
has disappeared because of the way fork
is implemented. Rather than copying the whole image when fork
is executed, copy-on-write techniques are used.
回答2:
As already stated, the vfork
man page is clear about the differences.
This topic gives a good description of fork
, vfork
, clone
and exec
.
Below are some often overlooked differences between fork
and vfork
I experienced on some Linux 2.6.3x embedded systems I worked with.
Even with copy-on-write techniques, fork
fails if you don't have enough memory to duplicate the memory used by the parent process. For example, if the parent process uses 2 GB of resident memory (ie, memory that is used and not just allocated), fork
fails if you have less than 2 GB of free memory left. That's frustrating when you just want to exec
a simple program and therefore will never need that huge parent address space!
vfork
doesn't have this memory issue, as it doesn't duplicate the parent address space. The child process acts more like a thread in which you are able to call exec*
or _exit
without hurting your parent process.
Because memory page tables are not duplicated, vfork
is much faster than fork
and vfork
's execution time is not affected by the amount of memory the parent process uses, as pointed out here: http://blog.famzah.net/2009/11/20/fork-gets-slower-as-parent-process-use-more-memory/
In situations where performance is critical and/or memory limited, vfork
+ exec*
can therefore be a good alternative to fork
+ exec*
. The problem is that it is less safe and the man page says vfork
is likely to become deprecated in the future.
A safer and more portable solution may be to look at the posix_spawn
function, which is higher level and offers more options. It safely uses vfork
when possible, depending on the options you pass it. I have been able to use posix_spawn
successfully and overcome that annoying "double memory checking issue" that fork
+ exec
was giving me.
A really good page on this topic, with links to some posix_spawn
examples.
回答3:
From my man page
(From POSIX.1) The vfork() function has the same effect as fork(2), except that the behavior is undefined if the process created by vfork() either modifies any data other than a variable of type pid_t used to store the return value from vfork(), or returns from the function in which vfork() was called, or calls any other function before successfully calling _exit(2) or one of the exec(3) family of functions.
vfork() differs from fork(2) in that the parent is suspended until the child terminates (either normally, by calling _exit(2), or abnormally, after delivery of a fatal signal), or it makes a call to execve(2). Until that point, the child shares all memory with its parent, including the stack. The child must not return from the current function or call exit(3), but may call _exit(2).
回答4:
Some systems have a system call vfork(), which was originally designed as a lower-overhead version of fork(). Since fork() involved copying the entire address space of the process, and was therefore quite expensive, the vfork() function was introduced (in 3.0BSD).
However, since vfork() was introduced, the implementation of fork() has improved drastically, most notably with the introduction of `copy-on-write', where the copying of the process address space is transparently faked by allowing both processes to refer to the same physical memory until either of them modify it. This largely removes the justification for vfork(); indeed, a large proportion of systems now lack the original functionality of vfork() completely. For compatibility, though, there may still be a vfork() call present, that simply calls fork() without attempting to emulate all of the vfork() semantics.
As a result, it is very unwise to actually make use of any of the differences between fork() and vfork(). Indeed, it is probably unwise to use vfork() at all, unless you know exactly why you want to.
The basic difference between the two is that when a new process is created with vfork(), the parent process is temporarily suspended, and the child process might borrow the parent's address space. This strange state of affairs continues until the child process either exits, or calls execve(), at which point the parent process continues.
This means that the child process of a vfork() must be careful to avoid unexpectedly modifying variables of the parent process. In particular, the child process must not return from the function containing the vfork() call, and it must not call exit() (if it needs to exit, it should use _exit(); actually, this is also true for the child of a normal fork()).
回答5:
Refer here and from wikipedia-
On some systems, vfork() is the same as fork(). The vfork() function differs from fork() only in that the child process can share code and data with the calling process (parent process).
回答6:
The basic difference between the two is that when a new process is created with vfork()
, the parent process is temporarily suspended, and the child process might borrow the parent's address space. This strange state of affairs continues until the child process either exits, or calls execve()
, at which point the parent process continues.
This means that the child process of a vfork()
must be careful to
avoid unexpectedly modifying variables of the parent process. In
particular, the child process must not return from the function
containing the vfork()
call, and it must not call
exit()
(if it needs to exit, it should use _exit();
actually, this is also true for the child of a normal fork()
).
However, since vfork()
was introduced, the
implementation of fork()
has improved drastically, most notably
with the introduction of 'copy-on-write', where the copying of the
process address space is transparently faked by allowing both processes
to refer to the same physical memory until either of them modify
it. This largely removes the justification for vfork();
indeed, a
large proportion of systems now lack the original functionality of
vfork()
completely. For compatibility, though, there may still be
a vfork()
call present, that simply calls fork()
without
attempting to emulate all of the vfork()
semantics.
As a result, it is very unwise to actually make use of any of the
differences between fork()
and vfork()
. Indeed, it is
probably unwise to use vfork()
at all, unless you know exactly
why you want to.