当前位置:文档之家› 期末 操作系统实验课程设计

期末 操作系统实验课程设计

操作系统实验课程设计(二)(参照实验五)学院:计算机科学与工程专业:信息管理工作与信息系统学号:2008142118 姓名:丁建东一、实验题目:设计一个Shell解释器二、实验目的:本设计的主要目的在于学会如何在Unix系统下创建进程和管理进程。

三、实验内容:实现一个简单的shell(命令行解释器),类似于bash, csh等。

要求实现的shell支持以下内部命令:1.cd <目录>更改当前的工作目录到另一个<目录>。

如果<目录>未指定,输出当前工作目录。

如果<目录>不存在,要求有适当的错误信息提示。

改命令应能够改变PWD的环境变量。

2.echo <内容>显示echo后的内容且换行。

3.help简短概要地输出你的shell的使用方法和基本功能。

4.jobs输出shell当前的一系列子进程,要求提供子进程的命名和PID号。

5.quit, exit, bye退出shell。

所有的内部命令应当优于在$PATH中同名的程序。

任何非内部命令必须请求shell创建一个新进程,且该子进程执行指定的程序。

这个新进程必须继承shell的环境变量和指定的命令行参数。

要求实现的shell支持以下内部命令:Batch Processing 如果shell启动带有一个文件名作为参数,打开该文件并执行文件里所有命令。

待所有进程全部结束退出shell。

四、实验思路:1.所用到的系统函数(1)打开目录void cd()API调用:int chdir(dir);getcwd(dir,dir_max);实现:改变当前目录,并判断目录是否存在。

(2)回应void echo()实现:用户输入字符串,以回车结束输入。

char echo_string[echo_len][echo_max];//用户输入命令,以空格符隔开,存为字符串数组按顺序输出用户输入的字符串。

(3)输出当前子进程Void jobs()API调用:shmget(),shmat()实现:开辟一个共享内存区,一旦创建一个子进程,就把该进程的进程ID和名字记字共享区里,在子进程结束的时候消除该记录。

这样,调用jobs时只要读取共享区里的记录并输出就可以知道当前运行的子进程了。

(4)输出当前路径void pwd()API调用:getcwd();五、程序流程图。

六、程序代码#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#define MAXLENGTH 25#define SUBLENGTH 5#define LINELENGTH 40#define ECHO "myshell#"#define QUIT "exit"char * readline;typedef enum{EXEC,REDI,REDIS,PIPE,NOHUP,BACKGROUND }TokenType;typedef void (*fun)(char *);void analyse(void);void exec(char*);void redi(char*);void piped(char*);void bgtask(char*);sigset_t *set;int main(void){readline = (char *) malloc(MAXLENGTH*sizeof(char)); set = (sigset_t *)malloc(sizeof(sigset_t));sigemptyset(set);if( sigaddset(set,SIGINT) == -1){printf("sigset error1~!\n");exit(0);}if(sigprocmask(SIG_BLOCK,set,NULL) == -1){printf("sigset error2~!\n");exit(0);}while(1){//signal(SIGINT,SIG_IGN); //ctrl+c is ignoredfputs(ECHO,stdout);//printf echogets(readline);//gets readlineif(strncmp(readline,QUIT,4) == 0) //equal exit then exit {free(readline);return 0;}analyse();//analyse}}//analyse the readlinevoid analyse(void){TokenType type = EXEC; //command style int i = 0;char c ;//function mappingfun fun_array[] ={exec,redi,NULL,piped,NULL,bgtask};//the 'nohup ' is amazing//test if contains nohupif(!strncmp(readline,"nohup ",6)){printf("nohup~!\n");signal(SIGHUP,SIG_IGN);// SIGHUP is ignored int j = 6;c = *(readline+j);//deal with the readlinewhile(c != '\0'){*(readline+i) = c;i++;j++;c = *(readline+j);}*(readline+i) = '\0';i = 0;}*/c = *(readline+i);//control the TokenTypewhile(c != '\0')if(c == '>'){type = REDI;*(readline+i) = '+';}else if(c == '<'){type = REDIS;*(readline+i) = '+';}else if(c == '|'){type = PIPE;*(readline+i) = '+';}else if(c == '&'){type = BACKGROUND;*(readline+i) = '+';}i++;c = *(readline+i);}//with the function array ,do it(*fun_array[type])(readline);}//execute simple commandvoid exec(char * p){printf("%s\n",p);char ** tmp = (char **)malloc(SUBLENGTH*sizeof(char*)); int num = 0;pid_t pid;//split the stringtmp[num] = strtok(p," ");while(tmp[++num] = strtok(NULL," "));pid = fork();if(pid == 0){if(sigprocmask(SIG_UNBLOCK,set,NULL) == -1){printf("sigset error~!\n");exit(0);}//execute itint error = execvp(tmp[0],tmp);if(error < 0){printf("Command not found~!\n");//exit(0);}free(tmp);exit(0);}elsewait(NULL);}//command contains '>'void redi(char *p){char * str = strtok(p,"+");char * file_name = strtok(NULL," ");char **tmp = (char **)malloc(SUBLENGTH*sizeof(char*)); int num = 0;int file,file_old,file_new;pid_t pid;tmp[num] = strtok(str," ");while(tmp[++num] = strtok(NULL," "));// open the filefile = open(file_name,O_WRONLY | O_CREAT);if(file == -1){printf("open file error!\n");free(tmp);}// inorder to recoverfile_old = dup(STDOUT_FILENO);// redirect the streamfile_new = dup2(file,STDOUT_FILENO);if(file_new == -1){printf("dup error~!\n");close(file);return ;}pid = fork();if(pid == 0){int error = execvp(tmp[0],tmp);if(error < 0){printf("Command is not found~!\n");exit(0);}close(file);free(tmp);exit(0);}else{wait(NULL);//recover the streamif(dup2(file_old,file_new)== -1){printf("dup2 error\n");}}}//command contains '|'void piped(char *p){char *str1 = strtok(p,"+");char *str2 = strtok(NULL,"+");char line[LINELENGTH];// use pipe implements the '|'FILE *in = popen(str1,"r");FILE *out = popen(str2,"w");if(in == NULL||out == NULL){printf("popen error~!\n");return ;//read the string and write to outwhile(fgets(line,LINELENGTH,in) != NULL)if(fputs(line,out) == EOF)printf("fputs error~!\n");pclose(in);pclose(out);}// implements background taskvoid bgtask(char *p){char *str = strtok(p,"+");char **tmp = (char **)malloc(SUBLENGTH*sizeof(char *)); int num = 0;pid_t pid;//splittmp[num] = strtok(str," ");while(tmp[++num] = strtok(NULL," "));if((pid = fork())< 0 ){printf("fork error~!\n");return ;if(pid == 0){if(fork())exit(0); //parent diedelse{int error = execvp(tmp[0],tmp);if(error < 0){printf("commamd not found");exit(0);}exit(0);}}}。

相关主题