Linux 原来实现一个shell这么容易!(史上最简单详细)

shell实际上是一个命令的解释程序,是一个用户与系统内核沟通的桥梁。那我们能不能通过代码自己实现一个shell呢?当然可以,看完这篇博文,我相信你会受益匪浅!

通常情况下,我们linux系统默认的shell是bash,下面是bash的工作流程:
Linux 原来实现一个shell这么容易!(史上最简单详细)_第1张图片
总结有以下四步骤:

  1. 等待用户标准输入
  2. 对输入的信息进行读取和解析,得到命令名称及命令运行所需要的参数
  3. 创建子进程,在子进程中进行程序替换,让子进程去运行读取解析后的指定命令
  4. 父进程等待子进程的退出

1、等待用户标准输入

#include 
#include 
#include 
#include 

 int main()
 {
     
     //1、等待标准输入
     char buf[1024] = {
      0 };
     fgets(buf, 1023, stdin);//将输入的数据放在buf中
     buf[strlen(buf) - 1] = '\0';//将最后一个换行取消
     printf("buf:[%s]\n", buf);
     //2、对输入数据进行读取解析
     //3、创建子进程,在子进程中进行程序替换
     //4、父进程进程等待
     return 0;
 }

运行结果:
在这里插入图片描述
我们已经获取到了用户输入的命令参数,并且存到了字符数组buf中

2、读取解析buf中的命令

	//2、对输入数据进行读取解析
    char *argv[32] = {
     NULL};
    int argc = 0;
    char *ptr = buf;
    // [   ls     -a    -l   ]
    while (*ptr != '\0')
    {
               
     	if (*ptr != ' ')
         {
     
             argv[argc++] = ptr;
             while (*ptr != ' ' && *ptr != '\0')
             {
     
                 ptr++;
             }
             *ptr = '\0';
         }
          ptr++;
     }
     argv[argc] = NULL;//最后一个参数位置的下一个位置置NULL

从buf存到指针数组argv中
Linux 原来实现一个shell这么容易!(史上最简单详细)_第2张图片

3、创建子进程,在子进程中进行程序替换

	//3、创建子进程,在子进程中进行程序替换
     pid_t pid = fork();
     if (pid == 0)//子进程
     {
     
          execvp(argv[0],argv);//程序替换成功就不会执行下面代码,而去执行新的程序
          perror("execvp error");//程序替换失败时会打印上一次系统调用接口使用的错误原因
          exit(0);
     }

4、父进程进行进程等待

wait(NULL);

完整代码:

#include 
#include 
#include 
#include 

int main()
{
     
	while (1)
	{
     
		printf("[WhiteShirtI@shell workspace]$ ");
		fflush(stdout);//刷新标准输出缓冲区
		
		//1、等待标准输入
		char buf[1023] = {
     0};
		fgets(buf, 1023, stdin); //将输入存放到buf中
		buf[strlen(buf) - 1] = '\0';//将最后一个换行取消
		
		//2、对输入数据进行读取和解析
		char *argv[32] = {
      NULL };
		int argc = 0;
		char *ptr = buf;
		//遍历命令和参数,不为空就继续遍历
		while (*ptr != '\0')
		{
     
			//遇到命令或者参数
			if (*ptr != ' ')
			{
     
				//让agv第argc的位置放ptr这个指针
				argv[argc++] = ptr;
				while (*ptr != ' ' && *ptr != '\0')
				{
     
					ptr++;
				}
				//一个命令或参数的结束标志
				*ptr = '\0';
			}
			ptr++;
		}
		argv[argc] = NULL;//最后一个参数位置的下一个位置置为NULL
		//3、创建子进程,在子进程中进行程序替换
		pid_t pid = fork();
		if (pid == 0) //子进程
		{
     
			//execvp(命令名称, 命令参数)
			execvp(argv[0], argv);//程序替换成功不会执行下面代码
			perror("execvp error");//打印上一次系统调用接口使用的错误原因
			exit(0);
		}
		//4、父进程进行进程等待
		wait(NULL);
	}
	return 0;
}

运行测试:
Linux 原来实现一个shell这么容易!(史上最简单详细)_第3张图片
Linux 原来实现一个shell这么容易!(史上最简单详细)_第4张图片
如果觉得这篇博客对你有用记得一键三连哦!!!

你可能感兴趣的:(Linux,linux)