实验课题1:Linux 命令解释程序设计与实现
实验报告
1 实验内容及要求
Linux 命令解释程序功能设计要求:
1) 选取和设计实现一组内部命令(五条以上) ;
2) 外部命令执行采用直接调用 exec 系统调用的方式来实现;
3) 至少一条内部命令采用直接调用相应系统调用的方式来实现;
4) 系统环境变量(至少包括当前目录)支持;
5) 在 Linux 操作系统上启用(或替换原命令解释程序 Shell )测试验证。
2 开发、运行及测试环境
1) 虚拟环境软件 : Oracle VM VirtualBox
2) 操作系统: Oracle Linux 6.5
3) 编辑器: vim
4) 编译器: gcc
3 实验步骤
采用 c 语言编写该 Linux 命令解释程序。首先包含 unistd.h 、
sys/syscall.h 等头文件以及完成各个功能的函数声明。主程序中利用循环结构完成不限次的命令提示符显示和命令输入,并判别输入的命令是否合法,是内部命令还是外部命令。将 Linux 命令解释程序的各个功能封装成函数,完成具体的命令执行处理。实现具体功能步骤如下。
3.1 采用间接调用实现的内部命令
3.1.1 显示指定目录下文件列表
设计该命令关键词为“ ls ”, 功能为用户输入该命令后,指定具体的目录路径,可显示在该目录下的文件列表,并将文件编号显示,格式为“ file 编号文件名”,每行显示一个文件的文件名。如该过程中出现错
误导致不能显示文件列表则输出具体错误提示。采用间接调用相应系统调用的方式将该功能完成后封装为 void list_() 函数。
3.1.2 显示当前路径
设计该命令关键词为“ pwd”, 功能为用户输入该命令后,在下一行显示当前路径并回车换行。采用间接调用相应系统调用的方式将该功能完成后封装为 void pwd_() 函数。
设计该命令关键词为“ rename”, 功能为用户输入该命令后,在下一行显示
3.1.3 文件重命名
“ pleace input the old file name: ”,用户需输入需要重命名的文件名,然
后显示“ pleace input the new file name: ”,用户需输入该文件的新的文件名,即可完成对文件的重命名。完成后显示提示重命名工作失败或成功。采用间接调用相应系统调用的方式将该功能完成后封装为 void rename_() 函数。
3.1.4 显示输入内容
设计该命令关键词为“ echo” , 功能为用户输入该命令后,输入空格,然后输入需要显示的内容,即可在下一行显示上述用户希望输出的内容并回车换行。采用间接调用相应系统调用的方式将该功能完成后封装为 void echo_() 函数。
3.1.5 使用帮助
设计该命令关键词为“ help ” , 功能为用户输入该命令后,然后显示本命令解释程序的合法命令及其具体的功能说明。采用间接调用相应系统调用的方式将该功能完成后封装为 void help_() 函数。
3.1.6 退出程序
设计该命令关键词为“ exit ”或“ quit ”, 功能为用户输入该命令后,显示“ thank you for using! bye~ ”,之后该命令解释程序( Shell )退出到 Linux
操作系统上的原命令解释程序 Shell 。采用间接调用相应系统调用的方式完成。因该功能代码较简单直接在主程序中实现并未封装为函数。
3.1.7 设置和初始化系统环境变量
此处略,详见下文 3.4 系统环境变量支持中的说明。
3.2 采用直接调用的内部命令
3.2.1 文件拷贝
设计该命令关键词为“ copy” , 功能为用户输入该命令后,然后显示
“ pleace input the file name to be copied: ”,用户输入需要复制的文件的文件名,然后显示“ pleace input the new file name: ”,用户输入新拷贝文
件的文件名,即可完成文件的拷贝。如该过程中出现错误导致文件拷贝不成功则输出具体错误提示。采用直接调用系统调用的方式将该功能完成后封装为 void
copy_() 函数。
3.3 外部命令
3.3.1 显示环境变量
linux命令及shell编写设计该命令关键词为“ env”, 功能为用户输入该命令后,然后显示出所有的系统环境变量,每行显示一个。采用直接调用 exec 系统调用的方式将该功能完成后封装为 int environ_() 函数。
3.3.2 显示当前一系列进程
设计该命令关键词为“ jobs ”, 功能为用户输入该命令后,然后显示出当前一系列进程和子进程。采用直接调用 exec 系统调用的方式将该功能完成后封装为int jobs_() 函数。
3.4 系统环境变量支持
设计该命令关键词为“ export ”, 功能为用户输入该命令后,输入需要设置的系统变量名称和变量值,格式为“ [系统变量名称 ]=[ 系统变量值] ”然后即可设置完成。采用间接调用相应系统调用的方式分别实现保存在本地用户变量中和保存在系统环境变量种,并分别封装为 void env_store() 和 void env_export() 函数。最后将上述功能函数完成后封装为 void export_() 函数。
以上代码编写完成后,通过 Linux 操作系统中的 gcc 编译器编译后运行,验证是否运行成功,功能是否完善,是否存在错误或问题。返回上述步骤修改代码,直到测试验证通过。
4 关键数据结构和算法流程在主程序中的关键数据结构是字符数组,用于接收用户输入的命令。关键的算法结构是循环结构,利用死循环结构用户可以不限次输入命令供程序执行处理,直到用户输入退出的命令则退出该循环结构,程序退出。
在循环结构中,输出系统命令提示符,提示用户输入。用户输入命令存入字符串数组后,将该命令与
预设的命令依次比较是否符合某一个,则进入相应命令的处理过程。若均不符合则输出输入错误的提示,继续回到循环开头输出系统命令提示符等待下一次输入命令。
4.1 采用间接调用实现的内部命令
4.1.1 显示指定目录下文件列表关键数据结构是另一字符数组,用于接收用户在命令后输入的指定目录;结构体“ struct dirent *entry ”, 用于存储该目录下文件,包括文件名;变量 DIR *olist 用于存储打开目录函数的返回值,判别是否打开成功并读取该目录下文件。
该命令是间接调用相应的系统调用实现的方式。关键算法是用户输入该命令和指定路径后,调用 opendir() 函数打开指定的目录。若返回值为空则打开失败,输出错误提示。利用循环结构调用 readdir() 函数读取该目录下文件,并依次输出文件序号和文件名。循环结束后,调用 closedir() 函数关闭该目录。若关闭失败则输出错误提示。
4.1.2 显示当前路径关键数据结构为字符型指针,用于指向当前路径。该命令是
间接调用相应的系统调用实现的方式。关键算法是用户输入该命
令后,调用 getcwd() 函数获取当前路径,由指针指向该空间,然后输出该路径。最后释放该指针空间。
关键数据结构为两个字符型数组,用于存储新文件名和旧文件名。该命令是间接调用相应的系统调用实现的方式。关键算法是用户输入该命令后,分别输入旧文件名和新文件名存入数组。调用 rename() 函数,将文件重命名。最后输出命名成
4.1.3 文件重命名
功或失败的提示。
4.1.4 显示输入内容
关键数据结构为字符型数组,用于存储用户除命令外输入的内容。该命令无需调用系统调用。关键算法是用户输入该命令后,将命令后的内容除空格外依次输出,最后输出换行即可。
4.1.5 使用帮助
在该函数中输出定义好的命令和相应使用帮助即可。
4.1.6 退出程序
输出用户提示,调用函数 exit() 退出程序即可。
4.1.7 设置和初始化系统环境变量
此处略,详见下文 4.4 系统环境变量支持中的说明。
4.2 采用直接调用的内部命令
4.2.1 文件拷贝
关键数据结构为三个字符型数组,用于存储需拷贝的文件的文件名和拷贝文件的文件名以及拷贝的部分文件内容。
该命令是直接调用相应的系统调用实现的方式。关键算法是用户输入该命令以及需拷贝的文件的文件名和拷贝文件的文件名后,使用 syscall() 函数和系统调用号 SYS_open,采用只读模式打开需要拷贝的文件,若打开失败输出相应提示。使用syscall() 函数和系统调用号 SYS_read,读取该文件的内容和字节数量,若读取失败输出相应提示。使用 syscall() 函数和系统调用号 SYS_creat,采用读写模式创建拷贝的新文件,若创建失败输出相应提示。使用 syscall() 函数和系统调用号SYS_write ,向新文件中写入读取的内容,若写入失败输出相应提示。使用
syscall() 函数和系统调用号 SYS_close,分别关闭两个文件,若关闭失败则分别输出相应提示。若以上步骤均成功则最后输出相应拷贝成功提示。
4.3 外部命令
4.3.1 显示环境变量
该命令是采用直接调用 exec 系统调用实现的方式。调用 fork() 函数生成子进程并返回 pid ,根据该值判断。如果出现错误, fork 返回一个负值,此时打印错误信息并返回;在子进程中, fork 返回 0,此时调用 execlp() 命令参数为“ env”, 即可显示所有的系统环境变量;在父进程中, fork 返回新创建子进程的进程 ID,需调用 wait() 函数等待。
该命令是采用直接调用 exec 系统调用实现的方式。调用 fork() 函数生成子进程并返回 pid ,根据该值判断。如果出现错误, fork 返回一个负值,此时打印错误信息并返回;在子进程中, fork 返回 0,此时调用 execlp() 命令参数为“ pstree -p ”, 即可以树状图显示一系列子进程;在父进程中, fork 返回新创4.3.2 显示当前一系列进程
4
建子进程的进程 ID,需调用 wait() 函数等待。
4.4 系统环境变量支持
关键数据结构为自定义的结构体,结构体内为两字符型数组,分别用于存储系统环境变量的名称和变量的值。
该命令是间接调用相应的系统调用实现的方式。关键算法是用户输入该命令后和系统环境变量的设置后,调用 setenv () 函数设置该环境变量并设置为可复写的,方便后续修改该变量的值。
同时,附加在本地变量中也保存了上述设置的系统环境变量。在存储变量的数组中保存上述系统环境变量即可。
5 编译运行测试结果
编译运行自行实现的命令解释程序 shell.o ,显示出命令输入提示符Qin>”,提示用户输入命令,如图 1 所示。
图1
5.1 采用间接调用实现的内部命令
5.1.1 显示指定目录下文件列表
用户输入命令 ls 后,指定具体的目录路径,可显示在该目录下的文件列表,并将文件编号显示,格式为“ file 编号: 文件名”,每行显示一个文件的文件名,如图 2 所示。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。