网站维护员工作内容,page手机转wordpress,网站没排名要怎么做,论坛类网站建站文章目录 #x1f984;0. shell#x1f42e;1. 交互及获取命令行#x1f437;2. 解析命令行#x1f42f;3. 执行命令行#x1f405;3.1 普通命令#x1f405;3.2 内建命令 #x1f981;4. 主函数逻辑及演示 本章代码gitee仓库#xff1a;简易shell #x1f984;0. she… 文章目录 0. shell1. 交互及获取命令行2. 解析命令行3. 执行命令行3.1 普通命令3.2 内建命令 4. 主函数逻辑及演示 本章代码gitee仓库简易shell 0. shell
shell是操作系统外的一层外壳程序负责将用户的指令执行将指令获取到之后再交给操作系统操作系统将指令执行完毕之后的结果通过shell交给用户。shell/bash也是一个进程本质上也是通过创建子进程来执行这些指令。
1. 交互及获取命令行
我们先来开一下交互及我们输入的命令行格式 先来做交互的页面这其实就是一个while循环一直等着我们输入指令我们可以通过获取环境变量来获取这些信息。
#define LEFT [
#define RIGHT ]
#define LABLE #
const char *getUserName()
{return getenv(USER);
}
const char *getHostName()
{return getenv(HOSTNAME);
}
void getPwd()
{getcwd(pwd,sizeof(pwd));
}
void interact(char *cline, int size)
{getPwd();printf(LEFT%s%s %sRIGHTLABLE ,getUserName(),getHostName(),pwd);char *s fgets(cline,size,stdin); //获取指令assert(s);(void)s; //防止后面不使用s变量报警告假装用一下cline[strlen(cline)-1] \0; //将回车抵消//printf(%s\n,s);
}我们可以输出我们获取的命令测试一下 2. 解析命令行
获取到命令之后我们就要解析这个命令这个解析的本质上就是将获取的字符串进行分割分割各个部分要执行的命令、所带的命令行参数
例如ls -a -l我们就需要解析成
所需执行的命令ls命令行参数-a、-l
#define DELIM \t
int splitString(char cline[], char *_argv[])
{int i 0;_argv[i] strtok(cline,DELIM);while(_argv[i] strtok(NULL,DELIM));return i-1;
}3. 执行命令行
获取到所需执行的命令和参数之后其实就是创建子进程然后程序替换来执行这个命令但是这些命令分为普通命令和内建命令
普通命令创建子进程直接程序替换内建命令父进程自己执行
3.1 普通命令
这里没有什么高科技就是简单的创建子进程、程序替换和进程等待
#define EXIT_CODE 11
void normalExcute(char *_argv[])
{pid_t id fork();if(id 0){perror(fork fail);return; }else if(id 0){//子进程执行命令//execvpe(_argv[0],_argv,environ); //直接程序替换execvp(_argv[0],_argv); //直接替换程序exit(EXIT_CODE); //替换失败的退出码}else{//父进程等待子进程退出int status 0;pid_t rid waitpid(id,status,0); //阻塞等待if(rid id){lastcode WEXITSTATUS(status);}}
}3.2 内建命令
对应内建命令需要我们自己去一个一个添加然后判断这里做一个简单的演示
int buildCommand(char *_argv[], int _argc)
{if(_argc 2 strcmp(_argv[0],cd) 0){chdir(_argv[1]);getPwd();sprintf(getenv(PWD),pwd);return 1;}else if(_argc 2 strcmp(_argv[0],export) 0) //导环境变量{putenv((char*)_argv[1]);return 1;}else if(_argc 2 strcmp(_argv[0],echo) 0) {if(strcmp(_argv[1],$?)0){printf(%d\n,lastcode);lastcode 0;}else if(*_argv[1] $){char*val getenv(_argv[1]1);if(val) printf(%s\n,val);}else printf(%s\n,_argv[1]);return 1;}//将ls命令显示颜色if(strcmp(_argv[0],ls) 0){_argv[_argc] --color;_argv[_argc] NULL;}return 0;
}4. 主函数逻辑及演示
这里我们全部都封装起来了各个模块解耦想要修改的话也很方便完整的代码可以去仓库里面查看。
#define LINE_SIZE 1024
#define ARGC_SIZE 32int main()
{while(!quit){//交互 获取命令行interact(commandline,sizeof(commandline));//解析命令行int argc splitString(commandline,argv);if(argc 0) continue;//for(int i0;argv[i];i) printf(%s\n,argv[i]);//printf(%s\n,argv);//普通命令执行int flag buildCommand(argv,argc);if(!flag) normalExcute(argv);}return 0;
}所以我们每次登录的时候界面会显示这些信息其实就是因为系统启动了一个shell进程。