- 学 科
- 计算机科学
- 外文名
- UNIX
- 类 型
- 多用户、多任务操作系统
- 中文名
- 尤尼克斯
- 设计原则
- 简洁至上、提供机制而非策略
-
Unix/Linux fork前传
2019-09-09 08:15:00本文是《Linux fork那些隐藏的开销》的前传。fork的由来fork的思想在UNIX出现几年前就出现了,时间大概是1963年,这比UNIX在PDP-7上的第一个版本...本文是《Linux fork那些隐藏的开销》的前传。
fork的由来
fork的思想在UNIX出现几年前就出现了,时间大概是1963年,这比UNIX在PDP-7上的第一个版本早了6年。
1963年,计算机科学家Melvin Conway(以Conway’s Law闻名于世)写下一篇论文,正式提出了fork思想,该论文链接:A Multiprocessor System Design:
https://archive.org/details/AMultiprocessorSystemDesignConway1963/page/n7
fork的思想最初是Conway作为一种 多处理器并行 的方案提出来的,这个想法非常有意思。简而言之,fork思想来源于流程图。
我们看一个普通的流程图:
你看,流程图的分枝处,fork-叉子,多么形象!
一个流程图上的分支点分裂出来的分支显然是逻辑独立的,这便是可并行的前提,于是它们便可以表现为不同的 处理进程(process) 的形式,当时的表达还只是“process”这个术语,它还不是现代操作系统意义上的“进程”的概念。
join同步点表现为多个并行处理的进程由于某种原因不得不同步的点,也就是多个并行流程汇合的点,直到现在,在多线程编程中,这个点依然叫join。比如Java Thread的join方法以及pthread库的pthread_join函数。
广义来讲,join也表示诸如临界区等必须串行通过的点, 减少join点的数量将会提高并行的效率。
我们来看看Conway论文中关于fork的原始图示:
Conway在论文中的另一个创举是,他将处理进程(也就是后来操作系统中的process的概念)以及执行该进程的处理器(即CPU核)分离了开来,抽象出了schedule层。
大意是说, “只要满足系统中的活动处理器数量是总处理器数量和并行处理进程的最小值即可。” 这意味着调度程序可以将多处理器系统的所有处理器和系统所有处理进程分别看作是统一的资源池和消费者,执行统一调度:
在UNIX引入fork之后,这种多处理器并行的设计思想就深入到了UNIX的核心。这个思想最终也影响了UNIX以及后来的Linux,直到现在。
关于这个设计思想为什么可以影响UNIX这么久,我想和Conway本人的“Conway’s law”不无关系,在这个law中,他提到:Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization’s communication structure.
好了,fork本身的由来我们已经了解,就像做菜一样,现在我们把它放在一边备用。
花开两朵,各表一枝。接下来看UNIX fork的另一个脉络。
早期UNIX的覆盖(overlaying)技术
1969年最初的UNIX用一种在现在看来非常奇怪的方式运行。
一般的资料都是从UNIX v6版本开始讲起,那个版本已经是比较 “现代” 的版本了,所以很少有人能看到最初的UNIX是什么样子的。即便是能查阅到的1970年的PDP-7上运行的UNIX源码,也是引入fork之后的版本,在那之前的最原始版本几乎找不到了(你可能会说,那时的UNIX不叫UNIX,but who cares…)。
1969年的汤普森版UNIX超级简陋,这可以在Dennis M. Ritchie的一篇论文中见一斑:The Evolution of the Unix Time-sharing System:
http://www.read.seas.harvard.edu/~kohler/class/aosref/ritchie84evolution.pdf
最初的UNIX是一个分时系统,它只有两个shell进程,分别属于两个终端:
分时系统最初并不是基于进程分时的,那时根本还没有完整的进程的概念,分时系统是针对终端分时的,而操作员坐在终端前,为了让每个操作员在操作过程中感觉上是在独占机器资源,每个终端享受一段时间的时间片,在该时间片内,该终端前的操作员完全享受机器,但是为了公平,超过了时间片,时间片就要给另一个终端。
就是这样,最初的UNIX为了体现分时特性,实现了最少的两个终端。注意,最初的UNIX没有fork,没有exec,甚至没有多进程的概念,为了实现分时,系统中仅有两个朴素的shell进程。
事实上,最初的UNIX用只有两个元素的表来容纳所有进程(显然,这看起来好笑…),当然,这里的 “表” 的概念也是抽象的朴素概念,因为当时的系统是用PDP-7的汇编写的,还没有后来C语言数据结构。
我们现在考虑其中一个终端的shell进程如何工作。马上问题就来了, 这个shell进程如何执行别的命令程序??
如果说系统中最多只能容纳两个进程,一个终端只有一个shell进程的话,当该终端的shell进程执行其它命令程序时,它自己怎么办?这个问题得思考一会儿…
注意,不要用现代的眼光去评价1969年的初版UNIX,按照现代的眼光,执行一个程序必然要生成一个新的进程,显然这在初版UNIX中并不正确。
答案是根本不用产生新的进程,直接将命令程序的代码载入内存并 覆盖 掉shell进程的代码即可!当命令执行完后,再用shell的代码覆盖掉命令程序的代码,针对单独的终端,系统其实一直在执行下面的覆盖循环(摘自论文的Process control 章节):
然而,在fork被引入UNIX之前,事实就是这样。一个终端上一直都是那一个进程,一会儿它执行shell的代码,一会儿它执行具体命令程序的代码,以下是一个覆盖程序的结构(图片来自《FreeBSD操作系统设计与实现》一书):
然而,当时毕竟还没有将这个逻辑封装成exec系统调用,这些都是每一个进程显式完成的:
对于shell执行命令程序而言,shell自己执行disk IO来载入命令程序覆盖掉自身;
对于命令程序执行结束时,exit调用内部执行disk IO载入shell程序。
exec逻辑是shell程序的一部分,由于它会被所有的命令程序所使用,该逻辑也被封装到了exit调用中。
fork引入UNIX前的表象
好了,目前为止,我们看完了两条线索:
1963年Melvin Conway提出了fork思想,作为在多处理器中并行执行进程的一个手段。
1969年汤普森版UNIX仅有两个shell进程,使用覆盖(overlaying)技术执行命令。
截止目前,我们看到的表象是:
汤普森版UNIX没有fork,没有exec,没有wait,仅有的库函数般的exit也和现在的exit系统调用大相径庭,显然汤普森版UNIX并非一个多进程系统,而只是一个可以跑的简陋的两终端分时系统!
UNIX fork的诞生
fork是如何引入UNIX的呢?
这还要从采用覆盖技术的汤普森版UNIX所固有的问题说起,还是看论文原文:
若要解决这些问题,很简单的方案汤普森都想到了:
保持shell进程的驻留而不是销毁。命令执行时,将其交换到磁盘便是了
很显然,命令程序是不能覆盖掉shell进程了。解决方案是使用 “交换” 技术。
交换技术和覆盖技术其实都是解决有限内存的多进程使用问题的,不同点在于方向不同:
覆盖技术指的是用不同的进程磁盘映像覆盖当前的进程内存映像。
交换技术指的是用将进程的内存映像交换到磁盘,载入一个别的进程磁盘映像。
使用交换技术解决覆盖的问题,意味着要创建新的进程:
在新的进程中执行命令程序。
UNIX需要进行改动,两个配额的进程表显然不够用了。当然,解决方案也并不麻烦:
要讲效率,创造不如抄袭,创建新进程的最直接的就是copy当前shell进程,在copy的新进程中执行覆盖,命令程序覆盖copy的新进程,而当前的终端shell进程则被交换到磁盘保得全身。
覆盖和交换相结合了,UNIX离现代化更近了一步!
确定了copy当前进程的方案后,进一步的问题是如何来copy进程。
现在要说回fork了。
Conway提出fork思想后,马上就有了fork的实现原型(正如Conway自己所说,他只是提出了一个可能造就存在的想法,并没有实现它),Project Genie算是实现fork比较完善的系统之一了。
Project Genie系统的fork不仅仅是盲目地copy进程,它对fork的过程拥有精细的控制权,比如分配多大的内存空间,copy哪些必要的资源等等。显然,Project Genie的fork是冲着Conway的多处理器并行逻辑去的。
还是那句话,创造不如抄袭,UNIX若想实现进程copy,有一个现成的模版就是Project Genie,但是Project Genie的fork对于UNIX太过复杂,太过精细化了,UNIX显然用不到这些精细的控制, UNIX仅仅是想让fork出来的新进程被覆盖,而不是让它去执行什么多处理器上的并行逻辑。
换句话说,UNIX只是借用了fork的copy逻辑的实现,来完成一件别的事。
于是,UNIX非常粗暴的实现了fork!即完全copy父进程,这就是直到现在我们依然在使用的fork系统调用:
取了个巧,奇技淫巧:
fork本来就不是让你用来覆盖新进程的,不然为何多此一举。fork是让你来分解程序流程得以并行处理的。
UNIX fork就此诞生!
我们再次回顾一下UNIX fork诞生之前的景象:
再来看看fork诞生之后的景象:
于是UNIX正式迈开了现代化建设的步伐,一直走到了今天。
UNIX fork-exec
关于exec,故事没什么好讲的,它事实上就是关于上述覆盖逻辑的封装,此后程序员不必自己写覆盖逻辑了,直接调用exec系统调用即可。
于是经典的UNIX fork-exec序列便形成了。
UNIX fork/exec/exit/wait
值得一提的是,fork被引入UNIX后,exit的语义发生了巨大的改变。
在原始的1969年汤普森版UNIX中,由于每一个终端有且仅有一个进程,这意味着覆盖永远是在shell程序和某个命令程序之间进行的:
shell执行命令A:命令程序A覆盖内存中的shell代码。
命令A执行结束:shell覆盖结束的命令A的内存代码。
然而,在fork被引入后,虽然shell执行某个命令依然是特定的命令程序覆盖fork出来的shell子进程,但是当命令执行完毕后,exit逻辑却不能再让shell覆盖当前命令程序了,因为shell从来就没有结束过,它作为父进程只是被交换到了磁盘而已(后来内存到了,可以容纳多个进程时,连交换都不需要了)。
那么exit将让谁来覆盖当前进程呢?
答案是不用覆盖,按照exit的字面意思,它只要结束自己就可以了。
本着 自己的资源自己管理的责任原则 exit只需要清理掉自己分配的资源即可。比如清理掉自己的内存空间以及一些其它的数据结构。
对于子进程本身而言,由于它是父进程生成的,所以它便由父进程来管理释放。于是经典的UNIX进程管理四件套正式形成:
(完)
浙江温州皮鞋湿,下雨进水不会胖!
查看我们精华技术文章请移步: Linux阅码场原创精华文章汇总
更多精彩,尽在"Linux阅码场",扫描下方二维码关注
感谢您的耐心阅读,请随手转发一下或者点个“在看”吧~
-
UNIX和类Unix操作系统
2020-09-08 09:55:23UNIX和类Unix操作系统 Unix是20世纪70年代初出现的一个操作系统,除了作为网络操作系统之外,还可以作为单机操作系统使用。 Linux的起源可以追溯到古老的UNIX系统。正因为受到了UNIX的影响,才诞生了Linux。 Linux...UNIX和类Unix操作系统
Unix是20世纪70年代初出现的一个操作系统,除了作为网络操作系统之外,还可以作为单机操作系统使用。 Linux的起源可以追溯到古老的UNIX系统。正因为受到了UNIX的影响,才诞生了Linux。 Linux继承了UNIX的许多优良传统,例如强大的网络功能、完善的命令以及良好的健壮性与稳定性。无论是从外观上,还是从功能上,UNIX与Linux都是非常相似的。 #UNIX System V家族 A/UX、AIX、HP-UX、IRIX、LynxOS、SCO OpenServer、Tru64、Xenix、Solaris、OS/2 #BSD UNIX-386BSD家族 BSD/OS、FreeBSD、NetBSD、NEXTSTEP、Mac OS X、iOS、OpenBSD、SUN OS、OpenSolaris #UNIX-Like GNU、Linux、Android、Debian、Ubuntu、Red Hat、Linux Mint、Minix、QNX、GNU/Linux、GNU/Hurd、Debian GNU/Hurd、GNU/kFreeBSD、StartOS #其他 DOS、MS-DOS、Windows、React OS
-
Unix、Posix和标准UniX规范
2017-06-03 18:14:40Unix、Posix和标准UniX规范文章作者:Tyan
博客:noahsnail.com | CSDN | 简书20世纪60年代是大型、复杂操作系统盛行的年代,比如IBM的OS/360和Honeywell的Multics系统。OS/360是历史上最成功的软件项目之一,而 Multics虽然持续存在了多年,却从来没有被广泛应用过。贝尔实验室曾经是Multics项目的最初参与者,但是因为考虑到该项目的复杂性和缺乏进展而于1969年退出。鉴于Mutics项目不愉快的经历,一群贝尔实验室的研究人员Ken Thompson、 Dennis Ritchie、 Doug Mcllroy和 Joe Ossanna,从1969年开始在DEC PDP-7计算机上完全用机器语言编写了一个简单得多的操作系统。这个新系统中的很多思想,比如层次文件系统、作为用户级进程的 shell概念,都是来自于 Multics,只不过在一个更小、更简单的程序包里实现。1970年,Brian Kernighan给新系统命名为“Unix”,这也是一个双关语,暗指“Multics”的复杂性。1973年用C重新编写其内核,1974年,Unix开始正式对外发布。
贝尔实验室以慷慨的条件向学校提供源代码,所以Unix在大专院校里获得了很多支持并得以持续发展。最有影响的工作发生在20世纪70年代晚期到80年代早期,在美国加州大学伯克利分校,研究人员在一系列发布版本中增加了虚拟内存和Internet协议,称为Unix4.xBSD(Berkeley Software Distribution)。与此同时,贝尔实验室也在发布自己的版本,称为System V Unix。其他厂商的版本,比如Sun Microsystems的Solaris系统,则是从这些原始的BSD和System V版本中衍生而来。
20世纪80年代中期,Unix厂商试图通过加入新的、往往不兼容的特性来使它们的程序与众不同,麻烦也就随之而来了。为了阻止这种趋势,IEEE(电气和电子工程师协会)开始努力标准化Unix的开发,后来由 Richard Stallman命名为“Posix”。结果就得到了一系列的标准,称作Posix标准。这套标准涵盖了很多方面,比如Unix系统调用的C语言接口、shell程序和工具、线程及网络编程。最近,一个被称为“标准Unix规范”的独立标准化工作已经与Posix一起创建了统一的Unix系统标准。这些标准化工作的结果是Unix版本之间的差异已经基本消失。
参考资料:
- 深度理解计算机系统(P11)
-
Unix时间戳
2018-09-29 13:02:04Unix时间戳(英文为Unix epoch, Unix time, POSIX time 或 Unix timestamp) 在线查询Unix时间戳 http://tool.chinaz.com/Tools/unixtime.aspx 百度百科 https://baike.baidu.com/item/unix时间戳/2...Unix时间戳是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数
Unix时间戳(英文为Unix epoch, Unix time, POSIX time 或 Unix timestamp)在线查询Unix时间戳
http://tool.chinaz.com/Tools/unixtime.aspx百度百科
https://baike.baidu.com/item/unix时间戳/2078227?fr=aladdin -
unix时间戳
2018-12-25 11:35:43unix时间戳是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。 UNIX时间戳的0按照ISO 8601规范为 :1970-01-01T00:00:00Z. 一个小时表示为UNIX时间戳格式为:3600秒;一天表示为UNIX时间戳为... -
Unix时间戳(Unix timestamp)
2017-07-13 16:54:31Unix时间戳(Unix timestamp),或称Unix时间(Unix time)、POSIX时间(POSIX time),是一种时间表示方式,定 义为从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数。 详细介绍和转换工具:... -
unix_timestamp、from_unixtime时间戳函数的使用
2018-07-18 11:36:45最近在做一个关于Spark sql清洗数据的项目,其中需要用到正则表达式及一些函数,在这里简单总结一下unix_timestamp、from_unixtime的用法,仅供参考。 一、unix_timestamp函数用法 1、UNIX_TIMESTAMP() :若无... -
unixbench
2019-05-13 10:07:24安装过程 ...wget http://soft.laozuo.org/scripts/UnixBench5.1.3.tgz 或通过网盘下载 链接:https://pan.baidu.com/s/1KnHn_xBoUjXInvsOBEYE_A 提取码:2jmw 复制这段内容后打开百度网盘手机Ap... -
关于Unix时间戳(Unix timestamp)
2016-11-10 11:02:36关于Unix时间戳(Unix timestamp) 时间戳是自 1970 年 1 月 1 日(00:00:00 GMT)以来的秒数。它也被称为 Unix 时间戳(Unix Timestamp)。 Unix时间戳(Unix timestamp),或称Unix时间(Unix time)、POSIX... -
UNIX简介
2017-03-15 15:26:54UNIX操作系统 UNIX操作系统由三部分组成:内核,shell和程序。 内核 UNIX的内核是操作系统的中枢:它为程序分配时间和内存,并处理文件存储和通信以响应系统调用。 作为shell和内核一起工作的方式的说明,假设... -
Unix 发展史
2016-07-05 00:05:27简述Unix和Linux用父子关系你比喻应该还是比较合适的 - Unix是父亲,Linux则是儿子。他们之间有一个不可分割的关系,当我们学习完Linux之后,再去学习Unix的时候,就会发现它们之间无论是文件系统、基本命令或管理... -
Unix V6 环境搭建:Simh 安装 Unix V6、Unix V6 基本使用以及源代码获取
2019-08-07 11:21:37最近心血来潮看到了一本有意思的书:《Unix内核源码剖析》。这本书有意思之处在于,作者的研究对象是 Unix V6。虽然 Unix V6 已经是 1975 年的系统了,但是其源代码拢共只有 1w 行左右,并且使用了 C 语言(K & ... -
Unix和UnixNano
2020-03-24 21:05:22Unix将t表示为Unix时间,即从时间点January 1, 1970 UTC到时间点t所经过的时间(单位秒)。 在windows下,rand.Seed(time.Now().Unix())作为种子,得出的随机数是随机的 func (t Time) Unix() int64 UnixNano将t... -
Unix的起源
2016-11-25 11:35:45不得不说的 Unix【内容摘要】 Unix诞生于1969年,此后快速被广泛应用; Unix一开始是开源的,后来AT&T收回版权,并且不公开源代码; Unix的代码是由90%的C语言和10%的汇编组成; Unix后来的两大分支:AT&T的System V... -
UNIX时间戳函数
2019-04-22 19:03:33UNIX_TIMESTAMP(date)若无参数调用,则返回一个Unix时间戳(‘1970-01-01 00:00:00’)作为无符号整数。 例1:使用UNIX_TIMESTAMP函数返回UNIX格式的时间戳,输入语句如下: mysql> select unix_timestamp(),unix... -
unix套接字通讯,unixsock
2017-04-26 18:45:00unix套接字通讯,unixsockunix套接字通讯unixsockunix域套接字unix本地域套接字类似于进程间通信的有名管道 需要包含头文件include sysunh unix域套接字有两种形式tcp和udp只能用于两个进程间本地通信 tcp类型的unix... -
60行C代码的shell领略Unix哲学之美
2019-09-10 16:29:491969年,Unix初始,没有fork,没有exec,没有pipe,没有 “一切皆文件” ,但是那时它已经是Unix了。它简单,可塑。 Melvin Conway在1963年的论文中叙述fork思想时就解释说并行路径要用结果来交互,也就是在汇合的... -
dos2unix与unix2dos之学习记录
2019-01-08 03:32:451. unix2dos与dos2unix这两个tool是用来干什么的? 这首先应该要说明一下背景知识: unix类操作系统下,换行字符是\n; 而早期的dos操作系统,其换行字符是由\r\n组成。 所以如果将unix系统下的文本文件copy到... -
Unix时间戳(Unix timestamp)是什么
2018-07-06 10:08:43时间戳是自 1970 年 1 月 1 日(00:00:00 GMT)以来的秒数。它也被称为 Unix 时间戳(Unix Timestamp)。侧重点 他是的单位是秒 -
UNIX SOCKET简介
2018-11-17 15:23:27UNIX Domain SOCKET 是在Socket架构上发展起来的用于同一台主机的进程间通讯(IPC)。它不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序列号应答等。只是将应用层数据从一个进程拷贝到另一个进程。UNIX ... -
UNIX时间戳
2016-03-26 16:44:10时间戳是文件属性中的创建、修改、和访问时间。数字时间戳服务是Web网站安全服务项目之一,能提供电子文件的日期和时间信息的...在UNIX系统中,日期与时间表示为自1970年1月1日零点起到当前时刻的秒数,这种时间被称 -
Unix的特点
2019-06-02 16:12:14UNIX操作系统,是一个强大的多用户、多任务操作系统,支持多种处理器架构,按照操作系统的分类,属于分时操作系统,于1969年在AT&T的贝尔实验室开发。 Unix特点: Unix很简洁,仅仅提供 几百个系统调用并且... -
UNIX系统特点
2018-08-07 10:27:18UNIX系统是一个多用户、多任务操作系统,支持多种处理器架构(并行处理能力)。 UNIX的系统结构可分为三部分:Unix内核(Kernel):系统核心,指挥调度机器运行,直接控制计算机资源,内核提供一种硬件抽象的... -
Linux之dos2unix和unix2dos
2017-11-23 18:59:381、dos2unix【dos2unix】命令用来将dos格式的文本文件转换成unix格式的文件。 DOS下的文本文件是以\r\n作为断行标志的,表示成十六进制就是0D 0A。 Unix下的文本文件是以\n作为断行标志的,表示成十六进制就是0A。 ... -
Unix起源
2014-01-21 15:25:48Unix和Linux 一、 Uninx的起源 1969年,由KenThompson在AT&T贝尔实验室实现的。使用的是用汇编语言。 1970年,KenThompson和DennisRitchie使用 C语言对整个系统进行了再加工和编写,使得Unix能够很容易的移植到... -
UNIX_TIMESTAMP 与 FROM_UNIXTIME
2016-07-10 22:59:52#当前时间转为秒数 1970...SELECT UNIX_TIMESTAMP()#1441686603 SELECT UNIX_TIMESTAMP('2015-09-08 12:30:03') -- 1441686603 SELECT UNIX_TIMESTAMP('2015-09-8 12:30:3')##2015-09-08 12:30:03 SELECT FROM_UNIXTIME
-
Redis数据库入门与使用
-
2021-01-23
-
【数据分析-随到随学】数据分析基础及方法论
-
《设计模式》中文版.rar
-
[转载] Python学习之Numpy
-
ensp最新版本安装包+防火墙配置包USG6000V.zip
-
性能测试面面观
-
SVGA直播礼物 直播平台礼物 SVGA礼物购买 新直播平台测试好用GIF
-
Dell-R230- H330-730-730P-RAID驱动 for Win 2008R2_2012_2012R2 -1.zip
-
JavaWeb
-
CSCD来源期刊列表2019-2020).xlsx
-
USG6000V-enspv1.3 +virtualBox + USG6000V设备包
-
手势解锁-canvas-javascript实战
-
Vue+ElementUi疫情监测平台(一)添加数据
-
转行做IT-第8章 类与对象、封装、构造方法
-
Java Web开发之Java语言基础
-
Spring Boot2.X仿朋友圈PC版系统实战_架构1.0
-
芯准TTE系统测试与验证(6)—— TT+BE+RC流混合传输
-
2021-01-23
-
算法导论(基础知识)——编程大牛的必经之路