<Linux>简单的shell解释器

目录

 一、命令分割

二、fork()创建子进程

三、全部代码


shell解释器:

就像下面Centos的环境下的命令行,可以解析我们输入的指令来达到运行不同功能的实现;

shelll条件:

必须是永不退出的,常驻内存的,我们使用死循环来解决;

输入的命令又指令和指令选项:ls -a -l,我们使用命令分割来进行区分

命令分割后解析需要子进程来运行解析后的指令对应的进程,这里需要运行其他进程,但是又不能影响父进程,我们创建子进程用execvp进行程序替换,来实现运行不同指令的效果;

 一、命令分割

我们需要将输入的指令和选项分割开,方便我们来解析指令;

 这里我们采用了字符串函数strtok()来分割

         g_argv[0] = strtok(cmd_line,  SEP);//第一次调用,传入原始字符串
         int index = 1;
         if (strcmp(g_argv[0], "ls") == 0)
         {
               g_argv[index++] = "--color=auto";
         }
         while(g_argv[index++] = strtok(NULL, SEP));//第二次调用,如果还要解析,传入NUL

二、fork()创建子进程

将命令解析后,创建子进程使用execvp()替换函数,来进行程序替换,实现功能;

这时的父进程只需要等待子进程正常退出即可;

   64         //5.fork();
   65         pid_t id = fork();
   66         if (id == 0)// child
   67         {
   68             printf("功能子进程执行\n");
   69             // cd 只影响当前的进程 
   70             execvp(g_argv[0], g_argv);//ls -a -l
   71             exit(-1);
   72         }
   73         
   74         // father 
   75         int status = 0;
   76         pid_t ret = waitpid(id, &status, 0);
   77         if (ret > 0)
   78         {
   79             printf("exit code:%d\n", WEXITSTATUS(status));
   80         }

三、全部代码

    1 #include <stdio.h>                                                                                                                                                     
    2 #include <stdlib.h>
    3 #include <string.h>
    4 #include <unistd.h>
    5 #include <sys/wait.h>
    6 #include <sys/types.h>
    7 
    8 #define NUM 1024
    9 #define SIZE 32
   10 #define SEP " "
   11 
   12 //保存打散之后的命令行 字符串
   13 char *g_argv[SIZE];
   14 //保存完成的命令行
   15 char cmd_line[NUM];
   16 
   17 //shell运行原理 
   18 //通过让子进程执行命令,父进程等待&&解析命令
   19 int main()
   20 {
   21     //0.命令行解释器, 一定是一个常驻内存进程,不退出
   22     while (1)
   23     {
   24         //1.打印提示信息
   25         // [mr@localhost myshell]#
   26         printf("[my@localhost myshell]#");
   27         fflush(stdout);
   28         memset(cmd_line, '\0', sizeof cmd_line);
   29         //2.获取用户键盘输入的各种指令和选项: “ls -a -l”
   30         if (fgets(cmd_line, sizeof cmd_line, stdin) == NULL)
   31         {
   32             continue;
   33         }
   34         cmd_line[strlen(cmd_line) - 1] = '\0';
   35 
   36         //printf("echo:%s\n", cmd_line);
   37         
   38         //3.命令行字符串解析 
   39         g_argv[0] = strtok(cmd_line,  SEP);//第一次调用,传入原始字符串
   40         int index = 1;
   41         if (strcmp(g_argv[0], "ls") == 0)
   42         {
   43             g_argv[index++] = "--color=auto";
   44         }
   45         while(g_argv[index++] = strtok(NULL, SEP));//第二次调用,如果还要解析,传入NUL 
   46  
   47 //         for (index = 0; g_argv[index]; index++)
   48 //        {
   49 //             printf("g_argv[%d]:%s\n",index,g_argv[index]);
   50 //         }
   51         //4.TODO 内置命令 :让父进程(shell)自己执行命令,叫做内置命令,内建命令
   52         //内建命令本质就是shell中的一个函数调用
   53         if (strcmp(g_argv[0], "cd") == 0) //not child excute, father excute
   54         {
   55             if(g_argv[1] != NULL)
   56             {
   57                 chdir(g_argv[1]);
   58 
   59                 continue;
   60             }
   61         }
   62         
   63 
   64         //5.fork();
   65         pid_t id = fork();
   66         if (id == 0)// child
   67         {
   68             printf("功能子进程执行\n");
   69             // cd 只影响当前的进程 
   70             execvp(g_argv[0], g_argv);//ls -a -l
   71             exit(-1);
   72         }
   73         
   74         // father 
   75         int status = 0;
   76         pid_t ret = waitpid(id, &status, 0);
   77         if (ret > 0)
   78         {
   79             printf("exit code:%d\n", WEXITSTATUS(status));
   80         }
   81     }
   82 
   83     return 0;
   84 }                                                                 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

绅士·永

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

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

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

打赏作者

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

抵扣说明:

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

余额充值