自主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

相关推荐
陌上花开缓缓归以14 小时前
OPENWRT 端口link问题
linux·arm开发
Coder个人博客14 小时前
Linux6.19-ARM64 mm ioremap子模块深入分析
linux·安全·车载系统·系统架构·系统安全·鸿蒙系统·安全架构
程序员一点14 小时前
第4章:Linux 文件系统结构与路径管理
linux·运维·服务器
百炼成神 LV@菜哥14 小时前
Kylin Linux V10 aarch64安装DBeaver
java·linux·服务器·kylin
郝学胜-神的一滴14 小时前
Linux网络编程之listen函数:深入解析与应用实践
linux·服务器·开发语言·网络·c++·程序人生
lcreek14 小时前
Linux信号掩码与sigsuspend原子操作:临界区信号安全处理实例详解
linux·系统编程
百***787514 小时前
Clawdbot 技术实战:基于一步 API 快速接入,打造本地化 AI 自动化助手
运维·人工智能·自动化
EnglishJun15 小时前
数据结构的学习(二)---Makefile的使用
linux·运维·学习
jl486382115 小时前
打造医疗设备的“可靠视窗”:医用控温仪专用屏从抗菌设计到EMC兼容的全链路解析
大数据·运维·人工智能·物联网·人机交互
曾几何时`15 小时前
Docker容器化部署编译运行模块
运维·docker·容器