Linux:minishell

目录

1.实现逻辑

2.代码及效果展示

1.打印字符串提示用户输入指令

2.父进程拆解指令

3.子进程执行指令,父进程等待结果

4.效果

3.实现过程中遇到的问题

1.打印字符串的时候不显示

2.多换了一行

3.cd路径无效

4.优化

1.ll指令

2.给文件或目录加上颜色

代码链接


模拟实现shell程序

所用知识

1.基础的C语言知识,fgets,fflush(刷新缓冲区)

2.字符串相关的函数:strtok

3.进程的创建(fork)进程的等待(waitpid) 进程的替换(exec*函数) 进程的终止(exit)

shell运行原理

父进程等待&&解析指令,子进程执行指令

1.实现逻辑

shell需要一直等待用户输入指令,然后执行指令,因此写一个死循环

1.打印出字符串"[zy@localhost myshell]# "提示用户输入信息

--使用fflush刷新缓冲区

2.父进程分析指令

--定义一个字符数组cmd来存放完整的指令(使用fgets函数,将命令读取到字符数组cmd中)

--定义一个字符指针数组来存放拆解后的指令(使用strtok函数,将其拆解)

--创建子进程执行指令,然后阻塞等待执行的结果

3.子进程执行指令

--调用execvp函数,执行拆解好的指令

2.代码及效果展示

--预备工作

--定义一个字符数组cmd来存放完整的指令(使用fgets函数,将命令读取到字符数组cmd中)

--定义一个字符指针数组来存放拆解后的指令(使用strtok函数,将其拆解)

--定义一个分割符(使用#define定义SEP为空格)

1.打印字符串提示用户输入指令

复制代码
 19     //1.打印字符串,提示用户输入指令                                                                                                        
 20     printf("[zy@localhost myshell]# ");                                                                                                    
 21     fflush(stdout);                                                                                                                        
 22     memset(cmd,'\0',sizeof(cmd));//初始化                                                                                                  
 23                                                                                                                                            
 24     if(fgets(cmd,sizeof(cmd),stdin)==NULL) continue;//读取用户输入的指令,若输入为NULL直接跳过                                             
 25     cmd[strlen(cmd)-1] = '\0';//由于是从键盘读取,会读取到\n,我们将其置为\0 

--fflush是用来刷新缓冲区的

--memset将cmd数组初始化,也清除了上一次输入的指令

--fgets函数:参数:char *str,int num ,FILE* stream

1.存储从输入流中读取的字符串 2.读取的最大字符数 3.从那读

2.父进程拆解指令

代码:

复制代码
 27     //2.拆解指令,放进g_argv中,后面调用execvp的时候直接传递                                                                                      
 28     int index = 0;                                                                                                                              
 29     g_argv[index++] = strtok(cmd,SEP);                                                                                                          
 30     while(g_argv[index++]=strtok(NULL,SEP)); 

--strtok:参数:char* str , const char * strDelimit (要分割的字符串,用来分割的字符)

第一次调用后,下一次还要继续分割这个字符,传递NULL即可,它会记录分割点的位置

3.子进程执行指令,父进程等待结果

4.效果

3.实现过程中遇到的问题

1.打印字符串的时候不显示

字符串不显示

使用fflush,刷新缓冲区即可

效果:

2.多换了一行

代码:

这里可以看到多换了一行

原因:fgets从键盘读取数据会把\n也读进cmd中,我们需要把\n置为'\0'

方法:cmd[strlen(cmd)-1] = '\0'; strlen遇到\0就不在计数了,通过其找到'\n'的位置

效果:

3.cd路径无效

原因

1.子进程是父进程的一份拷贝,直接用pwd显示的路径就是父进程的路径

2.如果使用cd指令,exec函数执行完就退出了,再执行pwd就是重新调用,父进程会生成一个新的子进程, 显示的是父进程的路径

解决:加一个判断,如果是cd命令,直接使用chdir改变当前父进程的路径

复制代码
   33     if(strcmp(g_argv[0],"cd")==0)//特殊处理一下cd指令
   34     {
   35       if(g_argv[1]!=NULL) chdir(g_argv[1]); 
   36       continue;
   37     }

解决:

4.优化

1.ll指令

解决:特殊处理一下

复制代码
   32     if(strcmp(g_argv[0],"ll")==0)//特殊处理一下ll指令
   33     {
   34       g_argv[0] = (char*)"ls";
   35       g_argv[index++] = (char*)"-l";                                                                                                                              
   36     }

原来:

解决:

2.给文件或目录加上颜色

思路:特殊处理

这是ls加上颜色的指令:

代码:

复制代码
   32     if(strcmp(g_argv[0],"ls")==0)//特殊处理ls指令,为其加上颜色
   33     {
   34       g_argv[index++] = (char*)"--color=auto";
   35     }
   36 
   37     if(strcmp(g_argv[0],"ll")==0)//特殊处理ll指令
   38     {
   39       g_argv[0] = (char*)"ls";
   40       g_argv[index++] = (char*)"--color=auto";
   41       g_argv[index++] = (char*)"-l";

效果:

代码链接

链接:myshell · 朱垚/C++与Linux实例 - 码云 - 开源中国 (gitee.com)

相关推荐
yuanpan38 分钟前
ubuntu系统上的conda虚拟环境导出方便下次安装
linux·ubuntu·conda
云边云科技1 小时前
零售行业新店网络零接触部署场景下,如何选择SDWAN
运维·服务器·网络·人工智能·安全·边缘计算·零售
城管不管1 小时前
Docker核心---数据卷(堵门秘籍)
运维·docker·容器
AOwhisky1 小时前
Linux 文本处理三剑客:awk、grep、sed 完全指南
linux·运维·服务器·网络·云计算·运维开发
Gavin_9152 小时前
从零开始部署经典开源项目管理系统最新版redmine6-Linux Debian12
linux·ruby on rails·开源·debian·ruby·redmine
xuanerya2 小时前
使用 SSH 方式克隆 GitHub 仓库没有权限解决办法
运维·ssh·github
花小璇学linux2 小时前
imx6ull-驱动开发篇31——Linux异步通知
linux·驱动开发·嵌入式软件
shelutai2 小时前
ubuntu 编译ffmpeg6.1 增加drawtext,libx264,libx265等
linux·ubuntu·ffmpeg
runfarther3 小时前
搭建LLaMA-Factory环境
linux·运维·服务器·python·自然语言处理·ai编程·llama-factory
百思可瑞教育3 小时前
Spring Cloud Gateway 负载均衡全面指南
运维·负载均衡·北京百思可瑞教育·百思可瑞教育·北京百思教育