Linux之简单的Shell命令行解释器


风晓
风晓 2024-01-10 17:58:10 62797 赞同 0 反对 0
分类: 资源
Linux之简单的Shell命令行解释器

我们前面学习了进程创建,进程终止,进程等待,进程替换,通过这些内容我们可以来进行实现简单的shell命令行解释器。下面我们直接来看一看如何去实现shell命令行解释器。

一、基本原理


1、我们知道,在打开shell解释器后,除非我们自己关闭它,那么它将一直不退出,所以命令行解释器一定是一个死循环。

2、输入:我们需要获取命令行上一行的内容,利用fgets函数获取,同时,可以定义一个cmd_line[NUM]数组来保存用户输入的内容。

3、解析:输入之后,我们自然需要去进行字符串的解析,我们需要分割字符串,将其分成命令+选项等内容,这个地方用strtok函数,把字符串切割成若干个子串,并将分开的各个子串保存至char* g_val[SIZE]数组中。strtok:第一次直接传递参数,第二次则必须传NULL。且在最终strtok会返回NULL。

4、我们在输入命令后,发现界面还是维持的原样,这是因为父进程会创建子进程去帮助其实现命令,同时父进程需要等待子进程退出返回结果。

5、子进程在执行命令的时候,我们需要使用进程替换的知识,将代码换成命令执行的代码。

6、有些命令,如cd命令,如果我们是交给子进程去完成的话,只会改变子进程的路径,所以cd命令必须由父进程亲自来完成。

不需要创建子进程执行,让shell自己执行命令,称为内建命令。本质就是执行系统接口,我们可以调用一个系统接口chdir,可以让父进程自己改变路径。

7、我们在输入完命令后,通常会按回车建使其执行,而fgets则会将它当成输入的一个字符,在给用户呈现结果时会多换一行,而不会紧挨着上一行去显示结果。所以我们要执行下面的操作:

cmd_line[strlen(line_cmd)-1] = '\0';
8、再比如,像ll这种命令,其等效于ls -l,因此我们需要将其在数组char* g_val[SIZE]中换成 g_val[0] = "ls",g_val[1] = "-l"即可。

二、代码实现
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<unistd.h>
 
#define NUM 32
#define SIZE 1024
#define SEP " "
char cmd_line[NUM];//存放输入的字符串
char* g_val[SIZE];//存放解析出来的字符串
 
int main()
{
    //命令行解释器是一个不退出的进程
    while(1)
    {
       printf("[zdl@hcss-ecs-d14f ~]# ");
       fflush(stdout);
       memset(cmd_line, '\0', sizeof(cmd_line));
 
       if(fgets(cmd_line,sizeof(cmd_line),stdin) == NULL)
       {
           continue;
       }
       cmd_line[strlen(cmd_line)-1] = '\0';
 
       //命令行字符解析
       g_val[0] = strtok(cmd_line, SEP);
       int index = 1;
       if(strcmp(g_val[0],"ll")==0)
       {
           g_val[0]="ls";
           g_val[index++]="-l";
       }
       while(g_val[index++] = strtok(NULL, SEP));//如果还解析原字符串,就传入NULL
       
       //让父进程执行的命令叫做内置命令
       if(strcmp(g_val[0], "cd")==0)
       {
           if(g_val[1] != NULL)
               chdir(g_val[1]);
 
           continue;
       }
 
       //创建子进程去执行
       pid_t id = fork();
       if(id==0)
       {
           execvp(g_val[0], g_val);
           exit(1);
       }
 
       //父进程
       int status = 0;
       pid_t ret = waitpid(id, &status,0);
       if(ret > 0)
       {
           printf("exit code: %d\n",WEXITSTATUS(status));
       }
    }
 
    return 0;
}

如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!

评价 0 条
风晓L1
粉丝 1 资源 2038 + 关注 私信
最近热门资源
分享如何在银河麒麟高级服务器操作系统V10SP3中需要启用内核审计功能。  176
分享免费开源高速下载器  171
一图对比分析IPv4与IPv6  167
统信uos家庭版与专业版的选择  166
分享如何查看网卡中断的数量  163
解决银河麒麟无法添加惠普打印机,提示'client-error-not-possible'.”错误  162
winrar绿色无广告版分享  154
通过shell脚本在统信UOS/麒麟系统中安装nginx  145
分享在麒麟系统中关闭占用端口的进程的办法  142
统信UOS常见问题小总结  142
最近下载排行榜
分享如何在银河麒麟高级服务器操作系统V10SP3中需要启用内核审计功能。 0
分享免费开源高速下载器 0
一图对比分析IPv4与IPv6 0
统信uos家庭版与专业版的选择 0
分享如何查看网卡中断的数量 0
解决银河麒麟无法添加惠普打印机,提示'client-error-not-possible'.”错误 0
winrar绿色无广告版分享 0
通过shell脚本在统信UOS/麒麟系统中安装nginx 0
分享在麒麟系统中关闭占用端口的进程的办法 0
统信UOS常见问题小总结 0
作者收入月榜
1

prtyaa 收益395.97元

2

zlj141319 收益228.47元

3

IT-feng 收益214.92元

4

1843880570 收益214.2元

5

风晓 收益208.24元

6

777 收益173.02元

7

哆啦漫漫喵 收益131.6元

8

Fhawking 收益106.6元

9

信创来了 收益105.97元

10

克里斯蒂亚诺诺 收益91.08元

请使用微信扫码

加入交流群

请使用微信扫一扫!