Linux minishell的简单实现

shell:命令行解释器,捕捉用户输入,根据输入的信息运行指定的命令程序。

利用进程终止,等待,替换既可以完成简单的minishell,我们分析一下shell的功能就是捕捉用户输入,对用户输入进行处理,进行程序替换,进程等待防止出现僵尸进程。

1. 捕捉用户输入

捕捉输入吗scanf_s就好了呀,不行!scanf_s遇到空格就停止了,gest(char * buf);从标准输入读取一行数据" pwd ..";

2.字符串解析

得到命令名称和运行参数” pwd  .. “ 把他放到argv数组里面去

3.创建子进程

创建子进程给子进程进行程序替换,并设置运行参数 因为是bin目录下的那些程序所以选择esec函数簇里面的execvp(argv[ 0 ],argv)

不能直接对shell进行替换,因为替换后运行完新的程序进程就退出了,如果替换了shell,shell运行完就会退出,万一要是运行的指令崩溃了shell也就崩溃了,因此要创建子进程让子进程运行指令

我们来看看为啥替换完新的进程原先进程就退出了

这里实现两端代码

example:

#include<stdio.h>

//程序是有运行参数和环境变量的
//程序的运行参数在给予的时候是运行程序一空格间隔跟在程序之后的
//程序的运行参数,就会被保存在argc这个字符数组中
//程序的环境变量,就会保存在env这个字符数组中,或者有个全局变量environ
int main(int argc, char *argv[], char *env[])
{
      extern char **environ;
      printf("程序参数个数: %d \n",argc);
      printf("程序运行参数: \n");
      for(int i = 0;argv[i] != NULL;i++)
      {
           printf("\t %s \n",argv[i]);
      }

      printf("程序的环境变量: \n");
      for(int i = 0;environ[i] != NULL;i++)
      {
        printf("\t %s \n",environ[i]);
      }
      return 0;
}

和一段exec.c来验证 

#include<unistd.h>
#include<stdio.h>

int main()
{
    extern char **environ;
    
    printf("hello !\n ");

    char *argv [] = {"./example" ,"-a" , "-l" , "-c", NULL };
    execve("./example", argv, environ);//程序替换
    printf("can you see me ?");
}

我们能看见can you see me ? 吗

 

是看不见的 ,所以是为啥要fork一个子进程

 

4.进程等待

防止子进程运行完指令退出后成为僵尸进程

5.代码实现

int main()
{
     while(1)
     {
       //字符串捕捉
       printf("[username@hostname]$ ");
       fflush(stdout);
       char input[1024] = {0};
       fgets(input,1023,stdin);
       input[strlen(input) - 1] = '\0';

       printf("[%s]\n",input);

       //字符串解析(把指令能拿出来)
       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 != ' ')
            {
              ptr++;
            }
            *ptr = '\0';
            ptr++;
       }
       argv[argc] = NULL;
       for(int i = 0;argv[i] != NULL;i++)
       {
            printf("[%s]\n",argv[i]);
       }

       //子进程替换
       int pid = fork();
       if(pid == 0)
       {
         execvp(argv[0],argv);
         exit(-1);//替换失败就退出不要接管成第二个shell
       }
       wait(NULL);//进程等待
     }
     return 0;
}

结果展示

应用进程控制实现简单的shell

 

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五毛变向.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值