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

相关推荐
梦帮科技3 分钟前
OpenClaw 桥接调用 Windows MCP:打造你的 AI 桌面自动化助手
人工智能·windows·自动化
Trouvaille ~16 分钟前
【Linux】TCP Socket编程实战(一):API详解与单连接Echo Server
linux·运维·服务器·网络·c++·tcp/ip·socket
芷栀夏23 分钟前
深度解析 CANN 异构计算架构:基于 ACL API 的算子调用实战
运维·人工智能·开源·cann
全栈工程师修炼指南32 分钟前
Nginx | stream 四层反向代理:SSL、PREREAD 阶段模块指令浅析与实践
运维·网络·网络协议·nginx·ssl
旖旎夜光1 小时前
Linux(13)(中)
linux·网络
威迪斯特2 小时前
CentOS图形化操作界面:理论解析与实践指南
linux·运维·centos·组件·图形化·桌面·xserver
一方热衷.2 小时前
在线安装对应版本NVIDIA驱动
linux·运维·服务器
独自归家的兔2 小时前
ubuntu系统安装dbswitch教程 - 备份本地数据到远程服务器
linux·运维·ubuntu
ONE_SIX_MIX2 小时前
ubuntu 24.04 用rdp连接,桌面黑屏问题,解决
linux·运维·ubuntu
龙飞052 小时前
Systemd -systemctl - journalctl 速查表:服务管理 + 日志排障
linux·运维·前端·chrome·systemctl·journalctl