Fork是unix中的一个很棒的工具。我们可以用它来生成我们的副本并改变它的行为。但我不知道fork的历史。
有人可以告诉我这个故事吗?
答案 0 :(得分:5)
实际上,与许多基本的UNIX功能不同,fork
是一个相对较晚的人(a)。
UNIX中最早存在的多个进程由几个(固定数量)进程组成,每个终端一个连接到PDP-7机器(b)。
基本思想是给定终端的shell进程接受来自用户的命令,找到程序文件,将一个小的引导程序加载到高内存中并跳转到它,传递足够的引导代码细节以加载程序文件。
将程序加载到低内存(覆盖shell)后,引导代码会跳转到它。
当程序结束时,它会调用exit
,但它不像今天我们所知道和爱的exit
。 这个 exit
只需重新加载shell并使用几乎与首先加载程序相同的方法运行它。
所以它更像是一个基本的exec
命令,在同一个进程空间中用另一个替换当前程序的命令。
shell会exec
你的程序,当你的程序完成后,它会再次通过调用exec
来exit
shell。
这种方法类似于当时许多其他交互系统中的方法,包括从UNIX得名的Multics。
从双向exec
开始,将fork
作为流程复制器添加到一起工作实际上并没有那么大的飞跃。虽然许多系统直接运行另一个程序,但它只是添加了所需的程序"在UNIX中负责fork
和exec
之间职责分离的方法。它还导致了一个非常简单的fork
函数。
如果您对Unix的各种功能(c)的早期历史感兴趣,那么不能通过Dennis的文章The Evolution of the Unix Time-Sharing System
Ritchie在1979年澳大利亚会议上发表,随后由AT& T出版。
(a)虽然我的意思是后来者意识到宇宙中四种基本力量的分离已经过去了,但是在大爆炸之后发生了大约0.00000000001秒。 < /幽默>
(b)由于在评论中提出了一个关于shell最初是如何启动的问题,因此有一个非常早期的源代码的很好的资源适用于The Unix Heritage Society以上的Unix,特别是the source code archives,尤其是first edition。
第一版的init.s
文件显示了如何创建固定数量的shell进程(稍微重新格式化):
...
mov $itab, r1 / address of table to r1
1:
mov (r1)+, r0 / 'x, x=0, 1... to r0
beq 1f / branch if table end
movb r0, ttyx+8 / put symbol in ttyx
jsr pc, dfork / go to make new init for this ttyx
mov r0, (r1)+ / save child id in word offer '0, '1, etc
br 1b / set up next child
1:
...
itab:
'0; ..
'1; ..
'2; ..
'3; ..
'4; ..
'5; ..
'6; ..
'7; ..
0
在这里,您可以看到为每个连接的终端创建进程的代码段。这些是硬编码值的日子,没有涉及终端数量的自动检测。 itab
处的零终止表用于创建许多进程,并希望代码中的注释解释如何(唯一可能是棘手的位是标签 - 尽管有多个1
标签,在给定方向上分支到最近的一个,因此1b
表示向后方向上最接近的1
标签。)
显示的代码只是处理表,调用dfork
为每个终端创建一个进程并启动getty
,即登录提示。反过来,getty
程序最终启动了shell。从那时起,正如我在这个答案的主要部分所描述的那样。
(c)没有路径(并使用临时链接来解决这个限制),有限的流程,为什么密码文件中有GECOS字段,以及各种其他琐事当然,一般只对超级极客感兴趣。