shell命令解释器实验报告

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验报告实验名称:实现一个shell命令解释器

学员:

学号:

年级:

专业:所属学院:计算机学院指导教员:职称:

实验室:实验日期:

目录

1.功能描述 (3)

2.主要数据结构 (3)

3.主要程序流程图 (4)

4.主要功能实现方法和系统调用 (4)

4.1初始化环境 (4)

4.2打印提示符,获取用户输入 (5)

4.3解析命令 (5)

4.4执行命令 (5)

4.4.1内部命令 (5)

4.4.2外部命令 (5)

4.4.3重定向功能 (6)

4.4.4管道功能 (6)

5.测试结果 (7)

6.心得体会 (10)

1.功能描述

本实验完成了一个shell命令解释器,实现了shell的解释命令功能,实现了内部命令(包括自定义命令)、外部命令、重定向功能和多管道等功能。具体功能描述如下:

1)内部命令:

●可以使用常用的如cd、echo、history、exit等命令

●自定义命令

1)smile命令:打印出笑脸

2)myinfo命令:打印出作者信息和版本信息

2)外部命令:可实现cp、rm等所有外部命令。

3)重定向:通过输入重定向符号’<’ 或输出重定向’>’ ,把一行命令分成

两部分,前者为需要执行的命令,后者为一个重定向文件。输入重定向

是把文件内容作为输入传到前面的命令中,而输出重定向则是把命令的

结果传入重定向文件中。

4)管道:通过管道符号’|’ 把一条命令分成两部分,前一部分命令运行后,

将结果放入管道,后一部分命令从管道中取出该结果,作为输入继续执

行。最多可以实现10个管道。

2.主要数据结构

本程序主要使用字符数组进行命令、路径的存储与分析。

3.主要程序流程图

命令的分析执行过程包括:初始化环境,打印提示符,获取用户输入命令,解析命令,寻找命令文件和执行命令,如图1。

图1程序设计流程图

4.主要功能实现方法和系统调用

下面将详细说明本shell解释器的实现原理和所用到的系统调用。

总结起来用到的系统调用主要有:

Open();close();dup();pipe();execv();chdir();getcwd();

如何使用这些系统调用实现shell的各项功能,下面将详细说明。

4.1 初始化环境

用init_environ()函数进行初始化,准备好执行外部命令可能用到的路径。

⏹void init_environ()

程序初始化,打开路径文件os_profile,调用getenviron()函数,将查找路径放入envpath[]中。

⏹void getenviron(char *str)

将路径文件中可能的路径按':'分开,存入envpath[]中。

4.2 打印提示符,获取用户输入

用一个死循环接受用户的输入,直到用户输exit命令。每次打印出当前的工作目录。getcwd(dir,sizeof(dir)),利用getcwd这个系统调用获取当前工作目录的绝对路径。

4.3 解析命令

用一个for循环遍历用户输入input,按照空格’’把各个分词分解开并依次存入arg[ ]数组。Input中碰到’|’,就去执行pipel( )函数,处理管道命令;碰到’<’,就去执行redirect_in(),处理输入重定向命令;碰到’>’,就去执行redirect_out(),处理输出重定向命令。处理完管道和重定向命令后,接着处理自己写的内部命令,最后剩下的就是外部命令。

4.4 执行命令

4.4.1 内部命令

1)cd命令

cd命令的实现利用chdir(arg[1])这个系统调用,将目录改到arg[1]的值。

2)echo命令

将arg[1]打印出来。

3)history命令

用全局变量cmd_num计数,打印出命令序号和相应的用户输入。

4)exit命令

当用户输入exit时,打印出“bye,bye ~~”,并break出程序的主for循环,

退出自己写的shell。

5)自定义命令

1)smile命令

打印出一个笑脸*^_^*,此命令有点娱乐成分。

2)myinfo命令

打印出作者信息author:zhaojingyue 201106021031和版本信息updating time:2013.12.10

4.4.2 外部命令

首先用is_founded( )函数把外部命令的执行文件路径存入buf,接着用fork 系统调用建立一个子进程用于执行该外部命令,然后用execv到buf说存储的路径下执行arg所对应的命令,最后用waitpid向父进程发信号。其中,is_founded( )函数具体实现如下:

int is_founded(char *cmd)

程序初始化时,已经将命令可能存在的路径置于envpath[i]数组中,函数

is_founded 做的工作就是把路径和命令存入buf 数组中,在相应的路径下查找、判断命令是否存在,如果找到返回1,没有则返回0。判断时用到系统调用函数access。

4.4.3 重定向功能

我把重定向分为输入重定向redirect_in()和输出重定向redirect_out()两个函数来处理。

⏹redirect_in()

输入重定向就是把改变命令的输入对象。

先用open这个系统调用以只读方式打开命令中指出的文件,然后用dup将标准输入的文件描述符保存在save_fd中,接着是关键的dup2,用刚刚打开的文件替换掉标准输入,这样就实现了重定向,最后用调用close关闭文件,不让它继续被用。

接下来的操作同外部命令的处理一样,用is_founded(arg[0])函数找到命令执行程序,fork子进程,execv执行此命令,waitpid等待子进程结束发信号给父进程。

执行玩命令之后不要忘了再dup2回来,用一开始保存在save_fd中的文件描述符替换掉现在的标准输入,这样,标准输入就是正常的了。

⏹redirect_out()

输出重定向就是把改变命令的输出对象。

先用open这个系统调用以可写方式打开命令中指出的文件,第二个参数是O_RDWR|O_CREAT|O_APPEND,即若文件不存在就创建一个,然后把要写入的内容拼接在原文件的后面。然后用dup将标准输出的文件描述符保存在save_fd 中,接着是关键的dup2,用刚刚打开的文件替换掉标准输出,这样就实现了重定向,最后用调用close关闭文件,不让它继续被用。

接下来的操作同外部命令的处理一样,用is_founded(arg[0])函数找到命令执行程序,fork子进程,execv执行此命令,waitpid等待子进程结束发信号给父进程。

执行玩命令之后不要忘了再dup2回来,用一开始保存在save_fd中的文件描述符替换掉现在的标准输出,这样,标准输出就是正常的了。

4.4.4 管道功能

管道功能用自定义函数pipel()实现。

⏹pipel()

该函数实现了连续执行多条管道的功能,最多可连续执行10条管道。函数主要执行流程如下:

1)初始化10个管道的读、写端,都置为-1。

2)进行命令解析,把各条命令分解存到argp[][]二维数组中,遇到管道符

号”|”则置为NULL。

3)用系统调用pipe(fd[I])创建li_cmd个管道。

4)接下来进入for循环,一条一条执行命令。每条命令的执行过程如下:

相关文档
最新文档