Linux实现简易版的shell

本文介绍了早期计算机中图形界面未普及时期,用户如何通过Shell这一命令行解释器与操作系统内核交互。Shell作为用户和内核之间的代理,接收用户输入的命令,解析并执行。文章通过一个简单的minishell代码示例,阐述了Shell的工作流程,包括捕捉键盘输入、解析命令、创建子进程和执行命令。
摘要由CSDN通过智能技术生成

什么是shell

现在我们使用的操作系统(Windows、Mac OS、Android、iOS等)都是带图形界面的,简单直观,容易上手,对专业用户(程序员、网管等)和普通用户(家庭主妇、老年人等)都非常适用;计算机的普及离不开图形界面。

然而在计算机的早期并没有图形界面,我们只能通过一个一个地命令来控制计算机,这些命令有成百上千之多,且不说记住这些命令非常困难,每天面对没有任何色彩的“黑屏”本身就是一件枯燥的事情;这个时候的计算机还远远谈不上炫酷和普及,只有专业人员才能使用。

对于图形界面,用户点击某个图标就能启动某个程序;对于命令行,用户输入某个程序的名字(可以看做一个命令)就能启动某个程序。这两者的基本过程都是类似的,都需要查找程序在硬盘上的安装位置,然后将它们加载到内存运行。换句话说,图形界面和命令行要达到的目的是一样的,都是让用户控制计算机。然而,真正能够控制计算机硬件(CPU、内存、显示器等)的只有操作系统内核,图形界面和命令行只是架设在用户和内核之间的一座桥梁。

由于安全、复杂、繁琐等原因,用户不能直接接触内核(也没有必要),需要另外再开发一个程序,让用户直接使用这个程序;该程序的作用就是接收用户的操作(点击图标、输入命令),并进行简单的处理,然后再传递给内核。如此一来,用户和内核之间就多了一层“代理”,这层“代理”既简化了用户的操作,也保护了内核。
用户界面和命令行就是这个另外开发的程序,就是这层“代理”。在Linux下,这个命令行程序叫做 Shell。

Linux中的shell,是指一个命令行解释器,表现形式就是一个可以由用户录入的界面,这个界面也可以反馈运行信息。

shell的工作流程

在这里插入图片描述综上,要实现一个迷你shell,必须循环以下步骤:
1.捕捉键盘输入
2.解析输入信息–命令名称、运行参数
3.创建子进程
4.子进程执行对应命令名称的程序(失败必须退出)
5.父进程等待子进程退出

minishell代码

#include<stdio.h>                                                                                                                                                   #include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
#include<string.h>
int main()
{
   while(1)
   {
     //捕捉键盘输入
     printf("[user@host path]$ ");
     //fflush(stdout),对标准输出流的清理,但是它并不是把数据丢掉。
     //而是及时地打印数据到屏幕上。
     //标准输出是以行为单位进行的,也即碰到\n才打印数据到屏幕。
     //这就可能造成延时。
     fflush(stdout);
     char buf[1024]={0};
     fgets(buf,1023,stdin);
     buf[strlen(buf)-1]='\0';
     
      //解析键盘输入
      int myargc = 0;
      char* ptr = buf;
      char* myargv[64]={NULL};
      while(*ptr!='\0')
      {
        if (*ptr!=' ')
        {
          myargv[myargc]=ptr;
          myargc++;
          while(*ptr!='\0'&&*ptr!=' ')
          {
           ptr++;
          }
         *ptr='\0';
       }
        ptr++;
      }
      myargv[myargc]=NULL;
      if(strcmp("cd",myargv[0])==0)
      {
       chdir(myargv[1]);
       continue;
      }
      
      //创建子进程
      pid_t pid = fork();
      if(pid<0)
      {
        perror("fork error");
        continue;
      }
      else if (pid==0)
      {
        //子进程执行对于命令名称的程序(程序替换)
        execvp(myargv[0],myargv);
        perror("execvp error");
        exit(-1);
      }
       //父进程等待
        wait(NULL);
    }
    return 0;
}

运行结果

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值