Linux系统下模拟实现命令解释器

本文发布时间: 2019-Mar-22
一.程序概述1. 进入系统概述本次课程设计是在红帽Linux发行版(Red Hat Enterprise Linux AS release 4 (Nahant Update 4) ))环境下运行,内核为:Kernel 2.6.9-42.ELsmp on an i686。以下为进入Linux操作系统命令行界面cd os_design 进入os_design这个目录pwd 显示当前路径为:/home/10131/os_design这个路径为本次操作系统课程设计的目录ls 显示os_design下的文件:cmd.cpp 为本次课程设计的源文件,采用语言为C++执行命令g++ -o cmd cmd.cpp产生可执行文件:cmd在命令行键入:./cmd就可以直接运行2. 源程序完成的功能本次课程设计在Linux环境下模拟实现命令解释器:本人实现的功能如下:1.使用pwd命令,实现查看目录所处路径的功能。2.使用dir命令,实现显示列出指定目录名中的所有目录及文件的功能。3.使用cd命令,实现改变工作目录的功能。4.使用newdir命令,实现创建新的目录的功能。5.使用deldir命令,实现删除目录的功能。6.使用rename命令,实现重命名一个文件或目录的功能。7.使用find命令,实现查找指定目录下及其子目录的指定文件。8.使用date命令,实现显示当前日期。9.使用exit命令,实现退出命令行模式。二.概念原理本次操作系统课程设计使用的语言为C++,包含的头文件大多是Linux下c的函数库。通过调用相关的函数库来实现模拟shell命令操作。下面是对一些概念原理的说明:1.源程序包含的头文件#include<iostream>//主要用于一些标准输入输出:cin,cout操作 #include<cstring>//标准C++函数库,主要用于字符串处理#include<sys/types.h>//基本系统数据类型#include<sys/stat.h>//文件状态#include<dirent.h>//文件操作函数#include<fcntl.h>//文件控制#include<time.h>//定义关于时间的函数#include<ftw.h>//文件树漫游以上是整个源程序涉及到的一些函数头文件2.函数概念说明以下是对程序调用Linux c函数库的方法说明:调用getcwd()函数函数原型:char * getcwd(char * buf,size_t size);函数说明:getcwd()会将当前的工作目录绝对路径复制到参数buf所指的内存空间,参数size为buf的空间大小。在调用此函数时,buf所指的内存空间要足够大,若工作目录绝对路径的字符串长度超过参数size大小,则回值NULL,errno的值则为ERANGE。倘若参数buf为NULL,getcwd()会依参数size的大小自动配置内存(使用malloc()),如果参数size也为0,则getcwd()会依工作目录绝对路径的字符串程度来决定所配置的内存大小,进程可以在使用完此字符串后利用free()来释放此空间。返回值:执行成功则将结果复制到参数buf所指的内存空间,或是返回自动配置的字符串指针。失败返回NULL,错误代码存于errno。调用opendir()函数函数原型:DIR * opendir(const char * name);函数说明:opendir()用来打开参数name指定的目录,并返回DIR*形态的目录流,和open()类似,接下来对目录的读取和搜索都要使用此返回值。返回值:成功则返回DIR* 型态的目录流,打开失败则返回NULL。调用readdir()函数函数原型:struct dirent * readdir(DIR * dir);函数说明:readdir()返回参数dir目录流的下个目录进入点。结构dirent定义如下struct dirent{ino_t d_ino;ff_t d_off;signed short int d_reclen;unsigned char d_type;har d_name[256;};d_ino 此目录进入点的inoded_off 目录文件开头至此目录进入点的位移d_reclen _name的长度,不包含NULL字符d_type d_name 所指的文件类型d_name 文件名返回值:成功则返回下个目录进入点。有错误发生或读取到目录文件尾则返回NULL。附加说明:EBADF参数dir为无效的目录流。调用closedir()函数函数原型:int closedir(DIR *dir);函数说明:closedir()关闭参数dir所指的目录流。返回值:关闭成功则返回0,失败返回-1,错误原因存于errno 中。调用chdir()函数函数原型:int chdir(const char * path);函数说明:chdir()用来将当前的工作目录改变成以参数path所指的目录。返回值:执行成功返回0,失败返回-1;调用mkdir()函数函数原型:int mkdir(const char *pathname, mode_t mode);函数说明:mkdir()函数以mode方式创建一个以参数pathname命名的目录,mode定义新创建目录的权限。返回值:若目录创建成功,则返回0,否则返回-1;调用rmdir()函数函数原型:int _rmdir(const char *dirname);函数说明:rmdir()函数删除以参数dirname为命名的目录。返回值:若目录删除成功,则返回0,否则返回-1;调用rename()函数函数原型:int rename(const char * oldpath,const char * newpath);函数说明:rename()会将参数oldpath 所指定的文件名称改为参数newpath所指的文件名称。若newpath所指定的文件已存在,则会被删除。返回值:执行成功则返回0,失败返回-1。调用ftw()函数表头文件:#include <ftw.h>函数原型:int ftw(const char *dir, int (*fn) (const *file, const struct stat *sb, int flag), int depth)函数说明:ftw() 会从参数dir指定的 目录开始,往下一层层地递归式遍历子 目录。ftw()会传三个参数给fn(), 第一个参数*file指向当时所在的 目录路径,第二个参数是*sb, 为stat结构指针,第三个参数为旗标,有下面几种可能值:FTW_F 一般文件FTW_D 目录FTW_DNR 不可读取的 目录,此 目录以下将不被遍历FTW_SL 符号连接FTW_NS 无法取得stat结构数据,有可能是 权限问题最后一个参数depth代表ftw()在进行遍历 目录时同时打开的文件数。ftw()在遍历时每一层 目录至少需要一个文件描述词,如果遍历时用完了depth所给予的限制数目,整个遍历将因不断地关文件和开文件操作而显得缓慢.如果要结束ftw()的遍历,fn()只需返回一非零值即可,此值同时也会是ftw()的返回值。否则ftw()会试着走完所有的 目录,然后返回0.返回值:遍历中断则返回fn()函数的返回值,全部遍历则返回0,若有错误发生则返回-1三.完成情况完成了整个操作系统课程设计的命令行功能基本要求:pwd//显示当前所在目录的路径名dir <目录名>//列出指定目录名中的所有目录及文件cd<目录名或路径> //改变当前工作目录newdir<目录名>//新建目录deldir<目录名> //删除目录exit //退出命令解释程序其中直接输入dir不能直接显示文件和目录,需要在使用dir .,才能显示当前文件夹下的目录和文件基本完成了以下几个扩展命令的动能要求:rename <旧文件名> <新文件名> //重命名一个文件或目录find <目录>-name <待查找的文件名> //在指定的目录及其子目录中查找指定的文件 date//显示当前日期其中find命令,只能查询指定目录的文件,不能指定待查找的文件名。通过测试,以上所有命令都运行正常。整个程序,代码实现简单清晰,没有太复杂的算法。基本上就是对函数的调用实现。运行结果又较好的提示信息,无论是成功错误都提示相应的信息。源代码的注释内容也非常清晰,方便查看理解函数调用的功能。四.详细设计下面是对整个程序功能实现的介绍:1.pwd()函数主要调用了getcwd()函数,获取当前工作目录的绝对路径。相关代码:char ptr[80];getcwd(ptr, sizeof(ptr));getcwd函数会将当前的工作目录绝对路径复制到参数buf所指的内存空间,所以直接输出ptr就可以得到当前目录的绝对路径。2.dir()函数dir()函数主要实现显示指定目录下的目录和文件调用了opendir()、readdir()、closedir()等对文件权限操作的函数下面是主要代码,输出目录dir = opendir(dirname);while((ptr = readdir(dir)) != NULL){// if the d_name is equal with "." or ".." ,do nothingif(strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0){}// if not , print the ptr->d_nameelsecout<<ptr->d_name<<" ";// count the d_namecount++;// if count % 8 == 0, line feedif(count % 8 == 0)cout<<endl;}closedir(dir);详细设计说明:1.通过目录名dirname,调用opendir()函数打开目录流2.调用readdir()函数读取目录,返回dirent*数据结构3.将d_name(目录名/文件名)输出4.有开的过程,就应该有关的过程,调用closedir()函数关闭目录流。3.cd()函数cd函数主要实现切换目录的功能。详细设计如下:调用chdir()函数切换目录,如果切换成功就返回0,切换失败返回-1;4.newdir()函数newdir函数主要实现,新建目录的功能。详细设计如下:调用mkdir()函数就可以创建新的目录,如果创建成功返回0,创建失败返回-1;实现代码如下:if(mkdir(filename,0777) == 0){cout<<filename<<" indecates successful!!!"<<endl;}else{cout<<filename<<" indecates failure!!!"<<endl;}其中0777设置文件为最大权限5.deldir()函数deldir函数主要实现了删除目录的功能。详细设计如下:调用rmdir()函数就可以将指定目录删除,如果创建成功返回0,创建失败返回-1;实现代码跟第4点类似。这里就不多说了。6.rename()函数rename函数主要实现了对文件进行重命名的功能。详细设计如下:调用rename(filename1, filename2);就可以将filename1更改为filename2,如果更改成功的话,返回0,否则返回-1;7.find()函数find函数主要实现了查找指定目录的文件,并列出每一个文件的类型,这里指列出来了目录和文件类型。find函数调用了ftw库函数,8.date()函数date函数实现的功能是显示当前日期。详细设计说明:代码实现如下:主要是调用ctime()函数返回一个关于日期的字符串。直接将这个字符串输出,就可以知道当前日期和时间。五.使用情况./cmd运行程序会显示以上9条命令使用提示,并指令提示符为[姓名@]$1.使用pwd命令 ----显示当前目录的绝对路径2.使用dir命令显示指定目录的文件和目录3.使用cd命令更换目录4.使用newdir命令新建目录5.使用deldir命令删除目录6.使用rename命令重命名目录7.使用find命令查找指定目录的文件8.使用date命令显示当前日期和时间9.使用exit命令退出命令行六.设计总结1.遇到的困难及解决的问题一段时间没有使用C++/C语言,有些函数的使用不怎么清晰,用惯了java的思考模式和API,转换过来用C++语言来编程,感觉有点不怎么舒服。后来,简单复习了C++的输入输出还有头文件包含等知识,还是把以前的底子给捡起来了。整个课程设计,遇到的问题并不多,难度是如果去理解Linux c函数库的调用。需要花时间去理解每一个函数的作用和相关参数的作用。刚开始做的时候,也是不知道怎么开始,之前把问题想得复杂化了,后来通过一步一步实现每个指令,才慢慢找到解决的办法。 2.总结与感想总的来说,整个课程设计还算比较顺利,因为对Linux操作系统接触得并不多,对一些命令行的实现还不怎么清楚,后来通过查阅资料,自己用虚拟机运行了Linux Ubuntu发行版来研究了一下。发现Linux确实非常简洁好用,我非常喜欢这样的系统。历时两天的时间,把程序设计出来了,也认真写了下这次的文档。感觉通过一段时间的学习,自己的编程能力确实变强了,但还是有许多不足。在程序设计过程中,要学会查看文档,因为很多文档都是英文,这就需要英文好一点。我也在克服查看英文文档的障碍,努力提升自己的英文阅读能力。通过这次课程设计,也让自己捡起了C++这门语言,熟悉了Linux环境下的一些命令操作,并且让我有了极大兴趣去研究Linux,我在接下来的时间里也会使用和学习Linux程序设计。总的来说,感觉不错。七.参考文献《Linux 程序设计第4版》,《The GUN C Library Manual》源程序代码如下:因为解决乱码问题,所以小巫把注释都改为了英文,我的英文有点粗,希望有人能看懂。/**source file: cmd.cpp @stunum: 201038889071 @classnum: 31 @author:wwj @date:2012/12/16 @decription:Linux Operation System **/ #include<iostream> #include<cstring> #include<sys/types.h> #include<sys/stat.h> #include<dirent.h> #include<stdlib.h> #include<fcntl.h> #include<time.h> #include<queue> #include<ftw.h> using namespace std; //declare method void pwd(); //show current absolute path void dir(); //show directory and file void cd(); //change directory void newdir(); //make new directory void deldir(); //delete directory void rename(); //rename the directory's name void find(); //find the assign file in the assign directory void date(); //show the date of now int fn(const char *file, const struct stat *sb, int flag); /** * main method * return 0 **/ int main(int argc, char *argv[]) { cout<<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"<<endl; cout<<">>>>>>Welcome to wwj's cmd line<<<<<<"<<endl; cout<<"You can use the commands as follows:"<<endl; cout<<"1. pwd "<<endl; cout<<"2. dir <dirname>"<<endl; cout<<"3. cd <dirname or path> "<<endl; cout<<"4. newdir <dirname> "<<endl; cout<<"5. deldir <dirname> "<<endl; cout<<"6. rename <old filename> <new filename> "<<endl; cout<<"7. find <dirname>"<<endl; cout<<"8. date "<<endl; cout<<"9. exit "<<endl; cout<<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"<<endl; string str; //when the str is equal with the string "exit",break the cycling while(str != "exit") { //shell prompt cout<<"[wuwenjie@]$"; cin>>str; //enter the command if(str == "pwd"){ // if str is equal with the string "pwd", execute the pwd() method pwd(); } if(str == "dir") { // if str is equal with the string "dir", execute the dir() method; dir(); } if(str == "cd") { // if str is equal with the string "dir", execute the cd() method; cd(); } if(str == "newdir"){ // if str is equal with the string "newdir", execute the newdir() meth newdir(); } if(str == "deldir"){ // if str is equal with the string "deldir", execute the deldir() mte deldir(); } if(str == "rename") { // if str is equal with the string "rename", execute the rename() meth rename(); } if(str == "date") { // if str is equal with the string "date", execute the date() method; date(); } if(str == "find") { // if str is equal with the string "find",execute the find() method find(); } } return 0; } /** * fuction:show current directory path * return : void **/ void pwd() { char ptr[80]; // create a character array with the size of 80 getcwd(ptr,sizeof(ptr)); //invoke the getcwd() method cout<<ptr<<endl; //print the directory path } /** * fuction: show current directory's directory or file * return : void */ void dir() { DIR * dir; //The DIR data type represents a directory stream struct dirent* ptr; int count = 0; char *dirname; cin>>dirname; dir = opendir(dirname); if(dir == NULL) { cout<<"cannot open directory"<<endl; } //The opendir function opens and returns a directory stream for reading the rectory whose file name is dirname //This readdir function reads the next entry from the directory. while((ptr = readdir(dir)) != NULL) { // if the d_name is equal with "." or ".." ,do nothing if(strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0){} // if not , print the ptr->d_name else cout<<ptr->d_name<<" "; // count the d_name count++; // if count % 8 == 0, line feed if(count % 8 == 0) cout<<endl; } // close directory stream. closedir(dir); cout<<endl; } /** * function; change the directory path * return: void */ void cd() { char dirname[20]; cin>>dirname; //if change the directory successful if(chdir(dirname) == -1) { cout<<"the directory is not exit!!!"<<endl; } else { cout<<"change directory success!!!"<<endl; } } /** * function : make a new directory * return: void */ void newdir() { char filename[20]; cin >> filename; //S_IFDIR is the mode, the meaning is the file'type is a dirtectory if(mkdir(filename, 0777) == 0) { cout<<filename<<" indecates successful!!!"<<endl; } else { cout<<filename<<" indecates failure!!!"<<endl; } } /** * function : delete a directory * return: void */ void deldir() { char filename[20]; cin >> filename; // if delete the dirtectory successful return 0 if(rmdir(filename) == 0) { cout<<filename<<" delete successful!!!"<<endl; } else cout<<filename<<" delete failure!!!"<<endl; } /** * function: rename the diretory'name * return :void */ void rename() { char filename1[20], filename2[20]; cin>>filename1>>filename2; // if the directory rename successful it will return 0 if(rename(filename1, filename2) == 0) { cout<<filename1<< " success change to "<<filename2<<endl; } else cout<<filename1<< " failure change to "<<filename2<<endl; } /** * function: find the assign directory and child directory's assign file * return: void */ void find() { char dirname[50]; cin>>dirname; // ftw(const char *dir, int(*fn)(const *file, const struct stat *sb,int fl ,int depth) ftw(dirname, fn,500); } /** * function: ergodic every layer directory and print the files * @param *file * @param struct stat *sb * @param flag * return int */ int fn(const char *file, const struct stat *sb, int flag) { if(flag == FTW_D) cout << file <<"-- directory"<<endl; else if(flag == FTW_F) cout << file <<"-- file"<<endl; return 0; } /** * function: show the current date * return : void */ void date() { time_t timeval; (void)time(&timeval); string timestr; // invoke the ctime fuction and return the string timestr = ctime(&timeval); cout<<"The date is: "<<timestr<<endl; }


(以上内容不代表本站观点。)
---------------------------------
本网站以及域名有仲裁协议。
本網站以及域名有仲裁協議。

2024-Mar-04 02:11pm
栏目列表