What is the difference between fork() and vfork()?

2019-01-17 19:37发布

What is the difference between fork() and vfork()? Does vfork() return like fork().

标签: c unix fork vfork
6条回答
你好瞎i
2楼-- · 2019-01-17 20:05

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()).

查看更多
在下西门庆
3楼-- · 2019-01-17 20:08

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楼-- · 2019-01-17 20:15

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).

查看更多
一纸荒年 Trace。
5楼-- · 2019-01-17 20:16

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.

查看更多
ら.Afraid
6楼-- · 2019-01-17 20:16

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.

查看更多
Root(大扎)
7楼-- · 2019-01-17 20:18

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.

查看更多
登录 后发表回答