实际上,与许多基本的UNIX功能不同,它fork是相对较晚的(a)。
UNIX中最早存在多个进程的是几个(固定数量的)进程,每个连接到PDP-7机器的终端都有一个(b)。
基本思想是给定终端的shell进程将接受用户的命令,找到程序文件,将一个小的引导程序加载到高内存中并跳转到该内存,并传递足够的详细信息以供引导代码加载程序文件。
引导程序代码在将程序加载到低内存(覆盖Shell)之后,将跳转到该程序。
当程序完成时,它会调用,exit但是不像exit我们今天所知道和喜欢的那样。这 exit将简单地重新加载外壳程序,并使用与最初加载程序几乎相同的方法来运行外壳程序。
因此,它实际上更像是一个基本exec命令,该命令在相同的处理空间中将您当前的程序替换为另一个程序。
Shell将为exec您的程序提供服务,然后在完成程序后exec通过调用将再次提供给Shell exit。
该方法类似于当时在许多其他交互式系统中发现的方法,包括UNIX起源于此的Multics。
从双向来看exec,添加fork作为流程复制器来协同工作实际上并不是一个很大的飞跃。尽管许多系统直接运行另一个程序,但正是这种“只需添加所需内容”的方法负责在UNIX fork和execUNIX 之间进行职责分离。这也导致了一个非常简单的fork功能。
如果您对Unix 的各种功能(c)的早期历史感兴趣,则不能The Evolution of the Unix Time-Sharing System错过Dennis Ritchie 的文章,该文章在1979年的澳大利亚会议上发表,随后由AT&T出版。
(a)虽然我的意思是后来者,是指宇宙中四种基本力的分离是“晚期”,发生在大爆炸之后约0.00000000001秒。</ humour>。
(b)由于在注释中提出了关于外壳最初是如何启动的问题,因此在Unix Heritage Society中有大量资源保存了非常早期的Unix 源代码,尤其是源代码档案库,尤其是第一版。
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
Run Code Online (Sandbox Code Playgroud)
在这里,您可以看到为每个连接的终端创建过程的代码段。这些是硬编码值的日子,不会自动检测涉及的终端数量。处的零终止表itab用于创建多个进程,并希望代码中的注释说明了如何(唯一可能棘手的是标签-尽管有多个1标签,但您会沿给定的方向分支到最近的标签,因此1b表示1在向后方向上最接近的标签)。
显示的代码仅处理该表,调用dfork以为每个终端创建一个进程,并启动getty登录提示。该getty程序最终启动了Shell。从那时起,就像我在答案的主要部分中所描述的那样。
(c)没有路径(和使用临时链接来解决此限制),流程有限,为什么密码文件中有GECOS字段,以及所有其他琐事,通常只有uber-geek才感兴趣。
| 归档时间: |
|
| 查看次数: |
605 次 |
| 最近记录: |