shell:命令行解释器,是一段程序,获取标准输入,进行解析,得到用户想要运行的shell命令程序名称,以及运行参数,然后运行这个指定的程序,将参数赋予其中。
simple_shell编写思路:
- 获取标准输入,得到用户输入的字符串
gets从标准输入获取一行数据 - 对输入的数据进行解析,得到指令程序名称以及运行参数
按照空格对字符串进行分割,定义一个字符串指针,指向输入数据的起始位置,如果是空格,指针就往后移动,直到不是空格,然后将非空格走完,直到遇到空格为止,则认为这次的字符串结束,将这个空格位置置为’\0’,则认为第一个字符串到此为止,以此往下循环… - 创建子进程,让子进程运行这个指定命令
fork()==0{execl()} - 避免产生僵尸进程,因此进行进程等待
wait(NULL); - 代码实现:
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/wait.h>
int main()
{
while(1)
{
printf("[zhengbinbin@localhost]# ");
fflush(stdout);//刷新标准输出缓冲区
char buf[1024] = {0};
fgets(buf,1023,stdin);//从标准输入读取一行数据
buf[strlen(buf)-1] = '\0';//将最后的换行符替换为字符串结尾标志
printf("buf:[%s]\n",buf);
char* ptr = buf;
char* argv[32] = {NULL};
int argc = 0;
while(*ptr != '\0')
{
if(*ptr != ' ')//每个子字符串的起始位置
{
argv[argc] = ptr;//刚进来是第0个子串的起始位置,++后是第2、第3.....个子串的起始位置
argc++;
while(*ptr != ' ' && *ptr != '\0')
{
ptr++;
}
*ptr = '\0';
}
ptr++;
}
argv[argc] = NULL;//参数以NULL作为结尾
pid_t pid =fork();
if(pid == 0)
{
//复制了父进程,因此也有自己的argc/argv
//子进程运行新的程序,使用程序替换
//当前运行的程序都是在PATH环境变量指定的路径下的程序,不需要指定路径,因此用带p的exec函数
//因为有字符串指针数组,因此用v
execvp(argv[0],argv);
printf("%s command not found\n",argv[0]);
//走到这里说明程序替换失败了
exit(-1);
}
wait(NULL);//等待子进程退出,避免子进程成为僵尸进程
}
return 0;
}