文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

【Linux】shell命令行简单解释器

2023-09-01 17:22

关注


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

总体分为(整体需要循环哦):

1.输出提示符

2.输入和获取命令

3.fork创建子进程

4.内建命令


这里的提示字符为用户名@主机名 当前路径# 直接打印出来作为提示所用,也可以自己设置成其他的,问题不大

printf("用户名@主机名 当前路径# ");

同时,这里并没有\n,会有缓冲区的问题,类似于我们之前所说的进度条所遇到的问题,在这个地方哦可以用fflush(stdout)刷新缓冲区

输入

我们需要获取一行的内容,利用fgets函数获取,同时,可以定义一个lineCommand[NUM]数组

char*s = fgets(lineCommand,sizeof(lineCommand)-1,stdin);assert(s != NULL);

但是打印的时候却多换了一行,这是我们把\n也读取到了,直接进行处理即可,清除最后一个\n

lineCommand[strlen(lineCommand)-1] = 0;       

获取

输入之后,我们自然需要去进行获取,我们需要分割命令行,这个地方用strtok。把字符串切割成若干个子串:

strtok:第一次直接传递参数,第二次则必须传NULL。且在最终strtok会返回NULL。

利用fork创建子进程,同时父进程需要等待子进程退出返回结果

另外我们还需要选择替换函数execvp:首先替换函数需要先带上v,可将所有的执行参数放入数组中统一传递,其次还要选择带上p,我们输入的只有程序命令,带上p会自动在环境变量中寻找

至此,基本的框架我们已经搞定了。

同时,在理解一下shell的运行原理:shell内部提取命令行做分析,然后调用exec. shell执行命令必须通过创建子进程,如果不创建子进程会把我们所有的shell全部替换,所以执行命令时一般磁盘上的程序必须创建子进程

我们在运行自己写的shell的时候,发现输入cd …输入cd path等命令时发现路径并没有改变!

image-20221130111814277

没有发生改变是因为自己写的shell执行很多命令都要fork()创建子进程,让子进程执行的cd,子进程有自己的工作目录,所以更改的子进程的目录,子进程执行完毕,继续用的是父进程,既shell,并没有影响父进程,所以并没有改变。

对于cd,我们可以采用内建命令:不需要创建子进程执行,让shell自己执行命令,称为内建命令。本质就是执行系统接口,我们可以调用一个系统接口chdir,可解决上述问题:

image-20221130142857416

image-20221130142956990

简易shell——代码实现

#include #include #include #include #include #include #include #define NUM 1024#define OPT_NUM 64char lineCommand[NUM];char *myargv[OPT_NUM];int lastCode = 0;int lastSig = 0;int main(){    while(1)    {        //输出提示符        printf("用户名@主机名 当前路径#");        fflush(stdout);        //获取输入        char*s = fgets(lineCommand,sizeof(lineCommand)-1,stdin);        assert(s != NULL);        (void) s;        lineCommand[strlen(lineCommand)-1] = 0;        // printf("test:%s\n",lineCommand);        //ls -a -l -i  字符串切割        myargv[0] = strtok(lineCommand," ");        int i = 1;        if(myargv[0]!= NULL&& strcmp(myargv[0],"ls") == 0)        {            myargv[i++] =(char*)"--color=auto";        }        //如果没有子串,strtok会返回NULL                   while(myargv[i++] = strtok(NULL," "));        //如果是cd命令, 不需要创建子进程,让shell自己执行对应的命令,本质就是执行系统接口        //像这种不需要我们的子进程来执行,而是让shell自己执行的命令 --内建 内置命令        if(myargv[0]!=NULL&& strcmp(myargv[0],"cd")==0)        {            if(myargv[1] != NULL) chdir(myargv[1]);            continue;        }        if(myargv[0]!=NULL&& myargv[1]!=NULL && strcmp(myargv[0],"echo")== 0)        {            if(strcmp(myargv[1],"$?") == 0)                  {                printf("%d %d\n",lastCode,lastSig);            }            else             {                printf("%s\n",myargv[1]);            }              continue;        }        //利用条件编译测试代码是否成功#ifdef DEBUG         for(int i = 0;myargv[i];i++)        {            printf("myargv[%d]:%s\n",i,myargv[i]);        }#endif        //执行命令        pid_t id = fork();        assert(id!=-1);        if(id == 0)        {            execvp(myargv[0],myargv);            exit(1);        }        int status = 0;        pid_t ret = waitpid(id,&status,0);        assert(ret > 0);        (void)ret;        lastCode = ((status>>8)&0xFF);        lastSig = (status & 0X7F);    }    return 0;}

image-20221130152756486

image-20221130153006990

来源地址:https://blog.csdn.net/weixin_60478154/article/details/128117711

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-人工智能
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯