vfork文档

VFORK(2)

NAME

vfork - create a child process and block parent

vfork - 创建一个子进程并阻塞父进程

SYNOPSIS

       #include <sys/types.h>
       #include <unistd.h>

        pid_t vfork(void);

DESCRIPTION

Standard description
(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.

标准描述
     标准描述: (始于POSIX.1) vfork函数和fork有相同的效果, 不同点在于vfork的以下行为是不确定的:
    1 修改除vfork返回的用于存储pid_t之外的其他变量.
    2 在调用_exit(2) 或者exec(3)系列函数之前调用其他方法.

Linux description
    vfork(), just like fork(2), creates a child process of the calling process. For details and return value and errors, see fork(2).
    vfork() is a special case of clone(2). It is used to create new processes without copying the page tables of the parent process. It may be useful in performance-sensitive applications where a child is created which then immediately issues an execve(2).
    vfork() differs from fork(2) in that the calling thread 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).
    As with fork(2), the child process created by vfork() inherits copies of various of the caller’s process attributes (e.g., file descriptors, signal dispositions, and current working directory); the vfork() call differs only in the treatment of the virtual address space, as described above.
    Signals sent to the parent arrive after the child releases the parent’s memory (i.e., after the child terminates or calls execve(2)).

    vfork(), 比较像fork(2), 用于创建调用进程的子进程. 详细的返回值和错误信息请参考fork(2).
    vfork() 是clone(2)函数的一个特殊用例. 用于创建一个新的进程但是不拷贝父进程的页表. 它应该用于性能敏感的应用程序,创建完子进程立即执行execve(2) 函数.
    vfork()和fork(2)的不同点在于 vfork调用进程(父进程)将被挂起,直到子进程结束(正常结束, 调用_exit(2), 或者异常,收到致命的信号), 或者调用execve(2)系函数. 在调用完vfork那个时间点. 子进程将共享父进程的所有内存, 包括栈. 子进程不能直接返回或者调用exit(3), 但是可以调用_exit(2).
    和fork(2)相同点在于vfork()创建的子进程也拷贝父进程的属性变量(包括文件描述符, 信号处理, 当前工作目录). vfork调用仅在处理虚拟地址空间方面和fork(2)有所不同. 如上所述.
    信号发送给父进程直到子进程释放和父进程共享的内存.(也就是当子进程结束或者调用execve(2)系函数之后)

Historic description
Under Linux, fork(2) is implemented using copy-on-write pages, so the only penalty incurred by fork(2) is the time and memory required to duplicate the parent’s page tables, and to create a unique task structure for the child. However, in the bad old days a
fork(2) would require making a complete copy of the caller’s data space, often needlessly, since usually immediately afterward an exec(3) is done. Thus, for greater efficiency, BSD introduced the vfork() system call, which did not fully copy the address space of
the parent process, but borrowed the parent’s memory and thread of control until a call to execve(2) or an exit occurred. The parent process was suspended while the child was using its resources. The use of vfork() was tricky: for example, not modifying data in
the parent process depended on knowing which variables were held in a register.

    在Linux中,fork(2) 是使用写时复制页面, 因此唯一的开销就是复制父进程页表和创建子进程的task结构所花费的时间和内存. 然而在过去糟糕的日子里, fork需要完整的拷贝父进程的所有数据空间, 在通常是没有必要的,一般情况下fork创建子进程后会马上调用exec(3)系列函数(调用exec系列函数后从父进程拷贝的内存将被释放). 为了更好的体验,BSD发行版引入了vfork系统调用, 它不完全拷贝父进程的地址空间, 但是借用父进程的内存空间和县城控制直到推出或者调用execve(2). 父进程被挂起直到子进程拥有自己的资源(内存空间). 使用vfork是tricky的: 例如,不修改父进程中的数据取决于知道哪些变量保存在寄存器中。

CONFORMING TO
     4.3BSD; POSIX.1-2001 (but marked OBSOLETE). POSIX.1-2008 removes the specification of vfork().

    The requirements put on vfork() by the standards are weaker than those put on fork(2), so an implementation where the two are synonymous is compliant. In particular, the programmer cannot rely on the parent remaining blocked until the child either terminates or calls execve(2), and cannot rely on any specific behavior with respect to shared memory.

    vfork的标准需求弱于fork(2), 所以一种实现的两个函数实现相同. 特别是,在子进程终止或调用execve(2)之前,程序员不能依赖仍被阻塞的父进程,也不能依赖与共享内存相关的任何特定行为。

NOTES
    Some consider the semantics of vfork() to be an architectural blemish, and the 4.2BSD man page stated: “This system call will be eliminated when proper system sharing mechanisms are implemented. Users should not depend on the memory sharing semantics of vfork() as it will, in that case, be made synonymous to fork(2).” However, even though modern memory management hardware has decreased the performance difference between fork(2) and vfork(), there are various reasons why Linux and other systems have retained vfork():
* Some performance-critical applications require the small performance advantage conferred by vfork().
* vfork() can be implemented on systems that lack a memory-management unit (MMU), but fork(2) can’t be implemented on such systems. (POSIX.1-2008 removed vfork() from the standard; the POSIX rationale for the posix_spawn(3) function notes that that function, which provides functionality equivalent to fork(2)+exec(3), is designed to be implementable on systems that lack an MMU.)

    一些人认为vfork()的语义是一个架构缺陷,4.2BSD手册页指出:“当实现适当的系统共享机制时,将消除此系统调用。用户不应该依赖vfork()的内存共享语义,因为在这种情况下,它将成为fork(2)的同义词。“然而,尽管现代内存管理硬件降低了fork(2)和vfork()之间的性能差异,但Linux和其他系统保留vfork()的原因是多方面的:

    *一些性能关键的应用程序需要vfork()所赋予的小性能优势。

    *vfork()可以在缺少内存管理单元(MMU)的系统上实现,但fork(2)不能在此类系统上实现。(POSIX.1-2008从标准中删除了vfork();POSIX_spawn(3)函数的POSIX基本原理指出,该函数提供了相当于fork(2)+exec(3)的功能,设计用于在缺少MMU的系统上实现。)

Linux notes
     Fork handlers established using pthread_atfork(3) are not called when a multithreaded program employing the NPTL threading library calls vfork(). Fork handlers are called in this case in a program using the LinuxThreads threading library. (See pthreads(7) for a description of Linux threading libraries.)
    A call to vfork() is equivalent to calling clone(2) with flags specified as:
         CLONE_VM | CLONE_VFORK | SIGCHLD

    当使用NPTL线程库的多线程程序调用vfork()时,不会调用使用pthread_atfork(3)建立的Fork处理程序。在本例中,Fork处理程序是在使用LinuxThreads线程库的程序中调用的。(参见pthreads(7)了解Linux线程库的说明。)
    调用vfork()等同于使用指定为的标志调用clone(2):
         CLONE_VM | CLONE_VFORK | SIGCHLD

History
The vfork() system call appeared in 3.0BSD. In 4.4BSD it was made synonymous to fork(2) but NetBSD introduced it again, cf. ⟨http://www.netbsd.org/Documentation/kernel/vfork.html⟩. In Linux, it has been equivalent to fork(2) until 2.2.0-pre6 or so. Since
2.2.0-pre9 (on i386, somewhat later on other architectures) it is an independent system call. Support was added in glibc 2.0.112.

BUGS
    Details of the signal handling are obscure and differ between systems. The BSD man page states: “To avoid a possible deadlock situation, processes that are children in the middle of a vfork() are never sent SIGTTOU or SIGTTIN signals; rather, output or ioctls are allowed and input attempts result in an end-of-file indication.”

BUGS
    信号处理的细节不清楚,系统之间也不尽相同。BSD手册页指出:“为了避免可能的死锁情况,vfork()中间的子进程永远不会发送SIGTTOU或SIGTTIN信号;相反,允许输出或ioctl,并且输入尝试会导致文件结束指示。”

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值