fbpx
维基百科

fork (系统调用)

计算机领域中,尤其是Unix类Unix系统操作系统中,fork(进程复制)是一种创建自身行程副本的操作。它通常是内核实现的一种系统调用。Fork是类Unix操作系统上创建进程的一种主要方法,甚至历史上是唯一方法。

概述 编辑

在多任务操作系统中,行程(运行的程序)需要一种方法来创建新进程,例如运行其他程序。Fork及其变种在类Unix系统中通常是这样做的唯一方式。如果进程需要启动另一个程序的可执行文件,它需要先Fork来创建一个自身的副本。然后由该副本即“子进程”调用exec英语Exec (computing)系统调用,用其他程序覆盖自身:停止执行自己之前的程序并执行其他程序。

Fork操作会为子进程创建一个单独的定址空間。子进程拥有父进程所有内存段的精确副本。在现代的UNIX变种中,这遵循出自SunOS-4.0的虚拟内存模型,根据寫入時複製语义,物理内存不需要被实际复制。取而代之的是,两个进程的虚拟内存页面英语Virtual memory pages可能指向物理内存中的同一个页,直到它们写入该页时,写入才会发生。在用fork配合exec来执行新程序的情况下,此优化很重要。通常来说,子进程在停止程序运行前会执行一小组有利于其他程序的操作,它可能用到少量的其父进程的数据结构

当一个进程调用fork时,它被认为是父进程,新创建的进程是它的孩子(子进程)。在fork之后,两个进程还运行着相同的程序,都像是调用了该系统调用一般恢复执行。然后它们可以检查调用的返回值英语Return value确定其状态:是父进程还是子进程,以及据此行事。

fork系统调用在第一个版本的Unix就已存在[1],它借用于更早的GENIE英语Project Genie 分時系統[2]Fork是标准化的POSIX的一部分。[3]

通信 编辑

子进程从父进程的文件描述符副本开始。[3]对于进程间通信,父进程通常会创建一个或多个管道,在fork进程之后,进程关闭它们不需要的管道端。[4]

变种 编辑

Vfork 编辑

Vfork是与fork具有相同调用约定和很多相同语义的一个变种,但只能在有限的情况下使用它。它起源于Unix的3BSD版本[5][6][7],这是首个支持虚拟内存的Unix版本。它已按POSIX标准化,这使得vfork能具有与fork完全相同的行为。但这已在2004年的版本中被标为过时[8],并在后续版本中被posix_spawn()取代(其通常通过vfork实现)。

在发出一个vfork系统调用时,父进程被暂停,直至子进程完成执行或被新的可执行映像取代(通过系统调用之“exec英语Exec (computing)”家族中的一项)。子进程借用父进程的MMU设置和内存页面,在父进程与子进程之间共享,不进行复制,尤其是没有寫入時複製语义;[8]因此,如果子进程在任何共享页面中进行修改,不会创建新的页面,并且修改的页面对父进程同样可见。因为没有页面复制(消耗额外的内存),此技术在纯复制环境中使用exec时较普通fork更优化。在POSIX中,除非是将立即调用exec家族(及其他几个操作)的函数,其他任何目的会导致未定义行为[8]使用vfork时,子进程借用而非复制数据结构,所以vfork仍比使用写时复制语义的fork更快。

System V在System VR4被引入前不支持此系统函数,因为它的内存共享容易出错:

Vfork does not copy page tables so it is faster than the System V fork implementation. But the child process executes in the same physical address space as the parent process (until an exec or exit) and can thus overwrite the parent's data and stack. A dangerous situation could arise if a programmer uses vfork incorrectly, so the onus for calling vfork lies with the programmer. The difference between the System V approach and the BSD approach is philosophical: Should the kernel hide idiosyncrasies of its implementation from users, or should it allow sophisticated users the opportunity to take advantage of the implementation to do a logical function more efficiently?

——Maurice J. Bach[9]

同样,Linux对vfork的手册页面强烈不鼓励它的使用:[5]

It is rather unfortunate that Linux revived this specter from the past. The BSD man page states: "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)."

使用vfork的其他问题包括死锁 ,它可能发生在多线程程序中,由于与动态链接交互。[10] 作为vfork接口的替代品,POSIX引入了posix_spawn函数家族,它结合了fork和exec的动作。这些函数可以实现为fork的程序库例程,就像Linux那样[10],或者为了更好的性能实现为vfork ,就像Solaris那样[10][11]。不过,POSIX规范中注明它是“为内核操作设计”,尤其是用于运行在受限硬件和实时系统上的操作系统。[12]

虽然4.4BSD的实现中摆脱了vfork的实现,使vfork做到与fork相同的行为,它在NetBSD操作系统中因性能原因而恢复。[6]

一些嵌入式操作系统(例如uClinux)省略fork并只实现vfork,因为它们需要在由于缺乏内存管理单元(MMU)而不可能实现写时复制的设备上操作。

Rfork 编辑

Plan 9操作系统由Unix的设计者创造,包括fork,但也有一个名为“rfork”的变种,它允许父进程与子进程之间资源的细粒度共享,包括地址空间(除了调用栈段,那是每个进程独有的)、环境变量文件系统命名空间[13]这使它成为了创建进程和其中的线程的一个统一接口。[14]FreeBSD[15]IRIX中采用了来自Plan 9的rfork,后者将其更名为“sproc”。[16]

Clone 编辑

“clone”(克隆)是Linux内核中的一个系统调用,它创建一个可以与其父共享“执行上下文”的子进程。类似FreeBSD的rfork和IRIX的sproc,Linux的clone受到了Plan 9的rfork启发,并可用于实现线程(尽管应用程序的程序员通常使用更高级的接口,例如pthreads,实现在clone的顶层)。出自Plan 9和IRIX的“separate stacks”(单独堆栈)特性已被省略,因为其导致了太多开销(据Linus Torvalds)。[16]

其他操作系统中的Fork 编辑

VMS操作系统(1977年)的原始设计中,新进程根据当前一些特定地址进行复制来创建被认为是有风险的。当前进程中的错误状态可能被复制给子进程。因此在这里使用了进程“产卵”(spawning)之隐喻:新进程的每个组件的内存布局都是重新创建的。spawn英语Spawn (computing)后来被微软的操作系统采用(1993年)。

VM/CMS(OpenExtensions)的POSIX兼容组件提供了一个非常有限的fork实现,其中的父进程在子进程执行时被暂停,并且子与父共享同一地址空间。[17]这本质上是一个名为fork的vfork。(注意,这只适用于CMS客户机操作系统,其他VM客户机操作系统如Linux提供标准的fork功能。)

应用程序范例 编辑

下列Hello World程序的变种以C语言展示了fork系统调用的机理。该程序fork为两个进程,每个都基于fork系统调用的返回值决定它们执行什么功能。样板代码英语Boilerplate code中的头文件等已被省略。

int main(void) {  pid_t pid = fork();  if (pid == -1) {  perror("fork failed");  exit(EXIT_FAILURE);  }  else if (pid == 0) {  printf("Hello from the child process!\n");  _exit(EXIT_SUCCESS);  }  else {  int status;  (void)waitpid(pid, &status, 0);  }  return EXIT_SUCCESS; } 

下面是该程序的解析:

 pid_t pid = fork(); 

调用中的第一句是调用fork系统调用来分割执行为两个进程。fork的返回值被记录在类型为pid_t的变量中,其中是POSIX类型的进程标识符(PID)。

计算机领域,尤其是Unix类Unix系统操作系统中,fork是一种创建自身行程副本的操作。它通常是内核实现的一种系统调用。Fork是在类Unix操作系统上创建进程的一种主要方法,甚至历史上曾是唯一方法。

-1错误表示fork出错:没有新进程被创建。因此要印出一条错误消息。

如果fork成功,那么现在有两个进程。两者都从fork返回时开始执行main函数。为了使进程执行不同的任务,程序必须基于fork的返回值决定其作为子进程或父进程执行某个分支

 else if (pid == 0) {  printf("Hello from the child process!\n");  _exit(EXIT_SUCCESS);  } 

Fork操作会为子进程创建一个单独的定址空間。子进程拥有父进程所有内存段的精确副本。在现代的UNIX变种中,这遵循出自SunOS-4.0的虚拟内存模型,根据寫入時複製语义,物理内存不需要被实际复制。取而代之的是,两个进程的虚拟内存页面英语virtual memory pages可能指向物理内存中的同一个页,直至它们写入该页时,写入才会发生。在用fork配合exec来执行新程序的情况下,此优化很重要。通常,子进程在停止程序运行前会执行一小组有利于其他程序的操作,它可能用到少量的其父进程的数据结构

 else {  int status;  (void)waitpid(pid, &status, 0);  } 

其他进程——即父进程,会收到fork传来的子进程的进程标识符,其始终为一个正数。父进程将此标识符传递给 waitpid 系统调用来暂停执行,直至子进程退出。当此情况发生后,父进程继续执行并按return语句的含义退出。

参见 编辑

  • fork炸弹
  • Fork–exec英语Fork–exec
  • Exit英语Exit (operating system)
  • Wait

参考资料 编辑

  1. ^ Ken ThompsonDennis Ritchie. (PDF). UNIX Programmer's Manual. Bell Laboratories. 3 November 1971 [2016年12月2日]. (原始内容 (PDF)存档于2015年2月3日). 
  2. ^ Ritchie, Dennis M.; Thompson, Ken. (PDF). Bell System Tech. J. (AT&T). July 1978, 57 (6): 1905–1929 [22 April 2014]. doi:10.1002/j.1538-7305.1978.tb02136.x. (原始内容 (PDF)存档于2015-06-11). 
  3. ^ 3.0 3.1 fork – 系统界面(System Interfaces)参考,单一UNIX®规范第7期,由國際開放標準組織发布
  4. ^ pipe – 系统界面(System Interfaces)参考,单一UNIX®规范第7期,由國際開放標準組織发布
  5. ^ 5.0 5.1 vfork(2) – Linux程序员手册页 – 系统调用(System Calls)
  6. ^ 6.0 6.1 NetBSD Documentation: Why implement traditional vfork(). NetBSD Project. [16 October 2013]. (原始内容于2016-12-22). 
  7. ^ vfork(2). UNIX Programmer's Manual, Virtual VAX-11 Version. University of California, Berkeley. December 1979. 
  8. ^ 8.0 8.1 8.2 [[[:Template:Man/SUS6]] vfork(Template:Man/SUS6)] – Template:Man/SUS6
  9. ^ Bach, Maurice J. The Design of The UNIX Operating System. Prentice–Hall. 1986: 291–292. 
  10. ^ 10.0 10.1 10.2 Nakhimovsky, Greg. Minimizing Memory Usage for Creating Application Subprocesses. Oracle Technology Network. Oracle Corporation. 2006 [2016-12-02]. (原始内容于2016-12-03). 
  11. ^ The OpenSolaris posix_spawn() implementation: https://sourceforge.net/p/schillix-on/schillix-on/ci/default/tree/usr/src/lib/libc/port/threads/spawn.c (页面存档备份,存于互联网档案馆
  12. ^ posix_spawn – 系统界面(System Interfaces)参考,单一UNIX®规范第7期,由國際開放標準組織发布
  13. ^ fork(2) – Plan 9库函数和系统调用(Library Functions and System Calls)手册页
  14. ^ intro(2) – Plan 9库函数和系统调用(Library Functions and System Calls)手册页
  15. ^ rfork(2) – FreeBSD系统调用(System Calls)手册页
  16. ^ 16.0 16.1 Torvalds, Linus. The Linux edge. Open Sources: Voices from the Open Source Revolution. O'Reilly. 1999 [2016-12-02]. ISBN 1-56592-582-3. (原始内容于2014-04-21). 
  17. ^ z/VM > z/VM 6.2.0 > Application Programming > z/VM V6R2 OpenExtensions POSIX Conformance Document > POSIX.1 Conformance Document > Section 3. Process Primitives > 3.1 Process Creation and Execution > 3.1.1 Process Creation. IBM. [April 21, 2015]. (原始内容于2019-10-16). 

fork, 系统调用, 此條目翻譯自其他語言維基百科, 需要相關領域的編者協助校對翻譯, 如果您精通本領域, 又能清楚地將來源語言翻譯為中文, 歡迎您協助校訂翻譯, 原文参见维基数据, 此條目需要精通或熟悉相关主题的编者参与及协助编辑, 請邀請適合的人士改善本条目, 更多的細節與詳情請參见討論頁, 关于软件开发之中的fork概念, 請見, 分叉, 软件开发, 在计算机领域中, 尤其是unix及类unix系统操作系统中, fork, 进程复制, 是一种创建自身行程副本的操作, 它通常是内核实现的一种系统调用, for. 此條目翻譯自其他語言維基百科 需要相關領域的編者協助校對翻譯 如果您精通本領域 又能清楚地將來源語言翻譯為中文 歡迎您協助校訂翻譯 原文参见维基数据 此條目需要精通或熟悉相关主题的编者参与及协助编辑 請邀請適合的人士改善本条目 更多的細節與詳情請參见討論頁 关于软件开发之中的Fork概念 請見 分叉 软件开发 在计算机领域中 尤其是Unix及类Unix系统操作系统中 fork 进程复制 是一种创建自身行程副本的操作 它通常是内核实现的一种系统调用 Fork是类Unix操作系统上创建进程的一种主要方法 甚至历史上是唯一方法 目录 1 概述 2 通信 3 变种 3 1 Vfork 3 2 Rfork 3 3 Clone 4 其他操作系统中的Fork 5 应用程序范例 6 参见 7 参考资料概述 编辑在多任务操作系统中 行程 运行的程序 需要一种方法来创建新进程 例如运行其他程序 Fork及其变种在类Unix系统中通常是这样做的唯一方式 如果进程需要启动另一个程序的可执行文件 它需要先Fork来创建一个自身的副本 然后由该副本即 子进程 调用exec 英语 Exec computing 系统调用 用其他程序覆盖自身 停止执行自己之前的程序并执行其他程序 Fork操作会为子进程创建一个单独的定址空間 子进程拥有父进程所有内存段的精确副本 在现代的UNIX变种中 这遵循出自SunOS 4 0的虚拟内存模型 根据寫入時複製语义 物理内存不需要被实际复制 取而代之的是 两个进程的虚拟内存页面 英语 Virtual memory pages 可能指向物理内存中的同一个页 直到它们写入该页时 写入才会发生 在用fork配合exec来执行新程序的情况下 此优化很重要 通常来说 子进程在停止程序运行前会执行一小组有利于其他程序的操作 它可能用到少量的其父进程的数据结构 当一个进程调用fork时 它被认为是父进程 新创建的进程是它的孩子 子进程 在fork之后 两个进程还运行着相同的程序 都像是调用了该系统调用一般恢复执行 然后它们可以检查调用的返回值 英语 Return value 确定其状态 是父进程还是子进程 以及据此行事 fork系统调用在第一个版本的Unix就已存在 1 它借用于更早的GENIE 英语 Project Genie 分時系統 2 Fork是标准化的POSIX的一部分 3 通信 编辑子进程从父进程的文件描述符副本开始 3 对于进程间通信 父进程通常会创建一个或多个管道 在fork进程之后 进程关闭它们不需要的管道端 4 变种 编辑Vfork 编辑 Vfork是与fork具有相同调用约定和很多相同语义的一个变种 但只能在有限的情况下使用它 它起源于Unix的3BSD版本 5 6 7 这是首个支持虚拟内存的Unix版本 它已按POSIX标准化 这使得vfork能具有与fork完全相同的行为 但这已在2004年的版本中被标为过时 8 并在后续版本中被posix spawn 取代 其通常通过vfork实现 在发出一个vfork系统调用时 父进程被暂停 直至子进程完成执行或被新的可执行映像取代 通过系统调用之 exec 英语 Exec computing 家族中的一项 子进程借用父进程的MMU设置和内存页面 在父进程与子进程之间共享 不进行复制 尤其是没有寫入時複製语义 8 因此 如果子进程在任何共享页面中进行修改 不会创建新的页面 并且修改的页面对父进程同样可见 因为没有页面复制 消耗额外的内存 此技术在纯复制环境中使用exec时较普通fork更优化 在POSIX中 除非是将立即调用exec家族 及其他几个操作 的函数 其他任何目的会导致未定义行为 8 使用vfork时 子进程借用而非复制数据结构 所以vfork仍比使用写时复制语义的fork更快 System V在System VR4被引入前不支持此系统函数 因为它的内存共享容易出错 Vfork does not copy page tables so it is faster than the System V fork implementation But the child process executes in the same physical address space as the parent process until an exec or exit and can thus overwrite the parent s data and stack A dangerous situation could arise if a programmer uses vfork incorrectly so the onus for calling vfork lies with the programmer The difference between the System V approach and the BSD approach is philosophical Should the kernel hide idiosyncrasies of its implementation from users or should it allow sophisticated users the opportunity to take advantage of the implementation to do a logical function more efficiently Maurice J Bach 9 同样 Linux对vfork的手册页面强烈不鼓励它的使用 5 It is rather unfortunate that Linux revived this specter from the past The BSD man page states 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 使用vfork的其他问题包括死锁 它可能发生在多线程程序中 由于与动态链接交互 10 作为vfork接口的替代品 POSIX引入了posix spawn函数家族 它结合了fork和exec的动作 这些函数可以实现为fork的程序库例程 就像Linux那样 10 或者为了更好的性能实现为vfork 就像Solaris那样 10 11 不过 POSIX规范中注明它是 为内核操作设计 尤其是用于运行在受限硬件和实时系统上的操作系统 12 虽然4 4BSD的实现中摆脱了vfork的实现 使vfork做到与fork相同的行为 它在NetBSD操作系统中因性能原因而恢复 6 一些嵌入式操作系统 例如uClinux 省略fork并只实现vfork 因为它们需要在由于缺乏内存管理单元 MMU 而不可能实现写时复制的设备上操作 Rfork 编辑 Plan 9操作系统由Unix的设计者创造 包括fork 但也有一个名为 rfork 的变种 它允许父进程与子进程之间资源的细粒度共享 包括地址空间 除了调用栈段 那是每个进程独有的 环境变量和文件系统命名空间 13 这使它成为了创建进程和其中的线程的一个统一接口 14 在FreeBSD 15 和IRIX中采用了来自Plan 9的rfork 后者将其更名为 sproc 16 Clone 编辑 clone 克隆 是Linux内核中的一个系统调用 它创建一个可以与其父共享 执行上下文 的子进程 类似FreeBSD的rfork和IRIX的sproc Linux的clone受到了Plan 9的rfork启发 并可用于实现线程 尽管应用程序的程序员通常使用更高级的接口 例如pthreads 实现在clone的顶层 出自Plan 9和IRIX的 separate stacks 单独堆栈 特性已被省略 因为其导致了太多开销 据Linus Torvalds 16 其他操作系统中的Fork 编辑在VMS操作系统 1977年 的原始设计中 新进程根据当前一些特定地址进行复制来创建被认为是有风险的 当前进程中的错误状态可能被复制给子进程 因此在这里使用了进程 产卵 spawning 之隐喻 新进程的每个组件的内存布局都是重新创建的 spawn 英语 Spawn computing 后来被微软的操作系统采用 1993年 VM CMS OpenExtensions 的POSIX兼容组件提供了一个非常有限的fork实现 其中的父进程在子进程执行时被暂停 并且子与父共享同一地址空间 17 这本质上是一个名为fork的vfork 注意 这只适用于CMS客户机操作系统 其他VM客户机操作系统如Linux提供标准的fork功能 应用程序范例 编辑下列Hello World程序的变种以C语言展示了fork系统调用的机理 该程序fork 为两个进程 每个都基于fork 系统调用的返回值决定它们执行什么功能 样板代码 英语 Boilerplate code 中的头文件等已被省略 int main void pid t pid fork if pid 1 perror fork failed exit EXIT FAILURE else if pid 0 printf Hello from the child process n exit EXIT SUCCESS else int status void waitpid pid amp status 0 return EXIT SUCCESS 下面是该程序的解析 pid t pid fork 调用中的第一句是调用fork 系统调用来分割执行为两个进程 fork 的返回值被记录在类型为pid t的变量中 其中是POSIX类型的进程标识符 PID 在计算机领域 尤其是Unix及类Unix系统操作系统中 fork是一种创建自身行程副本的操作 它通常是内核实现的一种系统调用 Fork是在类Unix操作系统上创建进程的一种主要方法 甚至历史上曾是唯一方法 1错误表示fork 出错 没有新进程被创建 因此要印出一条错误消息 如果fork 成功 那么现在有两个进程 两者都从fork 返回时开始执行main 函数 为了使进程执行不同的任务 程序必须基于fork 的返回值决定其作为子进程或父进程执行某个分支 else if pid 0 printf Hello from the child process n exit EXIT SUCCESS Fork操作会为子进程创建一个单独的定址空間 子进程拥有父进程所有内存段的精确副本 在现代的UNIX变种中 这遵循出自SunOS 4 0的虚拟内存模型 根据寫入時複製语义 物理内存不需要被实际复制 取而代之的是 两个进程的虚拟内存页面 英语 virtual memory pages 可能指向物理内存中的同一个页 直至它们写入该页时 写入才会发生 在用fork 配合exec 来执行新程序的情况下 此优化很重要 通常 子进程在停止程序运行前会执行一小组有利于其他程序的操作 它可能用到少量的其父进程的数据结构 else int status void waitpid pid amp status 0 其他进程 即父进程 会收到fork 传来的子进程的进程标识符 其始终为一个正数 父进程将此标识符传递给 waitpid 系统调用来暂停执行 直至子进程退出 当此情况发生后 父进程继续执行并按return语句的含义退出 参见 编辑fork炸弹 Fork exec 英语 Fork exec Exit 英语 Exit operating system Wait参考资料 编辑 Ken Thompson和Dennis Ritchie SYS FORK II PDF UNIX Programmer s Manual Bell Laboratories 3 November 1971 2016年12月2日 原始内容 PDF 存档于2015年2月3日 Ritchie Dennis M Thompson Ken The UNIX Time Sharing System PDF Bell System Tech J AT amp T July 1978 57 6 1905 1929 22 April 2014 doi 10 1002 j 1538 7305 1978 tb02136 x 原始内容 PDF 存档于2015 06 11 3 0 3 1 fork 系统界面 System Interfaces 参考 单一UNIX 规范第7期 由國際開放標準組織发布 pipe 系统界面 System Interfaces 参考 单一UNIX 规范第7期 由國際開放標準組織发布 5 0 5 1 vfork 2 Linux程序员手册页 系统调用 System Calls 6 0 6 1 NetBSD Documentation Why implement traditional vfork NetBSD Project 16 October 2013 原始内容存档于2016 12 22 vfork 2 UNIX Programmer s Manual Virtual VAX 11 Version University of California Berkeley December 1979 8 0 8 1 8 2 Template Man SUS6 vfork Template Man SUS6 Template Man SUS6 Bach Maurice J The Design of The UNIX Operating System Prentice Hall 1986 291 292 10 0 10 1 10 2 Nakhimovsky Greg Minimizing Memory Usage for Creating Application Subprocesses Oracle Technology Network Oracle Corporation 2006 2016 12 02 原始内容存档于2016 12 03 The OpenSolaris posix spawn implementation https sourceforge net p schillix on schillix on ci default tree usr src lib libc port threads spawn c 页面存档备份 存于互联网档案馆 posix spawn 系统界面 System Interfaces 参考 单一UNIX 规范第7期 由國際開放標準組織发布 fork 2 Plan 9库函数和系统调用 Library Functions and System Calls 手册页 intro 2 Plan 9库函数和系统调用 Library Functions and System Calls 手册页 rfork 2 FreeBSD系统调用 System Calls 手册页 16 0 16 1 Torvalds Linus The Linux edge Open Sources Voices from the Open Source Revolution O Reilly 1999 2016 12 02 ISBN 1 56592 582 3 原始内容存档于2014 04 21 z VM gt z VM 6 2 0 gt Application Programming gt z VM V6R2 OpenExtensions POSIX Conformance Document gt POSIX 1 Conformance Document gt Section 3 Process Primitives gt 3 1 Process Creation and Execution gt 3 1 1 Process Creation IBM April 21 2015 原始内容存档于2019 10 16 取自 https zh wikipedia org w index php title Fork 系统调用 amp oldid 66480011, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。