设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客

Unix考古记:一个“遗失”的shell

2013-4-27 12:57| 发布者: joejoe0332| 查看: 2610| 评论: 0|原作者: Leo|来自: 酷壳 – CoolShell.cn

摘要:   谨以此文纪念伟大的计算机科学巨匠Ken Thompson和Dennis Ritchie,并同时向其他所有为Unix发展做出贡献的黑客致敬。   历史的尘埃   Unix作为一个举世闻名的操作系统已有40余年的历史,围绕着这个古老的操作 ...

  执行命令(Executor)

  当前面一系列步骤之后,如果错误计数为0,则解释器从语法树的根节点开始,深度优先遍历所有节点,并根据前面语法和语义分析得到的类型和属性,一一执行所包含的命令,以生成最后的系统调用。

  对于命令序列(TLST)节点,从左至右顺序执行子树节点命令。

  对于过滤器(TFIL)节点,创建管道文件句柄,作为左右子树的重定向文件。

  对于简单命令(TCOM)和复合命令(TPAR)节点,首先筛选出系统内置命令(built-in),对于剩下的外部命令则fork一个子进程执行它。如果是复合命令中最后一个子命令,那么仍在原来的进程上执行而不必创建新进程。可执行文件路径按先后顺序搜索:①本地路径;②/bin;③/usr/bin。

  多进程环境下,特别要注意文件句柄管理。命令间共享标准输入输出设备之外,还会重定向到管道线,而父进程在fork之后子进程会获取一份文件句柄拷贝,所以父进程必须在fork之后立即关闭闲置的管道线句柄(如果有的话)以免造成资源泄漏,子进程也将在重定向之后关闭管道线句柄。

  对于后台命令需要打印pid,但不需要响应中断信号,父进程也不必等待子进程终止。其余进程命令执行中可捕获中断信号,并转入相应的处理函数。

  解释器用内置的errno全局变量保存进程终止状态,并生成终止报告(termination report),系统调用wait()用于返回终止进程的pid并输出报告消息索引。

  孰优孰劣

  尽管Thompson Shell是一款优秀的命令解释器,还产生了多项历史创举,但遗憾的是依然得不到命运女神的垂青,这要归咎于其自身的缺陷——功能单一、命令分散、控制流过于简单,尚无法用来编写脚本(script)。随着Unix日益壮大,它已经无法应付趋于繁杂的编程项目了。那时还出现了一个叫John Mashey的人写的PWB Shell(又 叫做Mashey Shell),基于Thompson Shell做了些改进,扩展了命令集,增加了shell变量,还增加了if-then-else-endif,for,while等控制逻辑。不幸的是它 比Thompson Shell更短命,因为1977年它遇上了一个强劲的对手。

  没错,那就是Bourne Shell,它的主要优点是真正实现了结构化脚本编程,比之前的shell实现得都要好,更要命的是它与前两个shell都不兼容,于是一场标准化的论战开始了。在David G. Kornksh作者)写的“ksh – An Extensible High Level Language”一 文中提及,Steve Bourne和John Mashey在三次连续的Unix用户组集会上争论他们各自的理由。在这些集会之间,各自增进他们的shell来拥有对方的功能。还设立了一个委员会来选 择标准shell,最终还是选择了Bourne shell作为标准。

  于是从Unix V7开始就有了前面所说的”Bourne Shell Family”。然而历史上没有完美的技术,随着八、九十年代操作系统迅猛发展,针对Bourne Shell的诟病也越来越多了。在解释器本身实现上,我看到网上一个对其评价是“universally considered to be one of the most horrible C code ever written”,至于原因去看一下mac.h就知道了,包括基本运算符、关键字在内的大量宏定义使得整个代码看上去简直不是C写的,也许Bourne是想把解释器打造成自己独特的风格吧,也难怪后来的bash以“born again”命名就是对其祖先的戏谑性调侃。另外内存管理上的一些毛病带来平台可移植性问题,至于其中的技术细节有点高级,超出本文范畴。

  Thompson Again Shell?

  虽然历史没有给Thompson Shell一个机会,但它并非就此同Unix V6那样一同沦为开源博物馆上的古老“化石”。作为出自顶级黑客之手的作品,作为伴随Unix那样伟大操作系统一同曾经流行计算机的产物,至今仍受国内外 程序员的缅怀,或将其改写,或为其作注。比如国外一个站点v6shell.org上就实现了一个免费开源的可移植性shell,它兼容并扩充原来的Thompson Shell并且可用来做脚本编程。再比如中国程序员寒蝉退士在其个人博客上发布了一个注解版,并对原版做了一些改写,主要是将K&R C转为ANSI C,并且符合POSIX规范,使原本晦涩难懂的源码变得清晰易读起来。正是因为接触到他的版本激起了我对老Unix的考古兴趣,才有了这篇“考古笔记”。我在想不知今后会不会像bash那样,出一个tash来呢?

  一些感想

  本来全文应该就此结束了,但此时此刻不禁想多说几句。这篇笔记当初并非有意而为之,在hacking源码的过程中感想积累多了也就逐渐成章了。看代 码、作注解、查资料、写此文,前后历经四个多礼拜,是在繁杂的工作中“挤乳沟”挤出来的零散时间片拼凑起来的,虽然文字不长但也算耗费了一番心血,酸甜苦 辣心中自明,体会到踏上社会之后潜下心做研究之艰难。如今面对这样一份不到900行写成的,没有一行多余的代码,简洁(clarity)、干净(clean)、快速(fast),这就是Pure C的魅力,我深为这种厚重的编程功力所折服,正所谓“大道至简”吧。虽然要完全弄懂它需要很多时间,但我相信这种代价却是值得的。

  最后再八卦一下,2011年Dennis Ritchie去世了,有人生前问过他“学C需要多久才能成为熟练开发者并写出重要产品代码?”,Ritchie回答“我不知道,我从没去学过C。”(I don’t know. I never had to learn C.)其实这里已经给出了答案——那就是没有比去阅读Unix源代码更好的选择了,某种意义上C语言就是为Unix而生的。

Dennis Mac Ritchie

参考资料

The Unix Heritage Society:Unix社区遗产,上面有v6和v7以及其它一些衍生版本的操作系统源代码。

The Traditional Bourne Shell Family:Bourne Shell家族简史。

v6shell:osh,一个基于Thompson Shell的开源可移植性old shell。

寒蝉退士的博客:Thompson Shell的一个注解版。

Evolution of shells in Linux:简述Linux Shell演变史。

附录一个中文注释的 shell源码


酷毙
1

雷人

鲜花

鸡蛋

漂亮

刚表态过的朋友 (1 人)

  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部