操作系统上机——实现一个简单的shell
2012-03-21 22:28
519 查看
原题见《操作系统—精髓与设计原理(第五版)》一书110页。
这里是实现代码。实现了基本的功能,主要通过系统调用,实验环境为Fedora 16 linux 。
//myshell.h
//myshell.c
其中的cd命令通过chdir函数实现。通过查资料和实验得知,在shell里面直接用cd命令实现工作目录切换不可以,因为system(command)是通过创建子进程实现系统命令调用,原则上是子进程执行cd命令,shell并未改变目录,因此必须通过其他方式比如调用chdir函数实现。
以下是makefile
#makefile
myshell:myshell.c myshell.h
gcc -I. myshell.c -o myshell
以下是readme
//readme
这里是实现代码。实现了基本的功能,主要通过系统调用,实验环境为Fedora 16 linux 。
//myshell.h
#include<stdio.h> #include<stdlib.h> #include<string.h> #define MAX_BUFFER 1024 //字符串长度最大值 #define MAX_ARGS 64 //参数最大数量 #define SWEPARATOR " \n\t"
//myshell.c
/********************************************************** myshell-basic shell replacement >my shell 从键盘输入一行字符串,分割字符串并解析为cmd命令 clr 清屏 ls <directory> 列出<directory>目录下面的文件,默认为当前目录 environ 环境变量 quit 退出 **********************************************************/ #include<myshell.h> extern char **environ; /**********************************************************/ int main(int argc,char** argv) { //system("title MyShell"); char linebuf[MAX_BUFFER]; char cmndbuf[MAX_BUFFER]; char *args[MAX_ARGS]; char **arg; char* prompt="==>"; while(!feof(stdin)) { system("pwd"); fputs(prompt,stdout); fflush(stdout); //输入参数 if(fgets(linebuf,MAX_BUFFER,stdin)) { arg=args; *arg++=strtok(linebuf,SWEPARATOR);//按空格,换行符,制表符等分割字符串 while((*arg++=strtok(NULL,SWEPARATOR))); if(args[0])//第一个参数存在 { //printf("args[0]:%s\n",args[0]); cmndbuf[0]=0; //printf("cmndbuf[0]:%c\n%s\n",cmndbuf[0],args[0]); //检查是否为系统已经存在的命令 if(!strcmp(args[0],"clr")) { strcpy(cmndbuf,"clear"); } else if(!strcmp(args[0],"dir")) { strcpy(cmndbuf,"ls "); if(!args[1]) { args[1]=".";//没输入参数默认为当前目录 } strcat(cmndbuf,args[1]); //printf("%s",cmndbuf); } else if(!strcmp(args[0],"help")) { strcpy(cmndbuf,"more ./readme");//显示当前目录下的readme } else if(!strcmp(args[0],"pause")) { //printf("Press enter to continue...\n");//提示暂停,直到按下回车键 strcpy(cmndbuf,"read -n 1 -p \"Press any key to continue...\""); // char temp=malloc(sizeof(char)); // scanf("%c",&temp); // while(strcmp(temp,'\n')) // { // scanf("%c",&temp); // } } else if(!strcmp(args[0],"cd")) { if(!args[1]) { args[1]=".";//没输入参数默认为当前目录 } int result=chdir(args[1]); if(result<0) {printf("Error:directory not exist!\n");} } else if(!strcmp(args[0],"environ")) { char** envstr=environ; while(*envstr) { printf("%s\n",*envstr); envstr++; } } else if(!strcmp(args[0],"quit")) { break;//return 0,退出循环 } else //其他命令 { int i=1; strcpy(cmndbuf,args[0]); while(args[i]) { strcat(cmndbuf," "); strcat(cmndbuf,args[i++]); } } //调用系统命令 if(cmndbuf[0]) { system(cmndbuf); } } } } return 0; }
其中的cd命令通过chdir函数实现。通过查资料和实验得知,在shell里面直接用cd命令实现工作目录切换不可以,因为system(command)是通过创建子进程实现系统命令调用,原则上是子进程执行cd命令,shell并未改变目录,因此必须通过其他方式比如调用chdir函数实现。
以下是makefile
#makefile
myshell:myshell.c myshell.h
gcc -I. myshell.c -o myshell
以下是readme
//readme
myshell - 一个简单的shell 概要 myshell 版权 myshell is Copyright (C) 2012 by Duan Cong. 介绍 myshell 是一个简单的shell程序,通过它你可以用来实现简单的命令行操作,比如列出目录下面的文件,清屏等等。 用法 在终端下输入myshell,即可打开程序。 后台运行:在终端下输入myshell时,紧接着输入一个&,即输入myshell&。 功能 当进入myshell后,你可以通过输入相应命令实现以下功能: cd [directory] —— 把当前默认目录改变为[directory]。不输入参数默认为当前目录。 dir [directory] —— 列出目录[directory]的内容。不输入参数默认为当前目录。 clr —— 清屏。 environ —— 列出所有的环境变量。 echo [comment] —— 在屏幕上显示[comment]并换行。 help —— 显示本用户手册。 quit —— 退出myshell。 还调用其他程序和系统命令。 说明 输入输出重定向功能: 在myshell中使用命令行如programname arg1 arg2 > outputfile 时,programname的输出将输出到outputfile里而不是显示屏幕上。如果outputfile已存在则覆盖已有文件,如果不存在则创建输出文件。 在myshell中使用命令行如programname arg1 arg2 >> outputfile 时,programname的输出将追加到outputfile里而不是显示屏幕上。如果outputfile已存在则将输出添加到已有文件尾部,如果不存在则创建输出文件。 示例 当前目录为/home/dc,在终端下输入myshell,显示如下: [dc@localhost ~]$ myshell /home/dc ==> 说明已经进入程序。 继续输入dir,显示如下: /home/dc ==>dir A Desktop index.php note.xml Public Untitled 1.docx Audiobooks Documents index.php.bak Pictures Templates Videos blog.docx Downloads Music Podcasts test.txt /home/dc ==> 输入clr,显示如下: /home/dc ==> 屏幕被清空。 输入environ,显示如下(中间省略部分环境变量,用省略号代替): /home/dc ==>environ XDG_VTNR=1 XDG_SESSION_ID=2 HOSTNAME=localhost.localdomain IMSETTINGS_INTEGRATE_DESKTOP=yes GPG_AGENT_INFO=/tmp/keyring-sFt4mm/gpg:0:1 TERM=xterm SHELL=/bin/bash ... XAUTHORITY=/var/run/gdm/auth-for-dc-mesabL/database _=/home/dc/Desktop/operating_system/project/myshell OLDPWD=/home/dc/Desktop/operating_system/project /home/dc ==> 输入dir /,显示如下: /home/dc ==>dir / bin dev home lost+found mnt proc run srv tmp var boot etc lib media opt root sbin sys usr /home/dc ==> 另外,myshell可以调用其他程序,例如输入gedit,将调用GUI的文本编辑器gedit,在终端中按下ctrl+C可以结束gedit进程。 在myshell中输入quit,退出myshell,返回终端,显示如下: /home/dc ==>quit [dc@localhost ~]$ 以上仅为部分示例,更多详细请参考“功能”。
相关文章推荐
- Clojure:在REPL上实现一个简单的shell(一)
- 一个简单的shell脚本-----实现虚拟机实验环境的简单配置
- 【C语言】实现一个简单SHELL应用
- 实现一个简单shell(支持重定向)
- C语言 实现一个简单的Shell (支持管道和"cd")
- 关于一个简单的shell的实现
- Linux下实现一个简单进度条和shell脚本实现彩色进度条
- 用Qt实现一个简单的shell (Qt5+V8)
- 用Qt实现一个简单的shell (Qt5+V8)
- 一个简单的wifi开关shell脚本实现
- shell实现一个简单的计算器功能小脚本
- 利用linux下的c语言编程来简单的实现一个shell功能实现!
- 【Linux】实现一个简单的shell
- 用C语言实现一个简单的Linux壳层(Shell)
- shell实现一个简单进度条
- 用c语言的实现一个简单的交互式shell
- Clojure:在REPL上实现一个简单的shell(二)
- 实现一个简单的shell
- Linux编程实现一个简单的Shell
- 【Linux】实现一个简单的shell