版权归原作者所有,如有侵权,请联系我们

[科普中国]-UNIX命令解释程序

科学百科
原创
科学百科为用户提供权威科普内容,打造知识科普阵地
收藏

简介定义

命令解释程序,用户通过它来进行操作系统内核和其它命令之间的交互。一般的命令解释程序都具有接受用户命令的输入、解释用户命令和执行用户命令的功能。一些功能较强的命令解释程序还有一定的程序设计语言的特征,某些命令解释程序还具有对以前输入过的命令进行重新编辑和执行的功能。

用户通过界面与操作系统进行交互作用,因此界面的设计在很大程序上决定了用户能否方便而有效地得到系统能够提供的各种服务。Unix分时操作系统与用户的界面是命令语言shell(外壳),其解释程序同样也被称为shell,包含有ksh,bash,csh等。1

基本结构shell解释程序基本上由四个部分组成(见图)。如巳无命令行可读入,或者执行login命令完全改换了进程图象,或执行logout命令终止了进程则结束执行shell解释程序。

调用方式用命令调用调用shell解释程序命令的一般格式是:

sh〔—e〕〔—t〕〔—c〕〔name〔arg1…〔arg9〕〕〕

括号中参数皆为可选。通常用这种命令调用shell解释程序解释执行一个shell过程,其格式是:

sh〔—e〕nameargmentlist

其中name是shell过程所在文件名,argmen-iltst是传向该过程的参数表,若用可选参数—e,则在执行每一条命令时,皆需打印此命令,并将代换的位置变量和shell变量用括号括出打印。1

在程序中调用在程序中可用系统调用execl执行shell命令,但这不能实施输入、出转向、管道命令、sshell过程调用等。但如果调用执行shell解释程序,情况大为改观,

例如:

execl(“/bin/sh",“sh”,“name",“argl",…“argn”,NULL);

它调用执行shell解释程序,而shell解释程序又解释执行一个shell过程,在过程名name之前可用可选参数—e。

如用可选参数“—c”,则调用方式可为:

execl(“/bin/sh”,“sh”,“—c,“Com-mandlist",NULL);

它调用shell解释程序直接解释执行命令表commandilst,命令表中可包含各种输入、出转向、管道操作等。

在程序中,如果调用执行方式是:

execl(“/bin/sh”,“sh",“—t”,NULL),

则从标准输入读一命令行,然后解释执行,于是就可用交互作用方式执行一shell命令行。

在程序中如果用

execl(“/bin/sh”,NULL);

则shell解释程序将从标准输入逐行读入命令并解释执行。在login程序中就是使用这种方式为每个用户运行一个shell解释程序。1

面向目标的命令解释程序在程序设计语言领域中,面向目标的范例设认为是构造复杂的大型软件系统的重要辅助工具。这一认识缘于这种技术能提供数据抽象、类属操作、软件可再用性及继承性支持。通过授权各个目标对自己的行为负责,用户往往可以略去不必要的实现细节,而专注于相当高的层次上的设计决策。

在将近二十年的时间里,Unix已证明是一种灵活稳妥的软件升发环境。然而Unix系统时常因过于简练和对新用户不随顺而遭受批评。因此,考虑能否卓有成散地利用面向目标技术研制一种既能保特原系统的能力又能提供更具用户亲和性的外部特性的Unix命令解释程序,是一个值得注意的问题。

普通Unix系统中的命令凋用可被看作是发出一种语言的具有过程性和函数性特征的语句。文件很象变量,而命令则是用以改变变量的操作。函数(即程序)被调用以创建或修改变量(即文件)的值。此外,通过集中传输设施还可把函数组合起来以构成新函数。我新的命令解释程序中尽可能地保留这种强制性质和函数性质,除此之外还要使之具备以面向目标方式说明动作的能力。

在这样做时,第一步便是引入一种新型目标,即可执行目标。可执行目标在行一项单一的具体任务;它在普通Unix环境下对应于一个二进制的可执行原本或外壳原本。为使程序执行该项任务,用户将选择可执行原本,并选择伴随它的一切变元,然后选用系统信息execute传送至被选择目标。同普通系统的情况一一样,execute信息将便外壳原本或二进制文件被调用。

目标专用命令提供的功能度最终要通过可执行目标来实现。如前所述,一个目标将要对应的目标专刚命令的范围取决于目标的种类(或类型)。

注意,这种做法不问子Smalltalk-80程序设计语言的做法,在该语言中,方法(响一命令时所执行的动怍序刘)不髓存于类描述之外。便方法仅作为可执行目标。我们可进行一种更灵活的命令调用,命令既可用面向目标的尾缀方式给出,也可用强制性前缀方式给出。2

命令树和进程族shell解释程序将命令行分解处理构成命令树,树中分层分布的各个节点功能单一,相对比较独立(特列是命令型节点)。

而从Unix核的设计来看,任一进程都可用系统调用fork()生成子进程,于是很容易生成树形结构的进程族。每个进程都可执行某个独立的程序。从结构上看,二者非常匹配。

命令树中各个节点按序执行,规则是从根节点开始,先左子树、后右子树,也就是说有一个比较简单的前、后顺序,Unix父、子进程的主要同步手段是等待,也就是父进程在生成子进程后,等待其终止,然后继续运行,虽然这种同步手段似乎过于简单,但却充分满足了命令树节点顺序执行的要求。

Unix子进程在生成时基本上复制父进程图象。从shell解释程序看,父进程图象的一部分的确是子进程需要的。例如父进程数据段中某些数据(如命令行,命令树等)、子进程要复制过来以便分析执行,又如父进程正文段的一部分正好是子进程要执行的,而父进程核心态第六页更涉及资源共享(如标准输入、出,pipe通讯机构以及其它打开文件等),子进程有必要复制图象的这些部分。当然父进程图象的另外一些部分则是子进程不需要的,例如shell解释程序中正文段的大部分。但如果注意到shell正文段是可共享的,根本不存在复制问题,则复制父进程图象会降底效率的缺点就被冲淡了。

进程执行命令型节点时要按命令名执行相应命令处理程序。命令种类繁多,因此shell解释程序不可能包含这些处理程序,Unix核的进程执行文件机构则为此提供了一种妥善的解决办法。于是shell解释程序中执行命令型节点就只要使用系统调用exev(“name”,arglist),其中name是命令文件名,arglist是参数表。

Unix将外部设备作为特殊文件处理,这就为hsell中的输入、出转向、管道算符的实施提供了基础。标准输入、出能很方便的改换成其它外设和一般数据文件,而命令执行过程却无需作任何变动,这样就将灵活性和一致性结合了起来。

Unix进程通讯机构pipe与一般操作系统不同,它是建立在文件系统基础上的,适宜于单向的大批量信息传送,shell中的管道算符则是建立在这种通讯机构基础上的。管道算符前、后命令之间的信息传送是单向的,一般而言,数量比较大。1