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)

相关推荐
黑客老李2 分钟前
区块链 智能合约安全 | 回滚攻击
服务器·数据仓库·hive·hadoop·区块链·php·智能合约
不知 不知24 分钟前
最新-CentOS 7 基于1 Panel面板安装 JumpServer 堡垒机
linux·运维·服务器·centos
BUG 40432 分钟前
Linux--运维
linux·运维·服务器
千航@abc38 分钟前
vim在末行模式下的删除功能
linux·编辑器·vim
MXsoft6181 小时前
华为E9000刀箱服务器监控指标解读
大数据·运维
贾贾20231 小时前
配电网的自动化和智能化水平介绍
运维·笔记·科技·自动化·能源·制造·智能硬件
九月十九2 小时前
AviatorScript用法
java·服务器·前端
发光小北2 小时前
关于六通道串口服务器详细讲解
运维·硬件工程
jcrose25802 小时前
Ubuntu二进制部署K8S 1.29.2
linux·ubuntu·kubernetes
爱辉弟啦2 小时前
Windows FileZila Server共享电脑文件夹 映射21端口外网连接
linux·windows·mac·共享电脑文件夹