A fork() in the road - Microsoft Research https://www.microsoft.com/en-us/research/publication/a-fork-in-the-road/

fork() 成为负担,需要淘汰 - OSCHINA https://www.oschina.net/news/105857/a-fork-in-the-road

A fork() in the road

17th Workshop on Hot Topics in Operating Systems | May 2019

Published by ACM

DOI

The received wisdom suggests that Unix’s unusual combination of fork() and exec() for process creation was an inspired design. In this paper, we argue that fork was a clever hack for machines and programs of the 1970s that has long outlived its usefulness and is now a liability. We catalog the ways in which fork is a terrible abstraction for the modern programmer to use, describe how it compromises OS implementations, and propose alternatives.

As the designers and implementers of operating systems, we should acknowledge that fork’s continued existence as a first-class OS primitive holds back systems research, and deprecate it. As educators, we should teach fork as a historical artifact, and not the first process creation mechanism students encounter.

相信每位开发者都对操作系统中的 fork() 有一定的了解,至少知道它是用来创建进程的。fork 系统调用方式在 20 世纪 70 年代被创造出来,它通常与 exec() 组合使用,非常简单却很强大,被认为是一种天才式的设计、Unix 的伟大思想,至今 50 余年一直作为 POSIX 操作系统的原语存在,同时几乎每个 Unix shell、主要 Web 和数据库服务器、Google Chrome、Redis 甚至 Node.js 都使用 fork。

然而微软系统研究实验室 Redmond 的研究人员 3 月份却发表了一篇论文,表示 fork 作为操作系统原语继续存在,阻碍了对操作系统的研究,“它是来自另一个时代的遗物,不适合现代系统,并且会带来一系列负面影响”,研究人员认为是时候将 fork 淘汰了。

fork 简单已成神话

论文中承认了 fork API 的优点,包括简单与缓解并发性,也肯定了 fork 在历史上的重要贡献,但更多地是列出了它在现代操作系统研究与发展中的弊端。

研究人员认为 fork 本身就存在许多问题,另一方面,fork 在操作系统的研究与发展上也起了限制作用,论文指出有明确的证据表明支持 fork 限制了 OS 体系结构的变化,并限制了操作系统适应硬件演进的能力。

乍一看可能会觉得 fork 很简单,而这也是它的一大特征,但是实际上,“这是一个具有欺骗性的神话”。

fork 已经不再简单。fork 的语义已经影响了每个创建进程状态的新 API 的设计,POSIX 规范现在列出了关于如何将父状态复制到子进度的 25 个特殊情况,包括文件锁定、定时器、异步 IO 操作与跟踪等。此外,许多系统调用标志控制 fork 关于内存映射(Linux madvise() 标记 MADV_DONTFORK/DOFORK/WIPEONFORK 等)、文件描述符(O_CLOEXEC、FD_CLOEXEC)和线程(pthread_atfork())的行为。任何重要的操作系统工具都必须通过 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 的能力与设计水平。

fork() 成为负担,需要淘汰 spawn的更多相关文章

  1. NodeJs之child_process

    一.child_process child_process是NodeJs的重要模块.帮助我们创建多进程任务,更好的利用了计算机的多核性能. 当然也支持线程间的通信. 二.child_process的几 ...

  2. Node.js使用PM2的集群将变得更加容易

    介绍 众所周知,Node.js运行在Chrome的JavaScript运行时平台上,我们把该平台优雅地称之为V8引擎.不论是V8引擎,还是之后的Node.js,都是以单线程的方式运行的,因此,在多核心 ...

  3. 使用PM2将Node.js的集群变得更加容易

    介绍 众所周知,Node.js运行在Chrome的JavaScript运行时平台上,我们把该平台优雅地称之为V8引擎.不论是V8引擎,还是之后的Node.js,都是以单线程的方式运行的,因此,在多核心 ...

  4. Nodejs进阶:如何玩转子进程(child_process)

    本文摘录自个人总结<Nodejs学习笔记>,更多章节及更新,请访问 github主页地址.欢迎加群交流,群号 197339705. 模块概览 在node中,child_process这个模 ...

  5. Node之集群

    介绍 众所周知,Node.js运行在Chrome的JavaScript运行时平台上,我们把该平台优雅地称之为V8引擎.不论是V8引擎,还是之后的Node.js,都是以单线程的方式运行的,因此,在多核心 ...

  6. 【Grunt】关于Grunt可视化的尝试

    使用Grunt遇到的问题? 必须要安装NodeJS 必须安装grunt-cli 需要编写复杂的Gruntfile.js规则 每个项目中必须存在nodejs的grunt模块 不方便管理每一个包含grun ...

  7. node.js(七) 子进程 child_process模块

    众所周知node.js是基于单线程模型架构,这样的设计可以带来高效的CPU利用率,但是无法却利用多个核心的CPU,为了解决这个问题,node.js提供了child_process模块,通过多进程来实现 ...

  8. 关于Grunt可视化的尝试

    关于Grunt可视化的尝试 使用Grunt遇到的问题? 必须要安装NodeJS 必须安装grunt-cli 需要编写复杂的Gruntfile.js规则 每个项目中必须存在nodejs的grunt模块 ...

  9. child_process小解

    js是一种单进程单线程的语言,但现行的cpu都是多核的,为了解决单进程单线程对多核使用不足的问题,child_process应运而生,理想情况下每个进程各自利用一个内核. 主要有四种方法来创建子进程, ...

随机推荐

  1. java利用MultipartRequest的getFileName方法不能得到原文件名问题

    想利用MultipartRequest的getFileName方法来一次获取多个上传的文件名字时,得到的不是文件的名字,而是 input 的name属性 最后找到了答案,解决方法,参照http://s ...

  2. c# 引用与对象举例

  3. skeleton directory: /etc/skel

    第一次接触这个词汇 还是在LFS8.2里面,感觉有点吓人.好好一个计算机操作系统,怎么搞出这个恐怖的术语.... 当使用useradd 或者其他命令创建用户的时候,/etc/skel这个目录下的文件. ...

  4. 【问题】Debian安装、配置sources.list、安装VMware Tools

    Debian安装: 我采用的是纯命令行安装方式.具体安装过程网上一大堆,不介绍了.需要强调一点,那个SSH Server必须选,否则像XShell这样的客户端不能访问Debian. 配置sources ...

  5. Linux基本命令-chmod

           chmod命令用来变更文件或目录的权限.在UNIX系统家族里,文件或目录权限的控制分别以读取.写入.执行3种一般权限来区分,另有3种特殊权限可供运用.用户可以使用chmod指令去变更文件 ...

  6. sklearn逻辑回归实战

    目录 题目要求 ex2data1.txt处理 方案一:无多项式特征 方案二:引入多项式特征 ex2data2.txt处理 两份数据 ex2data1.txt ex2data2.txt 题目要求 根据学 ...

  7. Week08_day01 (Hive实现WordCount计数)

    Hive实现WordCount计数 在没学习Hive之前,我们学习MapReduce去实现WordCount计数的时候,就要去编写80多行的java代码,现在我们学习了Hive,我们只需要一行Sql语 ...

  8. DataWorks入门

    阿里云有很多成熟的云产品(萌新认知),我自己只用过腾讯云的对象存储,对这类云产品不是特别了解. 有幸参与到大数据相关的项目,跟着学了点工具的使用方法,非常简单,也了解了一些使用大数据分析问题的流程. ...

  9. Windows Dialog对话框

    一.MessageBox弹出框 MessageBox.Show(<字符串> Text, <字符串> Title, <整型> nType,MessageBoxIcon ...

  10. IAR添加debug和release选项

    在IAR的Workspace窗口顶部的下拉菜单中有两个选项,Debug和Release. 名字和数量可以在菜单栏的Project-->Edit Configuration中增删修改 每个选项都对 ...