1.shell简介
shell是命令行解释器,功能就是捕捉用户的输入,然后根据输入的信息运行指定的命令程序。
2.逻辑实现过程
(1)捕捉用户输入
(2)字符串解析,得到命令名称和运行参数
(3)创建子进程,并对子进程进行程序替换,设置运行参数
(4)进程等待,防止子进程成为僵尸进程
(5)循环上述操作
3.实现思路
(1)捕捉用户输入
通过fgets函数读取用户输入保存到input字符数组中。
注意:用户输入可能夹带空格,不能使用scanf函数进行输入捕捉。
(2)字符串解析,得到命令名称和运行参数
通过指针数组argv保存每一个操作或选项的字符首地址,并将每个操作或选项的末尾的下一个字符替换为'\0'。
注意:argv末尾位置需要替换为NULL,以空作为参数结尾
(3)创建子进程,并对子进程进行程序替换,设置运行参数
通过pid对父子进程进行分流,利用execvp函数对子进程进行程序替换,让子进程运行对应的指令程序。
注意:不能直接对minishell进行替换,因为替换后运行完新程序,进程就会退出;并且如果替换了minishell,在运行某个指令程序时崩溃,minishell也就崩溃了。因此需要创建子进程,通过子进程来运行指令程序。
(4)进程等待,防止子进程成为僵尸进程
通过wait方法,让父进程等待子进程运行完毕退出,防止子进程成为僵尸进程。
(5)循环上述操作
利用while循环进行上述操作。
4.代码实现
#include<stdio.h> #include<unistd.h> #include<string.h> #include<stdlib.h> #include<sys/wait.h> int main(){ extern char** environ;//声明环境变量 while(1){ //1.捕捉用户输入 printf("[username&hostname]$ "); fflush(stdout);//刷新缓冲区 char input[1024]={0}; fgets(input,1023,stdin);//从标准输入读取一行数据,数据不能大于1023字节 input[strlen(input)-1]='\0';//将最后一个字符换为\0 //2.字符串解析 char* ptr=input; char* argv[32]={NULL}; int argc=0; while(*ptr!='\0'){ if(*ptr==' '){//查找第一个指令字符 ptr++; continue; } argv[argc]=ptr;//保存指令地址 argc++; while(*ptr!='\0'&&*ptr!=' '){//将末尾的下一个位置替换为'\o' ptr++; } *ptr='\0'; ptr++; } argv[argc]=NULL;//以空作为参数结尾 //3.创建子进程,进行程序替换 pid_t pid=fork(); if(pid==0){//子进程 execvp(argv[0],argv); exit(-1);//替换失败则退出子进程,否则子进程会成为第二个minishel } wait(NULL);//等待子进程退出 } return 0; }
5.测试用例及结果
测试用例1:“ ls -a"
测试结果:
测试用例2:”ls -l “
测试结果:
测试用例3:”pwd"
测试结果: