自主Shell命令行解释器

Shell的本质:

首先要明确一点:shell是我们未来所以进程的父进程。

shell想要执行命令,就需要从命令行中获取我们输入的字符串,shell会不断获取,所以其实,shell的本质其实是一个死循环!

并且,如今我们使用的大部分软件都是一个死循环,就比如说:你在看我这篇博客时,你不点击右上角的'x',这个软件就不会自动退出,而是一直维持当前循环。

1.打印命令行:

此时,我们的shell打印除了命令行之后,就因该从键盘中获取我们的输入

2.获取输入信息:

fgets():

fgets()可以从指定的文件(stream)中,获取到字符串s,该字符串的长度为参数size

封装函数:

3.解析字符串

我们需要将命令行字符串从"ls -a -l" 解析为 "ls" "-a" "-l"

最终目的:

切割方法:strtok

strtok的使用方法:

命令行解析命令:bash来解析命令行,其实和我们手搓的解析类似,都需要将一个字符串分割成一个一个小的命令,制成一个命令行参数表

4.执行命令

在第三步中,我们就已经将命令一个一个解析到了我们的命令行参数表了,所以想要执行命令,就只用一个一个执行命令行参数表中的内容即可。

最终,我们就完成了我们自己的shell,通过完成自主shell的过程,我们可以更清晰地了解到:shell其实就是一个死循环的过程,其命令运行的本质也是进程替换!

不过,我们这个shell对于所有的命令,都是让子进程去执行的,那么是否有一些指令是只能由父进程来执行的呢?

cd ..:路径切换指令,该指令切换的是父进程bash的路径,再经由bash传递给子进程,这样才能改变每个进程的路径,才能真正完成路劲切换。

5.内建命令:

原因是因为:在我们获取主机名时,使用的是:getenv("HOSTNAME")直接使用的是环境变量,该环境变量是从父进程的环境变量中拿出来的,而当我们更改路径后,操作系统并不会自动更改环境变量中的路径。

我们使用chdir是用户层面的数据进行更改,并不是操作系统的数据进行了更改,所以,我们需要让bash自己更改环境变量!

法一:系统调用

那如果说一定要从环境变量中获取工作路径呢?

法二:环境变量

既然需要直接改变系统的环境变量,首先就要找到我们的路径:

此时我们就明确了目标:就是要将环境变量中的PWD直接进行修改!!!

snprintf()

该函数其实和printf类似,不过可以由我们指定打印的目标对象。

最终,我们就完成对环境变量的修改,也就可以直接从环境变量中获取信息!

不过,我们并没有给myshell写环境变量表啊?那么他的环境变量表从何而来呢?

答案是:当我们执行myshell.exe可执行文件时,也就创建了一个shell的bash的子进程,我们成shell的bash为父bash,而myshell的bash由于父子进程的继承性,也就继承了父bash的环境变量表,而当我们对myshell的环境变量表进行写入时,也就自动触发了"写实拷贝"此时父子进程的环境变量表也就彻底分开了!此时,bash也就拥有了不同于父bash的环境变量表!!!

6.myshll进一步优化

一、路径显示

我们只需使用从尾到头查找字符串,找到 '\' 时就对该字符串进行截取即可。

二、退出码

所以,接下来我们的目标就是让echo $?得到上一条命令的退出码!

首先,我们要明确一点,父进程是可以拿到子进程的退出码的!

分析原理,定义全局

退出码默认为0

status

原理回溯

由于更新的延迟性,下一条指令结束之前,lastcode中保存的就是上一条指令结束的退出码

最终实现

通过上述操做,我们就可以完成echo $?得到上一条指令的退出码!

然而,我们的实现是有局限性的,如果面临echo PATH等想要得到环境变量中的内容,myshell就只能对echo命令进行回显,而不会打印真正的环境变量,这也就意味着我们需要做更多的关键词识别!!!

总结:

通过这篇文章,我们可以更好地理解shell底层运行的原理!

源代码:

自主shell · e98c943 · wgl520666/Linux学习仓库 - Gitee.com

相关推荐
用户0328472220701 天前
如何搭建本地yum源(上)
运维
A小辣椒2 天前
TShark:Wireshark CLI 功能
linux
A小辣椒2 天前
TShark:基础知识
linux
AlfredZhao2 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao3 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334663 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪3 天前
linux 拷贝文件或目录到指定的位置
linux
大树884 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠4 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质4 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务