shell的命令行设计其中包含用户名,系统,当前所处的文件夹这些信息我们可以从环境变量里面筛选得到使用getenv获取,在封装为函数,获取我们想要的信息变成函数提取出去void PrintCommmandLine() { printf([%s%s %s]#, GetUSER(), GetHOSTNAME(), GetPWD()); fflush(stdout); }现在我们暂且让路径是这个样子获取用户输入,我们接下来再看ls -l -a首先我们要将输入的命令,进行解析按照空变成-ls -l -a. strtok函数在这里很有用要选择什么来进行输入呢??scanf??-scanf是以空格作为分割符,在这里显然不太合适这里我推荐使用fgetschar *fgets(char *str, int n, FILE *stream);剔除换行但是我们发现这里会多了一些不必要的换行.因为我们每一次输入的结尾一定会按了一下enter也就是换行所以我们这里要将command_line的末尾用\0来代替if( fgets(command_line,sizeof(command_line),stdin)NULL) continue; command_line[strlen(command_line)-1]\0;在变成函数命令行解析strtok 详解实现子串一变多,根据自己设定的分割符char *strtok(char *str, const char *delim);str待分割的字符串delim分隔符集合返回值分割成功返回当前分割出来的子串首地址分割完毕返回NULL那怎么获得全部呢strtok第一次调用第一个参数传入待分割字符串数组找到第一个分隔符将分隔符改成\0返回第一段字符串首地址找不到分隔符直接返回整个字符串首地址后续循环调用第一个参数必须传NULL从上次停下的位置继续向后查找分隔符找到就返回下一段地址再也找不到任何片段时返回 NULLstrtok在命令解析的使用执行任务我们不让父进程执行,要让子进程来执行,一但让父进程来执行进程就会退出我们的命令行操作根据我们之前讲命令行是放在数组里面的,这里我们要使用的程序替换函数使用带v的比较好void ExecuteCommand() { pid_t idfork(); if(id0) { //创建子进程失败 perror(fork); } else if(id0) { //child extern char** environ; execvpe(margv[0],margv,environ); perror(execvp fail); exit(0); } else{ //parent int status0; pid_t ridwaitpid(id,status,0); if(rid0) { printf(wait success\n); } else { perror(waitpid); } } }我们通过上面的实践发现可以完成很多的命令操作了存在问题但是像是一些内建命令还是没有办法实现还有之前的遗留问题,这里应该只有myshell解决相应的问题解决cd的问题首先cd命令应该要由父进程执行,如果让子进程执行,他结束后不会和父进程同步更新解决工作目录打印的问题查看envcd回到家目录再次查看时现象说明启动 myshell环境变量PWD/xxx/Myshell执行cd→chdir()成功内核目录切换到家目录但是代码没有更新环境变量 PWD内存里依然保留旧值执行外部命令pwd系统pwd命令优先读取环境变量 PWD打印旧路径此时我们发现环境变量不会自主更新,所以我们要自己来更新pwd,通过cd时来更新解决部分echo内建命令定义全局变量,将退出码记录出来,要在父进程执行或者子进程执行时即使更新退出码对于子进程,我们让父进程waitpid来获得子进程的退出码父进程自己来来更新退出码获取环境变量
linux之进程管理--自主shell
shell的命令行设计其中包含用户名,系统,当前所处的文件夹这些信息我们可以从环境变量里面筛选得到使用getenv获取,在封装为函数,获取我们想要的信息变成函数提取出去void PrintCommmandLine() { printf([%s%s %s]#, GetUSER(), GetHOSTNAME(), GetPWD()); fflush(stdout); }现在我们暂且让路径是这个样子获取用户输入,我们接下来再看ls -l -a首先我们要将输入的命令,进行解析按照空变成-ls -l -a. strtok函数在这里很有用要选择什么来进行输入呢??scanf??-scanf是以空格作为分割符,在这里显然不太合适这里我推荐使用fgetschar *fgets(char *str, int n, FILE *stream);剔除换行但是我们发现这里会多了一些不必要的换行.因为我们每一次输入的结尾一定会按了一下enter也就是换行所以我们这里要将command_line的末尾用\0来代替if( fgets(command_line,sizeof(command_line),stdin)NULL) continue; command_line[strlen(command_line)-1]\0;在变成函数命令行解析strtok 详解实现子串一变多,根据自己设定的分割符char *strtok(char *str, const char *delim);str待分割的字符串delim分隔符集合返回值分割成功返回当前分割出来的子串首地址分割完毕返回NULL那怎么获得全部呢strtok第一次调用第一个参数传入待分割字符串数组找到第一个分隔符将分隔符改成\0返回第一段字符串首地址找不到分隔符直接返回整个字符串首地址后续循环调用第一个参数必须传NULL从上次停下的位置继续向后查找分隔符找到就返回下一段地址再也找不到任何片段时返回 NULLstrtok在命令解析的使用执行任务我们不让父进程执行,要让子进程来执行,一但让父进程来执行进程就会退出我们的命令行操作根据我们之前讲命令行是放在数组里面的,这里我们要使用的程序替换函数使用带v的比较好void ExecuteCommand() { pid_t idfork(); if(id0) { //创建子进程失败 perror(fork); } else if(id0) { //child extern char** environ; execvpe(margv[0],margv,environ); perror(execvp fail); exit(0); } else{ //parent int status0; pid_t ridwaitpid(id,status,0); if(rid0) { printf(wait success\n); } else { perror(waitpid); } } }我们通过上面的实践发现可以完成很多的命令操作了存在问题但是像是一些内建命令还是没有办法实现还有之前的遗留问题,这里应该只有myshell解决相应的问题解决cd的问题首先cd命令应该要由父进程执行,如果让子进程执行,他结束后不会和父进程同步更新解决工作目录打印的问题查看envcd回到家目录再次查看时现象说明启动 myshell环境变量PWD/xxx/Myshell执行cd→chdir()成功内核目录切换到家目录但是代码没有更新环境变量 PWD内存里依然保留旧值执行外部命令pwd系统pwd命令优先读取环境变量 PWD打印旧路径此时我们发现环境变量不会自主更新,所以我们要自己来更新pwd,通过cd时来更新解决部分echo内建命令定义全局变量,将退出码记录出来,要在父进程执行或者子进程执行时即使更新退出码对于子进程,我们让父进程waitpid来获得子进程的退出码父进程自己来来更新退出码获取环境变量