提要

最近操作系统作业写了一个shell,最后效果感觉还可以,发出来分享下。

提示:因为使用了动态库readline 编译时要加 -l readline

已实现功能:

  1. 完善的提示符
  2. 内含命令 (cd, help. exit, history)
  3. 外部命令 (可执行文件,简单shell命令)
  4. 重定向
  5. 无名管道
  6. readline库的功能:命令历史记录(按上下查看历史, tab自动补全,历史记录本地记录

**具体的代码讲解这里不会涉及。
下面是源码的下载**



功能演示

提示信息


以上是一个shell运行流程,通过这个流程,我们可以得到我们大概的代码框架

    while (true)
    {
        line = readline(info)
        if (line == 'xxxxxxx') // 退出信息
            break;

        if (!(analysis(line))) //如果分析成功
        {
                do_command(); //运行命令
        }
    }

ok,现在我们要做的就是在这个框架上面加代码
我们先做提示信息,观察发现系统自带的提示信息分为四个部分:
用户名 用户组 路径 权限符($或者#)

程序中的setInfo(info);就是设置每次打印的提示符,不展开讲
下面是myshell的提示信息,为了区别改了部分颜色,做到了较高还原度。

读取输入及分析

输入使用的是动态库readlinereadline(info)就是先打印提示信息,然后等待输入。

readline带有以下的功能

  1. tab键补全路径,如下所示,输入tab后

补全为

  1. 历史记录,我们使用shell的是按上下键可以回顾之前的历史,这里使用了readline/history.h可以记录历史记录,并且实现类似的效果。
    如下图,cd后按上键


补全为

并且在同级目录下生成了一个txt记录历史记录,方便下次重新打开程序时读取。

分析部分较为简单,不展开。

内含命令

内含命令值得一提的就是history,可以展示,之前的历史记录,系统的shell就有此功能

以下是该内含命令的代码。

void display_history_list()
{
    HIST_ENTRY **h = history_list();
    if (h)
    {
        int i = 0;
        while (h[i])
        {
            printf("%d: %s\n", i, h[i]->line);
            i++;
        }
    }
}

外部命令

  1. 重定向
    如下图,使用>进行重定向


生成的文件如下

  1. 无名管道
    ls的输出中选出带有ls字符串的再输出,平时也比较常用

主要功能的演示就到这里,还有一个改进的点是接管ctrl+c,使得不会直接退出myshell,不过暂时不知道如何下手。
有问题可以在评论区留言,由于没有仔细调试,有的时候还会出现段错误,如发现bug,希望各位大佬帮我指出,谢谢!

一个小彩蛋

因为我们的shell是一个可执行文件,这时我发现有一个有趣的玩法,就是在shell里面运行shell,从而达到无限套娃的效果:eyes:。

Reference

myShell:Linux Shell 的简单实现



Last modification:July 15th, 2020 at 02:34 pm
If you think my article is useful to you, please feel free to appreciate