在Unix中调用fork()时会发生什么?

Rob*_* P. 18 c unix fork process

我试着仔细研究一下,但是在调用fork()之后,我正在努力理解父进程和子进程之间的关系.

它们是完全独立的进程,只与id/parent id相关联吗?或者他们共享记忆?例如,每个进程的"代码"部分是重复的,以便每个进程都有自己的相同副本,或者以某种方式'共享'以便只存在一个?

我希望这是有道理的.

以完全披露的名义,这是"与家庭作业相关"; 虽然不是书中的直接问题,但我感觉它主要是学术性的,在实践中,我可能不需要知道.

jpa*_*jpa 22

在整个过程中,整个内存都是重复的.

实际上,它使用"写入时复制"系统.第一次进程在fork()之后更改其内存时,会对已修改的页面(通常为4kB)进行单独的复制.

通常,流程的代码段不会被修改,在这种情况下,它仍然是共享的.


Mar*_*tos 17

从逻辑上讲,fork会创建原始进程的相同副本,该副本在很大程度上独立于原始进程.出于性能原因,内存与copy-on-write语义共享,这意味着未修改的内存(如代码)仍然是共享的.

文件描述符是重复的,因此分叉进程原则上可以代表父进程接管数据库连接(或者如果程序员有点扭曲,它们甚至可以与数据库联合通信).更常见的是,这用于在进程之间设置管道,以便您可以编写find -name '*.c' | xargs grep fork.

一堆其他的东西是共享的.详情请见此处.

一个重要的遗漏是线程 - 子进程只继承调用的线程fork().这导致多线程程序中没有问题,因为锁定在父级中的互斥锁等的状态是特定于实现的(并且不要忘记malloc()并在printf()内部使用锁).fork()返回后孩子唯一安全的做法就是尽快打电话execve(),即使这样你也必须对文件描述符保持谨慎.见这里的完整的恐怖故事.


Ano*_*non 6

  1. 它们是单独的进程,即Child和Parent将具有单独的PID
  2. 子将继承Parent中的所有开放描述符
  3. 在内部,页面即可以与.text区域不同地修改的堆栈/堆区域将与父项和子项共享,直到其中一个尝试修改内容为止.在这种情况下,将创建一个新页面,并将特定于正在修改的页面的数据复制到这个新分配的页面,并映射到与导致更改的页面相对应的区域 - 可以是父级或子级.这被称为COW(上面的论坛中其他成员在他们的答案中提到).
  4. Child可以完成执行,直到父级使用wait()或waitpid()调用回收,将处于ZOMBIE状态.这将有助于从进程表中清除子进程的进程,并允许重用子进程.通常当一个子节点死亡时,SIGCHLD信号被发送到父节点,这将理想地导致在该处理程序中执行wait()调用之后调用处理程序.
  5. 如果Parent退出但没有清理已经运行或僵尸的子进程(通过wait()waitpid调用),init()进程(PID 1)将成为这些现在孤儿的父进程.此init()进程定期执行wait()或waitpid()调用.

编辑:错别字HTH