微软研究人员发表论文称用于建立进程的 fork 系统调用方式已经很落后,而且对操做系统的研究与发展产生了极大的负面影响,须要淘汰,做者同时提出了替代方案。
相信每位开发者都对操做系统中的 fork () 有必定的了解,至少知道它是用来建立进程的。fork 系统调用方式在 20 世纪 70 年代被创造出来,它一般与 exec () 组合使用,很是简单却很强大,被认为是一种天才式的设计、Unix 的伟大思想,至今 50 余年一直做为 POSIX 操做系统的原语存在,同时几乎每一个 Unix shell、主要 Web 和数据库服务器、Google Chrome、Redis 甚至 Node.js 都使用 fork。linux
然而微软系统研究实验室 Redmond 的研究人员 3 月份却发表了一篇论文,表示 fork 做为操做系统原语继续存在,阻碍了对操做系统的研究,“它是来自另外一个时代的遗物,不适合现代系统,而且会带来一系列负面影响”,研究人员认为是时候将 fork 淘汰了。程序员
fork 简单已成神话shell
论文中认可了 fork API 的优势,包括简单与缓解并发性,也确定了 fork 在历史上的重要贡献,但更多地是列出了它在现代操做系统研究与发展中的弊端。数据库
研究人员认为 fork 自己就存在许多问题,另外一方面,fork 在操做系统的研究与发展上也起了限制做用,论文指出有明确的证据代表支持 fork 限制了 OS 体系结构的变化,并限制了操做系统适应硬件演进的能力。安全
乍一看可能会以为 fork 很简单,而这也是它的一大特征,可是实际上,“这是一个具备欺骗性的神话”。服务器
fork 的语义已经影响了每一个建立进程状态的新 API 的设计,POSIX 规范如今列出了关于如何将父状态复制到子进度的 25 个特殊状况,包括文件锁定、定时器、异步 IO 操做与跟踪等。此外,许多系统调用标志控制 fork 关于内存映射(Linux madvise () 标记 MADV_DONTFORK/DOFORK/WIPEONFORK 等)、文件描述符(O_CLOEXEC、FD_CLOEXEC)和线程(pthread_atfork ())的行为。任何重要的操做系统工具都必须经过 fork 记录其行为,而且用户模式库必须作好准备,以便随时 fork 它们的状态。fork 已经再也不简单。并发
fork 不是线程安全的,Unix 进程支持线程,但 fork 建立的子进程只有一个线程(调用线程的副本),当一个线程在 fork 时,若是另外一个线程此时进行内存分配并持有堆锁,任何在子进程中分配内存的尝试(从而得到相同的锁)都将当即发生死锁。异步
fork 很慢,fork 的性能一直是个问题,此前使用写时复制技术使其性能可接受,可是在今天,创建写时复制映射自己都成了一个性能问题,好比 Chrome 在 fork 时会经历了长达 100 毫秒的延迟,Node.js 应用在 exec 以前 fork 时,能够被阻塞几秒钟。fork+exec 与 spawn 的性能对比状况能够经过本文开头的图片直观看到。工具
fork 没法扩展,系统规模的设计首先要避免没必要要的共享,但 fork 进程会与其父进程共享全部内容,因为 fork 复制了进程操做系统状态的各个方面,这样复制与引用计数成本会比较低,因此 fork 实际上是趋向于将状态集中在单片内核中,这就使得难以实现一些新技术,好比用于安全性和可靠性的内核划分。性能
fork 与异构硬件不兼容,它将进程的抽象与包含它的硬件地址空间混为一谈。fork 将进程的定义限制为单个地址空间,而且是在某个核心上运行的单个线程。但现代硬件和在其上运行的程序并非这样,硬件异构化愈来愈严重,使用有内核旁路 NIC 的 DPDK 或带有 GPU 的 OpenCL 的进程没法安全地 fork,由于操做系统没法复制 NIC/GPU 上的进程状态。这个问题至少已经困扰了 GPU 程序员十年,而随着将来的芯片上系统包含愈来愈多的状态加速器,状况只会变得更糟。
“GET THE FORK OUT OF MY OS!”
论文提出了替代 fork 的方案:包括一个高级 Spawn API 和一个低级类微内核 API 的组合。涉及到 posix_spawn ()、vfork ()、跨进程操做、clone ()、改进写时复制内存等内容。
fork 的问题愈来愈严重,做者最后总结出必须作三件事来纠正这种状况,不只要弃用 fork,还要改善替代方案,同时纠正咱们关于 fork 的教学内容,不能再错误地宣扬 fork 的能力与设计水平.