Linux——自写一个简易的shell
目录
前言
一、打印提示信息
二、分割字符串
三、替换程序
前言
之前学习了很多进程相关的知识,包括环境变量、进程的创建与退出、进程等待、进程替换。现在可以用所学的作一个小总结,手撕一个shell解释器,大致的思路是先通过环境变量获取相关信息,再通过fork创建子进程并进行程序替换,bash的命令。
一、打印提示信息
当我们链接上虚拟机,就会有这一行输出到屏幕上,告诉我们可以开始输入命令了。首先我们得把提示写出来。

环境变量中有用户名、主机号、当前目录等信息,我们可以通过 getenv 获取相关信息进行打印。
同时,我们输入命令会有很多空格存在,比如 ls -a -l。因此不能用scanf获取输入信息,可以用fgets,第三个参数为stdin(标准输入)。最后输入完毕后会输入回车换行,我们将最后一个字符设置为 '\0' 代表字符串的结束,同时也避免了换行。
#inlcude<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#define NUM 1024char* getUsername()
{char* env = getenv("USER");if(env) return env;return NULL;
}char* getHostname()
{char* env = getenv("HOSTNAME");if(env) return env;return NULL;
}char* getPwd()
{char* env = getenv("PWD");if(env) return env; return NULL;
}int main()
{char command[NUM];printf("[%s@%s %s]$ ",getUsername(),getHostname(),getPwd());//打印fgets(command,NUM,stdin); //输入完成后还会输入回车,导致换行command[strlen(command)-1] = '\0'; printf("%s",command); // 打印看看是否获取到了完整的字符串
}
运行结果如下,获取了完整了字符串。

二、分割字符串
分割字符串C语言可以用strtok函数,他第一个参数为需要分割的字符串,第二个参数是按什么字符进行分割。如果想继续往后分割同一字符传,后续需要将第一个参数设置为NULL。
分割成功返回值为分割出来的字符串,如果分割失败,返回0。

我们先分割一次字符串,放到数组argv里,后面使用while循环一直进行分割,由于分割失败返回0,自然而然就退出了。下面是打印代码,看看结果是否正确。

成功分割。

三、替换程序
fork出子进程,然后使用execvp进行程序替换,第一个参数为argv[0],比如你输入ls -a -l,他会自己去path路径里面查找 ls 是否存在,第二个参数为agrv,整个数组放进去,是命令行参数。这里写简单一点,没有处理等待失败的情况。

成功进行替换。

最后给他套上循环,一个建议的shell就做好了。我们写的比较简单,有很多bug,功能还不算完善,但是勉强也算够用。

附上总代码
#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<string.h>#define NUM 1024#define SIZE 64char* getUsername(){char* env = getenv("USER");if(env) return env;return NULL;}char* getHostname(){char* env = getenv("HOSTNAME");if(env) return env;return NULL;}char* getPwd(){char* env = getenv("PWD");if(env) return env;return NULL;}int main(){while(1){char command[NUM];char* argv[SIZE];int argc = 0;printf("[%s@%s %s]$ ",getUsername(),getHostname(),getPwd());//打印fgets(command,NUM,stdin); //输入完成后还会输入回车,导致换行command[strlen(command)-1] = '\0';argv[argc++] = strtok(command," ");while(argv[argc++] = strtok(NULL, " "));pid_t id = fork();if(id == 0){//childexecvp(argv[0],argv);exit(1);}else{pid_t rid = waitpid(id,NULL,0);if(rid>0) printf("等待成功\n");}}}
这里完善了一下代码,添加了重定向,在大标题“四”。
相关文章:
Linux——自写一个简易的shell
目录 前言 一、打印提示信息 二、分割字符串 三、替换程序 前言 之前学习了很多进程相关的知识,包括环境变量、进程的创建与退出、进程等待、进程替换。现在可以用所学的作一个小总结,手撕一个shell解释器,大致的思路是先通过环境变量获…...
【操作系统学习笔记】处理器管理1.3
【操作系统学习笔记】处理器管理1.3 参考书籍: 王道考研 视频地址: Bilibili 进程控制 进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换的功能。简而言之,进程控制就是要实现进程的状态转换…...
AndroidUI--setContentView
我们的Activity通常继承自Activity或者AppCompatActivity,这两个setContentView流程是不同的 一、继承自Activity 1、Activity.setContentView Activity中setContentVIew调用了getWindow().setContentView(view, params); getWindow返回的是mWindow,mWi…...
编程笔记 Golang基础 047 mysql数据库连接与操作
编程笔记 Golang基础 047 mysql数据库连接与操作 一、连接与操作1. 安装MySQL驱动2. 导入驱动包3. 连接数据库4. 执行SQL查询和操作5. 使用连接池6. 处理事务 二、连接字符串三、应用示例四、比较 MySQL凭借其开源、高效、稳定、灵活、安全以及广泛的社区支持等诸多优势&#x…...
.jsonl 格式文件的解释
根据 CHATGPT .jsonl 文件格式是一种文本文件格式,通常用于存储每行一个JSON对象的数据。.jsonl 文件的每一行都是一个独立的JSON对象,这些对象之间没有任何分隔符。 以下是一个示例.jsonl文件的内容: {"name": "John"…...
nodejs web服务器 -- 搭建开发环境
一、配置目录结构 1、使用npm生成package.json,我创建了一个nodejs_network 文件夹,cd到这个文件夹下,执行: npm init -y 其中-y的含义是yes的意思,在init的时候省去了敲回车的步骤,如此就生成了默认的pac…...
laravel-admin 头部添加操作
新建html 样式及js namespace App\Admin\Extensions\Nav;class Links {public function __toString(){return <<<HTML<li><a href"" οnclick"js_method();return false;"><i class"fa fa-floppy-o"></i><s…...
mysql笔记:10. 日志
文章目录 一、日志概述二、错误日志1. 启动2. 查看3. 删除 三、二进制日志1. 启动2. 查看3. 删除 四、通用查询日志1. 启动2. 查看3. 删除 五、慢查询日志1. 启动2. 查看3. 删除 日志是MySQL数据库的重要组成部分,日志文件中记录着MySQL数据库运行期间发生的变化。M…...
代码随想录刷题笔记-Day32
1. 最大子序和 53. 最大子数组和https://leetcode.cn/problems/maximum-subarray/ 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组:是数组中的一个连续…...
指针的学习5
目录 sizeof和strlen的区别 sizeof strlen 数组和指针笔试题解析 一维数组 字符数组 二维数组 指针运算笔试题解析 题目1: 题目2: 题目3: 题目4: 题目5: 题目6: 题目7: sizeof和…...
Dynamo——常用几何形体的创建与编辑(二)
上一次,我们简单整理了一些创建几何形体的节点用法,今天我们接着整理一些,几何形体的编辑方法。 一、坐标点的平移复制 [Point.Add] 使用节点 “Vector.ByCoordinates” 生成一个向量,将该向量连接到 “Point.Add” 节点的输入端 …...
uniapp富文本编辑-editor-vue2-vue3-wangeditor
前言 不管vue2还是vue3,都推荐官方的editor组件, 官方手册 https://uniapp.dcloud.net.cn/component/editor.html除了“微信小程序”,其他小程序想要使用editor组件实现富文本编辑,很难 第三方组件wangeditor在vue2࿰…...
【java】22:try-catch 异常处理
try-catch 方式处理异常说明 public static void main(String[] args) { int num1 10; int num2 0; try { int res num1 / num2; } catch (Exception e) { System.out.println(e.getMessage()); } } 注意事项 1)如果异常发生了,则异常发生后面的代码不会执行&…...
【C语言】linux内核ip_local_out函数
一、讲解 这个函数 __ip_local_out 是 Linux 内核网络子系统中的函数,部分与本地出口的 IPv4 数据包发送相关。下面讲解这段代码的每一部分: 1. 函数声明 int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb): -…...
动态规划6,最大数组和,环形子数组最大和,乘积最大子数组
最大子数组和 思路: 1.经验题目要求 dp[i]表示:以 i 位置为结尾的所有子数组中的最大和 2.状态转移方程 按长度来划分,如果长度为1,那么dp[i] nums[i]; 如果长度大于1,那么当前位置的最大和就为 i-1 位置最大和 …...
js 清空数组的方法
1、直接赋值空数组 let array [1, 2, 3, 4, 5]; array []; 这种方法并不推荐,如下图所示: 虽然a数组确实变为了空数组,但这种方法只是修改了a的指向,把a指向一个新的空数组,然而[1,2,3,4,5]这个数组并没有被清除&a…...
QT中使用QProcess执行命令,实时获取数据,例如进度条
前言 因为之前写了一个接收和发送文件的脚本,然后又需要获取进度,同步到进度条中。 效果: 使用正则匹配,获取命令行命令中的以下数据,然后同步到进度条 源码demo: 非完整代码: #include <Q…...
绘图设计:用Draw.io绘制图形技巧大全(含统一建模语言UML模板)
一、常见UML模板 1.流程图 2.用例图 include是包含关系,extend是扩展关系 简而言之,include是子集指向父集;而extend是扩展用例指向基础用例(基础用例可以理解为系统核心功能,扩展用例是可选的,不是必须…...
被唤醒的“第二十条”深入人心
近来张艺谋执导的电影《第二十条》,因为它与正在召开中的全国两会所发布的《最高人民法院工作报告》联系相当紧密,加之可免费收看,网民便相互转告,于是此信息条目立即冲上了网络热搜榜,观者如潮。因为最高人民法院工作…...
PHPInfo()信息泄漏原理以及修复方法
漏洞名称:PHPInfo信息泄漏、phpinfo()函数信息泄漏 漏洞描述: phpinfo()函数返回的信息中包含了服务器的配置信息,包括: 1)PHP编译选项以及文件扩展名的相关信息; 2)php的版本信息 3&#…...
AGI不是更大参数的大模型:3个被主流忽略的底层范式差异,决定你是否还在伪智能赛道
第一章:AGI与当前大模型的本质区别 2026奇点智能技术大会(https://ml-summit.org) 当前主流大语言模型(LLM)如GPT-4、Claude 3或Qwen2,本质上是高度优化的统计模式匹配系统——它们在海量文本上通过自回归预测实现“表观智能”&a…...
【NLP实战】基于NLTK词性标注的英语缩写消歧:以he‘s/she‘s为例
1. 为什么需要英语缩写消歧? 第一次处理英文文本数据时,我就被hes/shes这类缩写搞得晕头转向。明明都是s结尾,有时候表示"is",有时候又表示"has"。比如"Shes finished"和"Shes happy"&a…...
告别乱码!用Python的chardet库自动检测文件编码,再也不用猜encoding参数了
智能编码检测:用Python自动化解决文本文件编码难题 每次处理未知来源的文本文件时,你是否也经历过这样的痛苦循环?先用utf-8打开文件→遭遇UnicodeDecodeError→尝试gbk→再试ISO-8859-1→最终在多次失败后勉强找到能打开的编码。这种手动试错…...
AGI验证不是“加个测试集”那么简单:基于27个真实事故案例的12项反模式清单
第一章:AGI验证的本质挑战与范式跃迁 2026奇点智能技术大会(https://ml-summit.org) AGI验证远非传统软件测试或模型评估的简单延伸,其核心困境在于:验证对象本身缺乏稳定定义、可穷举行为边界与可判定终止条件。当系统具备跨域元认知、自主…...
Fornjot模块化设计详解:fj-core、fj-math、fj-viewer深度剖析
Fornjot模块化设计详解:fj-core、fj-math、fj-viewer深度剖析 【免费下载链接】fornjot Early-stage b-rep CAD kernel, written in the Rust programming language. 项目地址: https://gitcode.com/gh_mirrors/fo/fornjot Fornjot是一个用Rust编写的早期阶段…...
MyBatis-Plus Samples企业级应用架构:从单体到微服务的平滑过渡
MyBatis-Plus Samples企业级应用架构:从单体到微服务的平滑过渡 【免费下载链接】mybatis-plus-samples MyBatis-Plus Samples 项目地址: https://gitcode.com/gh_mirrors/my/mybatis-plus-samples MyBatis-Plus Samples是一套全面的企业级应用架构示例&…...
精读Mem0论文|通俗解读+全网补充,让AI拥有“长效记忆”不再是难题
精读Mem0论文|通俗解读全网补充,让AI拥有“长效记忆”不再是难题 大家好,今天咱们精读一篇近期爆火的AI记忆领域论文——《Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory》,同时结合全网相关资讯&am…...
AUTOSAR通信栈实战指南 - 从DBC到模块联调,打通CAN信号流配置全链路
1. AUTOSAR通信栈配置全景图 第一次接触AUTOSAR通信栈时,我完全被它复杂的模块关系搞懵了。记得当时导入DBC文件后,工具里蹦出上百个错误提示,那种手足无措的感觉至今难忘。其实通信栈就像快递分拣系统,DBC文件是发货清单…...
MCP-AI编程打通WIKI知识库以及后续的一些思考
摘要本文包含两部分内容,第一部分是MCP的开发配置,第二部分是MCP开发后的一些感悟,即AI 时代的数据存储与后端架构。引言使用了AI编程工具一年了,最直观的感觉就是AI编程的代码生成效果越来越好,想要代码生成效果好&am…...
SITS2026重磅预警:2026年起,未集成AI告警生成能力的CI/CD流水线将无法通过ISO/IEC 27001 DevSecOps认证——附合规迁移路线图
第一章:SITS2026演讲:AI代码告警生成 2026奇点智能技术大会(https://ml-summit.org) 在SITS2026主会场,来自CodeGuard AI实验室的研究团队首次公开演示了新一代AI驱动的实时代码告警生成系统——AlertGen v3。该系统不再依赖传统静态分析规…...
