logo资料库

Linux下Shell命令解释步骤程序实现.doc

第1页 / 共8页
第2页 / 共8页
第3页 / 共8页
第4页 / 共8页
第5页 / 共8页
第6页 / 共8页
第7页 / 共8页
第8页 / 共8页
资料共8页,全文预览结束
实验四 Shell 解释程序的分析与设计 白凤伟 10120451 实验目的 Shell 是操作系统最外面的一层,处理用户与操作系统之间的交互动作,并且给出相应的操作系统 的输出结果。Shell 基本上是一个命令解释器,类似于 DOS 下的 command.com。它接收用户命令,然后 调用相应的功能处理程序。通过本次实验,我们可以简单了解操作系统和用户间的交互。 实验内容 编写 C 代码完成 Shell 解释命令的步骤: (1)打印提示符 (2)得到命令行 (3)解析命令 (4)查找文件 (5)准备参数 (6)执行命令 实验过程 Shell 解释命令的流程如下:
(1)打印提示符 在本实验中,将当前工作目录的绝对路径名和符号“->$”一并作为命令提示符。 (2)得到命令行 为了得到命令行,shell 执行一个阻塞读操作,让执行 shell 的进程进入睡眠状态,直到用户键入一 个命令行作为对提示符的响应。 (3)解析命令 解析程序从命令行的左边开始扫描命令行,直到遇到第一个空白字符。第一个单词是命令的名称, 而后面的则是命令参数。 (4)查找文件 Shell 为每个用户提供了一组环境变量,这些变量定义在用户的.login 文件中。其中 PATH 环境变量 是一个有序的绝对路径列表,它指明了 shell 应该在什么地方寻找命令文件。如果在任何指定的目录中 都没有找到与命令同名的文件,那么 shell 将提示用户无法找到命令。 (5)准备参数 在本实验中,将输入的命令行解析到数组 Real_Command 中,Real_Command[0]代表命令名字,其 它位置存放的是参数。 (6)执行命令 Shell 需要执行指定文件中的可执行程序,并保护原始进程不被破坏。Shell 通过采用系统调用 fork()、 execv()和 wait()使用多进程来达到这个目的。 本实验的程序实现见附录。 实验结果分析 将 C 程序文件编译取名为 sh,运行 sh 后如图 1 所示,即出现提示符:/home/vincent->$,前半部分 即为当前工作目录的绝对路径。 接下来我们输入命令 ls,命令执行结果如图 2 所示,能够正确显示此目录下的文件。 图 1
再输入 file sh easyshell.c,结果如图 3 所示,进一步说明命令的执行是正确的。 图 2 当我们随便输入一列字母时,它并不是命令语句,因此会提示错误,并没有此命令,结果如图 4 所示。 图 3 最后,我们输入命令 quit,便会结束此程序,因为程序中设置的是输入 quit 就退出,结果如图 5 所 图 4 示。 此程序的运行比较成功,从结果中还可以看到多进程的执行过程。通过编写 shell 解释命令的步骤 的程序,我们知道了操作系统是如何和用户进行交互的,进一步理解了 shell 作为解释程序的含义。 图 5 附录 文件名:easyshell.c
#include #include #include #include #include #include #include #include #include #define MAX_LENGTH 80 char *Input_Command(){//输入命令 char *Input_Array; if ((Input_Array = (char *)malloc(MAX_LENGTH * (sizeof (char)))) == 0 ) { printf("error! can't malloc enough space for buffer\n"); return NULL; } fgets(Input_Array,MAX_LENGTH,stdin); Input_Array[strlen(Input_Array)-1] = '\0'; return Input_Array; } char *Command_File_Exist(char *Command){//寻找输入命令所在文件的绝对路径 char *File_Path; //存储输入的命令所在文件的绝对路径 char *path;//存储环境变量中的 PATH 值 if ((path = getenv("PATH"))!=0){ printf("PATH 为: %s\n",path); int File_Path_Length = strlen(path) + strlen(Command) + 1; File_Path = (char *)malloc(File_Path_Length * (sizeof(char)));
int i = 0; int j = 0; for (i = 0;i < strlen(path);i++){ if(path[i]==':' || path[i]=='\0'){//找到 PATH 中的一个绝对路径名 File_Path[j++] = '/'; File_Path[j] = '\0'; strcat(File_Path,Command);//将命令名加到绝对路径名后,用于查找 if (access(File_Path,F_OK) == 0) {//找到文件 return File_Path; } else j = 0; } else{File_Path[j++] = path[i];} } return NULL; return NULL; } else } char **Analyse_Command(char *Input_Array){//分析输入命令 char **Real_Command;//存储分析结果 char *args; if ((Real_Command = (char **)malloc(MAX_LENGTH * (sizeof(char *)))) == 0 ){ printf("error! can't malloc enough space!\n"); return 0; } if ((args = (char *)malloc(MAX_LENGTH * (sizeof(char)))) == 0 ){ printf("error! can't malloc enough space!\n");
return 0; } int i,j = 0,k = 0; for (i = 0; i < strlen(Input_Array);i++){ if (Input_Array[i] != ' ')//输入命令以空格为间隔,第一个空格前为命令,其它为参数 args[j++] = Input_Array[i]; else { args[j] = '\0'; if (strlen(args) > 0){ if ((Real_Command[k] = (char *)malloc(strlen(args) * (sizeof (char)))) == 0){ printf("error! can't malloc enough space!\n"); return 0; } strcpy(Real_Command[k++],args); j = 0; } } } args[j] = '\0'; if (strlen(args) > 0){//存储最后一个参数 if ((Real_Command[k] = (char *)malloc(strlen(args) * (sizeof (char)))) == 0){ printf("error! can't malloc enough space!\n"); return 0; } strcpy(Real_Command[k++],args); } Real_Command[k] = NULL; return Real_Command; }
int main(){ char *Input_Array;//输入命令的数组 char *Current_Path;//当前工作目录的绝对路径 char **Real_Command;//存储分析输入命令的结果 if ((Input_Array = (char *)malloc(MAX_LENGTH * (sizeof (char)))) == 0 ) { printf("error! can't malloc enough space for buffer\n"); return (0); } while (1){ Current_Path = getcwd(NULL,0); printf ("%s->$",Current_Path);//打印提示符,形式为:当前路径->$ Input_Array = Input_Command(); if (strlen(Input_Array) != 0){ if (strcmp(Input_Array,"quit") == 0){//输入为 quit 时退出程序 printf("Good Bye!\n"); break; } else if(strcmp(Input_Array,"cd")==0){//输入为 cd 时转化路径 if (Real_Command[1] != NULL){ if (chdir(Real_Command[1]) < 0)//转换失败 fprintf(stderr,"cd ERROR!\n"); } else } else{ fprintf(stderr,"no input\n"); Real_Command=Analyse_Command(Input_Array); char *Full_PathName; Full_PathName = Command_File_Exist(Real_Command[0]);
if (Full_PathName != NULL){ int pid=0; pid=fork(); if(pid>0){//父进程 wait(0); printf("This is the parent's pid:%d\n",pid); } else{//子进程 printf("This is the child's pid:%d\n",pid); execv(Full_PathName,Real_Command); exit(0); } } else{fprintf(stderr,"error:the command isn't exsit!\n");} } } } return 1; }
分享到:
收藏