已阅读5页,还剩22页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
北航计算机学院 OS操作系统实验一-Shell解释程序实现文档 32060624 OS实验小组OS操作系统实验一:Shell解释程序(YSH0)实现文档32060624 OS实验小组2019年1月6日星期日32060624 王 克(组长)32060518 杜可斌32060532 徐 瑞32060621 张 劲目录:1概述22YSH0功能与设计22.1程序形式22.2内部命令和外部命令22.3重定向和管道命令22.4特殊命令键32.5程序结构图33命令行分析器设计43.1功能43.2实现54命令解释执行的实现64.1使用到的系统调用64.2程序结构65程序源代码相关说明75.1文件说明75.2主要函数说明75.3主要数据结构说明76简易测试86.1编译运行测试86.2内部命令测试96.3外部命令测试96.4重定向和管道命令测试106.5测试总结107总结及感想107.132060624 王克107.232060518 杜可斌117.332060621 张劲117.432060532 徐瑞118附录118.1参考资料118.2源代码111 概述由于时间和能力的限制,这个的实验是参考实验教程上源代码及相关说明,但程序源代码的差异性在60%以上,从整体结构设计到具体的实现细节都有不同程度的改进和提高,但也可能带来一些BUG。通过对操作系统课程的学习,我们对Linux有了进一步更深入的认识,从它的使用到内核编译都有所了解。第一个实验是实现在Linux下实现一个Shell解释程序,所以我们将其命名为Linux Shell 0(表示一个最简单的Shell程序)。它是用户与系统内核沟通的中介,为用户使用操作系统的服务提供一个命令界面。用户在提示符下输入一个命令,Shell先解释后通过内核函数调用执行。2 YSH0功能与设计2.1 程序形式用户运行本程序,lsh0提供一个命令提示符lsh0#,程序一直等待用户输入命令,直到exit命令结束。2.2 内部命令和外部命令解释器首先支持一定的内部命令,实现特定的动作,它包括: exit:结束所有子程序并退出。 jobs:打印当前正在后台运行的作业和挂起的作业信息。本SHELL采用十分便于用户理解的格式。 fg %:把进程标识符为int的作业放到前台运行。如果这个作业已经暂停,就让它继续开始运行。并开始等待此前台进程执行完毕。 bg %:在后台执行进程标识符为int的已经挂起的进程。外部命令的形式是一系列分隔的字符串。第一个字符串为可执行程序的程序名,其余的参数。它必将位于环境变量所设置的某个路径中,如果不存在则表示命令错误。2.3 重定向和管道命令SHELL的命令大部分都是从标准输入信息并将输出信息送到标准输出。分别缩写为stdin和stdout。默认情况下,stdin为键盘,stdout为屏幕。但可使用和将输入和输出重定向到文件中,将信息存入一文件以便保存,而不送到屏幕。使用将信息从文件中输入。并且两者可以组合使用。SHELL也提供管道,利用管道可以将一个命令的输出作为另一个命令的输入来使用。这种方法比使用临时文件来连接两个命令要方便和高效的多。2.4 特殊命令键 Ctrl + Z:产生SIGTSTP信号,这个信号是让SHELL挂起在前台运行的作业。如果没有任何前台作业,则无效。 Ctrl + C:产生SIGNT信号,这个信号是让SHELL杀死前台运行的作业的进程。如果没有任何前台作业,则无效。2.5 程序结构图3 命令行分析器设计3.1 功能为Shell程序提供命令行的分析,并对信息进行分析存储,为解释执行做好准备。当用户在提示符后面输入命令时,输入的整行内容为一个“命令行字符串”。lsh0分析器的先将保存起来,直到它的作业执行结束。在执行一个命令行字符串时,lsh0也同时为其分配一个非负整数标识符,用来标识此作业的数据结构。当其作业执行完毕时,就删掉这个作业的整个数据结构。3.2 实现4 命令解释执行的实现4.1 使用到的系统调用pid_t for(void);int execv(const *file, char *const argv);void exit(int status);int wait(int *stat_loc);pid_t waitpid(pid_t pid; int *stat_loc, int options);int dup2(int fildes, int fides2);int pipe(int fides2);(详见教程上,不再赘述了)4.2 程序结构5 程序源代码相关说明5.1 文件说明文件名说明1lsh0.c程序主要源代码文件2lsh0_profile环境变量配置文件3readme.txtShell程序说明4makefileMakeFile文件,使用make命令编译5Lsh0Linux下编译得到的执行文件5.2 主要函数说明main()/*主函数, 程序入口 */ voidinitEnv();/*初始化环境*/ intreadInput();/*读入用户输入,保存到指针input中,返回读取的字符数*/ intparseInput();/*解析命令函数*/ voidexecuteCmd(intcmdType);/*执行命令函数*/ voidaddToHistory(char*);/*命令添加到历史函数*/ voidhistoryCmd();/*历史命令函数*/ voidcdCmd();/*CD命令函数*/ voidjobsCmd();/*打印任务命令函数*/ voidbgCmd();/*任务后台化bg %命令函数*/ voidfgCmd();/*任务前台化函数*/ intfindProg(char*cmdBuf);/*查找外部命令函数*/ voidaddJob(intjobPid,char*name);/*添加任务函数*/ voiddelJob(intjobPid);/*删除任务函数*/ voidctrlz();/*响应键盘CTRL + Z操作函数*/ voidDEBUG(char*s1,char*s2);/*调试程序时信息输出函数*/ 5.3 主要数据结构说明在这个程序中,用到的数据结构主要有循环数组和链表。/*定义历史命令信息数组*/ 循环数组 在history命令中,用数组来存放我们输入过的历史命令。假设我们设定义一个能够记录10条历史记录的数组。数组的定义如下:typedefstructhistory intstart; intend; charcmdBufHISTORYMAXBUFSIZE; history; historyhistoryCmds; 由于把作业以链表的形式保存起来,所以在处理job命令时,实际上就是对链表的操作。/*定义作业结构链表*/ typedefstructjobs pid_tpid; charcmdNameBUFSIZE; charstate10; structjobs*link; jobs; /*定义指向作业链表的头指针,尾指针*/ jobs*headJob,*endJob; headJob指针指向链表表头,endJob指针指向链表尾。 /*重定向用到的文件信息*/ typedefstructfileRedir inttype; charnameNAMESIZE; fileRedir; fileRedir*filesHISTORYMAX; 6 简易测试6.1 编译运行测试程序编译运行无错误,测试通过。6.2 内部命令测试内部命令测试正常。6.3 外部命令测试外部命令测试正常。6.4 重定向和管道命令测试重定向命令测试正常,但管道命令存在一定问题,可能造成进程死掉。6.5 测试总结通过测试,发现了许多本来没有发现的BUG,但程序的基本功能已经实现,但管道命令执行存在一定的问题,有待解决。7 总结及感想7.1 32060624 王克通过这个Linux Shell的实验让我受益匪浅,让我对Linux有了更深入的理解,特别是其BASH的执行过程。由于程序使用C语言编写,让我在使用OO语言的空闲之余再度回归到了C语言,对自己编程基础的提高很有帮助。开发Linux下程序,也让我学到了许多新的东西,如使用VI,EMACES编辑,使用MAN查手册,使用GCC(CC)编译,使用GDB调试,以及用MAKE来组织编译文件。这让我这个一直努力使用LINUX的爱好者更加了解一LINUX下编程,而不是只停留在LINUX下的简单操作层面上。SHELL程序让我对操作系统课上学的概念有了进一步的了解,特别是内核的系统调用、进程管理及通信,管道、并发等知识得到了巩固。在完成此大作业的过程中,我也认识到了项目小组内合作的重要性,大家要合理分工,加强管理,使用版本控制软件(暂用VSS)及建模工具(不多)等。小组内大家相互信任和良好的合作态度给我留下了深刻印象。我们会继续努力做好以后的实验内容!7.2 32060518 杜可斌 通过编写YSH0程序,我更加熟悉了各种SHELL命令,理解了SHELL的具体实行过程,以及其中用到的各种功能调用。同时,我也提高了自己的C语言的编程能力,并获得组织较大型程序的能力。在整个YSH0的编写过程中,OS小组成员之间,互相探讨,互相帮助,合理分工,既提高了各成员的专业水平,也促进了小组成员的团队协作能力。可以说,通过该OS实验,我们都得到了很大的提高.7.3 32060621 张劲通过这次操作系统大作业的完成,我在Linux下的编程能力得到了大大的提高,对Linux的了解也更深了一步。同时,也加深了对课程理论的理解。7.4 32060532 徐瑞通过操作系统的大作业,使我更熟悉了Linux下的编程环境,加深了对进程管理、进程通信的理解,明白了操作系统的并发处理机制,并且和小组各成员之间也建立了友好的交流和合作关系。8 附录8.1 参考资料l 毛曙福,Linux C高级程序员指南,国防工业出版社,2001.2l 任爱华等,操作系统实验指导,清华大学出版社,2004.6l William Stallings著,魏迎梅等译,操作系统内核与设计原理,电子工业出版社,2005.1l 任爱华等,操作系统实验指导,清华大学出版社,2004.68.2 源代码/*LinuxShell0.txtPowered by 3206. 2005.4.24 2005.4.27-V0.1 */ /* *库文件 */ #include #include #include #include #include #include #include #include #include /*#define DEBUG_ON*/*程序中DEBUG信息开关*/ /* *宏定义和常数 */ #define BUFSIZE 256 /*定义最大buf大小*/ #define HISTORYMAX 11/*定义最大历史命令信息数*/ #define NAMESIZE 100 #define CMD_PIPE 0/*定义管道命令类型*/ #define CMD_REDIR 1/*定义重定向命令类型 */ #define CMD_INTER 2/*定义内部命令类型*/ #define CMD_EXTER 3/*定义外部命令类型*/ #define TRUE 1 /*定义真*/ #define FALSE 0 /*定义假*/ #define INOUT -1 /*定义既不是输入也不是输出*/ #define IN 0 /*定义输入*/ #define OUT 1 /*定义输出*/ /* *全局变量 */ /*定义历史命令信息数组*/ typedefstructhistory intstart; intend; charcmdBufHISTORYMAXBUFSIZE; history; historyhistoryCmds; /*定义作业结构链表*/ typedefstructjobs pid_tpid; charcmdNameBUFSIZE; charstate10; structjobs*link; jobs; /*定义指向作业链表的头指针,尾指针*/ jobs*headJob,*endJob; typedefstructfileRedir inttype; charnameNAMESIZE; fileRedir; fileRedir*filesHISTORYMAX; charbufBUFSIZE,*argHISTORYMAX,*envPathHISTORYMAX,*inputBuf=NULL; /*char infileBUFSIZE, outfileBUFSIZE;*/ intinputLen,isBackgroundJob,argCount,curJobPid,status,fileCount; /* *主函数,程序入口 */ voidinitEnv();/*初始化环境*/ intreadInput();/*读入用户输入,保存到指针input中,返回读取的字符数*/ intparseInput();/*解析命令函数*/ voidexecuteCmd(intcmdType);/*执行命令函数*/ voidaddToHistory(char*);/*命令添加到历史函数*/ voidhistoryCmd();/*历史命令函数*/ voidcdCmd();/*CD命令函数*/ voidjobsCmd();/*打印任务命令函数*/ voidbgCmd();/*任务后台化bg %命令函数*/ voidfgCmd();/*任务前台化函数*/ intfindProg(char*cmdBuf);/*查找外部命令函数*/ voidaddJob(intjobPid,char*name);/*添加任务函数*/ voiddelJob(intjobPid);/*删除任务函数*/ voidctrlz();/*响应键盘CTRL + Z操作函数*/ voidDEBUG(char*s1,char*s2);/*调试程序时信息输出函数*/ /*主函数*/ main() intpath,cmdType; initEnv(); for(;) isBackgroundJob=FALSE;/*设置后台运行程序标志*/ argCount=0;/*设置参数个数初值*/ /*/ path=get_current_dir_name(); printf(lsh0#%s ,(char*)path);/*?*/ /*/ /*读入命令*/ if(0=readInput() continue; /*解析命令*/ cmdType=parseInput(); /*执行命令*/ executeCmd(cmdType); /* *程序初始化函数 */ voidinitEnv() FILE*fp; intlineLen,len,i,envPathCount; char*tmpBuf=NULL; curJobPid=0; len=0; envPathCount=0; historyCmds.start=0; historyCmds.end=0; headJob=endJob=NULL; /*打开保存查找路径的lsh0_profile文件*/ if(fp=fopen(lsh0_profile,r)=NULL) printf(-lsh0: Lost profile file n); exit(1); while(lineLen=getline(&tmpBuf,&len,fp)!=-1) DEBUG(getline :,tmpBuf); i=0; len=0; for(;tmpBufi!=;+i) ; tmpBufi+=0; if(0!=(strcmp(tmpBuf,PATH)/*比较tmpBuf 与PATH的内容*/ return; while(tmpBufi+!=0) if(tmpBufi=:) buflen+=/; buflen=0; envPathenvPathCount=(char*)malloc(sizeof(char)*len); strcpy(envPathenvPathCount+,buf); envPathenvPathCount=NULL; len=0; DEBUG(path :n,envPathenvPathCount-1); else buflen+=tmpBufi; /* *读入用户输入,保存到指针input中,返回读取的字符数 */ intreadInput() charc; inputLen=0; while(c=getchar()= |c=t|c=EOF)/*跳过开始的空格,制表符,以及文件结尾*/ ; /*获得一行输入,并将之保存在buf中*/ while(c!=n) bufinputLen+=c; c=getchar(); if(inputLen=0) return0; bufinputLen=0;/*在字符数组buf的最后插入一个结束标志*/ inputBuf=(char*)malloc(sizeof(char)*(inputLen+1); strcpy(inputBuf,buf);/*将buf中的内容送入inputBuf*/ DEBUG(inputBuf = ,inputBuf); returninputLen;/*返回读入的字符长度*/ /* *解析命令函数 */ intparseInput() inti,j,k,bufCount,isSpaceChar; /*以下对所有输入命令进行初步分析*/ for(i=0,isSpaceChar=FALSE,bufCount=0,argCount=0;i=inputLen;+i) if(inputBufi= |inputBufi=t|inputBufi=0) if(isSpaceChar=TRUE)/*跳过空格等无用信息*/ continue; else bufbufCount+=0; argargCount=(char*)malloc(sizeof(char)*bufCount); strcpy(argargCount+,buf);/*分配动态存储空间,将命令从缓存拷贝到input中*/ bufCount=0; isSpaceChar=FALSE; DEBUG(argn = %s,buf); else if(inputBufi=&inputBufi+1=0) isBackgroundJob=TRUE;/*将后台命令标志置一*/ continue; bufbufCount+=inputBufi; /*针对管道命令调整参数*/ for(i=0;i=inputLen;+i) if(inputBufi=) for(j=0;jargCount;+j) if(strcmp(argj,)=0) filesfileCount=(fileRedir*)malloc(sizeof(fileRedir); if(strcmp(argj,type=IN; elseif(strcmp(argj,)=0) filesfileCount-type=OUT; strcpy(filesfileCount+-name,arg+j); filesfileCount=NULL; +j; for(k=j;kargCount;+k) strcpy(argk-2,argk); DEBUG(arg0 = %s,argk); argk-2=NULL; argCount-=2; returnCMD_REDIR; /*针对重定向命令调整参数*/ elseif(inputBufi=|) for(j=0;jargCount;+j) if(strcmp(argj,)=0) filesfileCount=(fileRedir*)malloc(sizeof(fileRedir); if(strcmp(argj,type=IN; elseif(strcmp(argj,)=0) filesfileCount-type=OUT; strcpy(filesfileCount+-name,arg+j); filesfileCount=NULL; +j; for(k=j;kBye! Thank you!n); free(inputBuf); exit(0); elseif(strcmp(arg0,history)=0)/*执行history命令,打印历史命令信息*/ historyCmd(); elseif(strcmp(arg0,jobs)=0)/*执行jobs命令*/ jobsCmd(); elseif(strcmp(arg0,cd)=0)/*执行cmd命令*/ cdCmd(arg1); elseif(strcmp(arg0,bg)=0)/*执行bg命令*/ bgCmd(); elseif(strcmp(arg0,fg)=0)/*执行fg命令*/ fgCmd(); /*/ elseif(cmdType=CMD_EXTER) if(!findProg(arg0)/*没有找到该命令程序*/ printf(-lsy0: This command is not founded!n); /*return;*/ if(curJobPid=fork()=0)/*若为子进程,执行该命令*/ argargCount=(char*)malloc(sizeof(char);/*将最后一个参数置为NULL*/ argargC
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025版授权合同续签及运营权调整协议3篇
- 二零二五年度车辆抵押评估服务合同3篇
- 二零二五年度城市绿地租赁合同示范文本4篇
- 2025机械外加工合同协议书模板
- 二零二五年度车棚光伏发电系统设计与施工合同4篇
- 2025单方合同范本
- 二零二五年度高端电子产品采购与专业运输合同范本3篇
- 二零二五年度海南鲜品线上销售渠道建设合同2篇
- 二零二五年度存量房购买房屋维修保养合同3篇
- 二零二四年智慧农业债权债务担保合同3篇
- 盘式制动器中英文对照外文翻译文献
- 社会系统研究方法的重要原则
- 重症医学科健康宣教手册
- 2022版《义务教育英语课程标准》解读培训课件
- 科技进步类现代轨道交通综合体设计理论与关键技术公
- 五个带头方面谈心谈话范文三篇
- 互联网的发展历程
- 部编人教版五年级道德与法治下册全册课件(完整版)
- 广西贵港市2023年中考物理试题(原卷版)
- 外观质量评定报告
- 窒息的急救解读课件
评论
0/150
提交评论