这是之前写的博客,那时因为内容涉及学校正在上的课程的作业,经同学提醒,删除了,现在恢复,供有需要的同学参考。
实验目的
综合利用进程控制的相关知识,结合对shell功能的和进程间通信手段的认知,编写简易shell程序,加深操作系统的进程控制和shell接口的认识。
实验内容
- 可以使用Linux或其它Unix类操作系统;
- 全面实践进程控制、进程间通信的手段;
- 编写简易shell程序。
- 尝试自行设计一个C语言小程序,完成最基本的shell角色:给出命令行提示符、能够逐次接受命令;对于命令分成三种,内部命令(例如help命令、exit命令等)、外部命令(常见的ls、cp等,以及其他磁盘上的可执行程序HelloWrold等)以及无效命令(不是上述三种命令)。
- 参考“综合预备(3)”中的4.1.1小节内容将上述shell进行扩展,使得你编写的shell程序具有支持管道的功能,也就是说你的shell中输入“dir || more”能够执行dir命令并将其输出通过管道将其输入传送给more作为标准输入。
- 可以将步骤1和2直接合并完成。
- 设计标准的参考。1)提示符最低标准是固定字符串。提升标准是使用含当前路径的信息为提示符。2)接受命令的最低标准是一次接受一个命令就推出shell程序,提升标准是在shell内部循环读取和执行命令。
实验步骤与结果
shell的基本功能分析
Shell是用户和系统内核之间的一个接口程序,shell可以较好地保护系统内核免受非法操作的破坏,也能让用户能方便地完成自己的任务。它是一个命令解释command-language interpreter,我们提交的每条命令都会通过shell的解释,然后再提交给内核执行。
当我们如图1一样,启动一个终端时,会打印出“用户@主机:~$”的提示符,这是由bash打印的,bash是shell的一种,我们可以手动指定自己要使用的shell。
shell包含内部命令和外部命令,比如打印目录的pwd命令就是一个内部命令,而压缩文件时用的tar命令则是一个外部命令。对于用户来讲,内部命令和外部命令使用起来并没有差别,当然我们也并不关心这条命令究竟是外部命令还是内部命令。
对于Shell来说,当用户需要执行一条命令时,它会先看看这条命令是否为内部命令,如果不是,再去环境变量$PATH中去找一下这是不是一个可执行的程序,如果都不是,shell会返回错误,提示没找到这条命令:
图3展示了几个shell内部命令,echo用来指定的字符串;cd 用来切换目录;help用来输出帮助信息。
shell外部命令包括linux提供的一些使用的命令,比如ls,grep等,和我们自行安装的一些软件。
预计实现的功能
- 命令提示符:如图1一样,输出命令提示符(并设置对应的颜色);
- 常用外部命令:ls,cp,cat;
- 可执行程序运行支持:允许通过./helloworld 这样的方式来执行可执行程序
- 常用内部命令:help,echo,cd,exit
- 无效命令提示:如图2一样提示未找到命令
设计及实现过程
shell我们一直都在用,其实很容易直观地想到它的运行机制就是:
按照图4的运行流程,我们可以设计出我们自己的shell程序的大致框架:
while(TRUE){
print_prompt();
get_command();
if command valid
deal_command();
else
print_error();
}
图5中的shell框架来自《现代操作系统》一书,和我们刚开始自己想的框架没有太大差别,说明我们的大体思路是没有问题的。只是我们的框架太“抽象”了些,没有多少指导意义,而这里则比较清楚地展示了shell执行中需要fork命令子进程,以及调用exec族函数来执行命令等细节。
图6展示了我们正在使用的shell版本,本实验中模仿的shell将以bash为标准。
根据搜索的资料,为了达到较好的命令交互效果,我们需要使用一个开源的库,realine。
从官网下载源码,解压后进入readline所在目录,使用./configure进行必要的配置,然后make,再make install,我们就完成了readline库的配置工作。