编写自己的Shell解释器-6[转]

简单命令处理过程

我们已经看到,对列表命令和管道命令的处理,实际只是一个分解过程,最终命令的执行还是要由简单命令来完成。

在简单命令的处理过程中,必须考虑以下情况:

1、区分内部命令和外部命令

根据简单命令的定义,它的第一个参数是要执行的命令,后面的参数作为该命令的参数。要执行的命令有两种情况:

一种是外部命令,也就是对应着磁盘上的某个程序,例如 wcls等等。对这种外部命令,我们首先要到指定的路径下找到它,然后再执行它。

二是内部命令,内部命令并不对应磁盘上的程序,例如cdecho等等,它需要shell自己来决定该如何执行。例如对 cd 命令,shell就应该根据它后面的参数改变当前路径。

对于外部命令,需要创建一个子进程来执行它,而对于内部命令,则没有这个必要。

外部命令的执行,是通过 exec 函数来完成的。有六种不同形式的 exec 函数,它们可以统称为 exec 函数。我们使用的是 execv()。关于 exec的细节,请看《unix环境高级编程》第8章:进程控制。

对于内部命令,我们目前支持五种,分别是:

exit:退出shell解释器

cd:改变目录

echo:回显

export:导入或显示环境变量

history:显示命令历史信息

这几个内部命令分别由 do_exit()do_cd()do_echo()do_export()do_history()来实现。

2、处理重定向

在简单命令的定义中,包括了对重定向的支持。重定向有多种情况,最简单的是输入重定向和输出重定向,分别对应着“<”和“>”。

输入重定向,就是把“<”后面指定的文件作为标准输入,例如:

wc < xxx

       表示把 xxx 这个文件的内容作为 wc 命令的输入。

输出重定向,就是把“>”后面指定的文件作为标准输出,例如:

echo “hello world” > xxx

表示把 echo “hello world” 的结果输入到 xxx 文件中,而不是屏幕上。

为了支持重定向,我们首先对简单命令的参数进行扫描,如果遇到“<”或者“>”那么就认为遇到了重定向,并把“<”或者“>”符号后面的参数作为重定向的文件名称。

对于输入重定向,首先是以只读方式打开“<”后面的文件,并获得文件描述符,然后将该文件描述符复制给标准输入。

对于输出重定向,首先是以写方式打开“>”后面的文件,并获得文件描述符,然后将该文件描述符复制给标准输出。

具体实现在 predo_for_redirect() 函数中:

3、管道的实现

管道的实现实际上也是一种重定向的处理。对于“前”管道,类似于输入重定向,不同的是,它是把一个指定的描述符(“前”管道的输出端)复制给标准输入。对于“后”管道,类似于输出重定向,不同的是,它把一个指定的描述符(“后”管道的输入端)复制给标准输出。

在对管道的处理上,还必须要注意管道和输入或输出重定向同时出现的情况,如果是一个“前”管道和一个输入重定向同时出现,那么优先处理输入重定向,不再从“前”管道中读取数据了。同样,如果一个“后”管道和一个输出重定向同时出现,那么优先处理输出重定向,不再把数据输出到“后”管道中。

       至此,我们已经描述了实现一个简单的 shell 解释器的全部过程,相应的代码和 makefile 在我们的网站上可以下载。希望大家能够结合代码和这篇文章,亲自动手做一次,以加深对shell 解释器的理解。

posted @ 2008-12-05 22:34  aoogur  阅读(533)  评论(1编辑  收藏  举报