linux 模拟shell

💓博主CSDN主页:麻辣韭菜-CSDN博客💓

⏩专栏分类:http://t.csdnimg.cn/G90eI⏪

🚚代码仓库:Linux: Linux日常代码练习🚚

🌹关注我🫵带你学习更多Linux知识
  🔝🔝

目录

一.命令行提示信息

 二.获取用户输入的字符串

三.拆解用户输入的字符串

四.子进程程序替换

五.内建命令(内置命令)


 

想想Xshell的命令解释器,我们在命令行输入ls命令,他的父进程是谁?bash 。根据之前的讲的进程替换,根据这个原理父进程当个监工,让子进程去做一些其他事情。

一.命令行提示信息

我们在Linux在命令行输入各种指令是需要提示行的。如下图

而且这个提示行我们不输入他是一只存在的,那就说明了他是一个无限循环的程序->常驻的进程。 

按照上面的这个代码 一直打印如下图,那肯定不行。

int main()
{
    while(1)
    {
        //1. 打印出提示信息 [root@localhost myshell]# 
        printf("[root@localhost myshell]# ");
        fflush(stdout);
    }
    return 0;
}

有了提示信息,我们就要获取用户输入指令,如何获取?用fgets获取 用户输入的指令 我们需要建立一个缓冲区来接受和保存。

 二.获取用户输入的字符串

#define NUM 1024
//保存完整的命令行字符串
char cmd_line[NUM]; //用来保存用户输入的字符串
int main()
{
    while(1)
    {
        //1. 打印出提示信息 [root@localhost myshell]# 
        printf("[root@localhost myshell]# ");
        fflush(stdout);
        //初始化缓冲区数组
        memset(cmd_line, '\0', sizeof cmd_line);
        //2. 获取用户的键盘输入[输入的是各种指令和选项: "ls -a -l -i"]
        //如果用户输入错误重新开始
        if(fgets(cmd_line, sizeof cmd_line, stdin) == NULL)
        {
            continue;
        }
    }
    return 0;
}

想一想我们在命令行输入各种指令,最后会输入一个回车键,那fgets这个函数也接收到回车键->"\n" 所以我们还需要将回车键设置成"\0"。

#define NUM 1024
//保存完整的命令行字符串
char cmd_line[NUM]; //用来保存用户输入的字符串
int main()
{
    while(1)
    {
        //1. 打印出提示信息 [whb@localhost myshell]# 
        printf("[root@localhost myshell]# ");
        fflush(stdout);
        //初始化缓冲区数组
        memset(cmd_line, '\0', sizeof cmd_line);
        //2. 获取用户的键盘输入[输入的是各种指令和选项: "ls -a -l -i"]
        //如果用户输入错误重新开始
        if(fgets(cmd_line, sizeof cmd_line, stdin) == NULL)
        {
            continue;
        }
        cmd_line[strlen(cmd_line)-1] = '\0';
    }
    return 0;
}

三.拆解用户输入的字符串

#define NUM 1024
#define SEP " "    //定义分割标识符
#define SIZE 64
//保存完整的命令行字符串
char cmd_line[NUM]; //用来保存用户输入的字符串
//保存被打散的字符串
char* g_argv[SIZE];
int main()
{
    while(1)
    {
        //1. 打印出提示信息 [root@localhost myshell]# 
        printf("[root@localhost myshell]# ");
        fflush(stdout);
        //初始化缓冲区数组
        memset(cmd_line, '\0', sizeof cmd_line);
        //2. 获取用户的键盘输入[输入的是各种指令和选项: "ls -a -l -i"]
        //如果用户输入错误重新开始
        if(fgets(cmd_line, sizeof cmd_line, stdin) == NULL)
        {
            continue;
        }
        cmd_line[strlen(cmd_line)-1] = '\0';
        //3.命令行字符串解析
        g_argv[0] = strtok(cmd_line,SEP); //第一次调用,要传入原始字符串
        int index = 1;
        while(g_argv[index++] = strtok(NULL,SEP));
       
        
}

四.子进程程序替换

#define NUM 1024
#define SEP " "    //定义分割标识符
#define SIZE 64
//保存完整的命令行字符串
char cmd_line[NUM]; //用来保存用户输入的字符串
//保存被打散的字符串
char* g_argv[SIZE];
int main()
{
    while(1)
    {
        //1. 打印出提示信息 [root@localhost myshell]# 
        printf("[root@localhost myshell]# ");
        fflush(stdout);
        //初始化缓冲区数组
        memset(cmd_line, '\0', sizeof cmd_line);
        //2. 获取用户的键盘输入[输入的是各种指令和选项: "ls -a -l -i"]
        //如果用户输入错误重新开始
        if(fgets(cmd_line, sizeof cmd_line, stdin) == NULL)
        {
            continue;
        }
        cmd_line[strlen(cmd_line)-1] = '\0';
        //3.命令行字符串解析
        g_argv[0] = strtok(cmd_line,SEP); //第一次调用,要传入原始字符串
        int index = 1;
        while(g_argv[index++] = strtok(NULL,SEP));
        //4.创建子进程
        pid_t id = fork();
        if(id <0) 
        {    
            perror("fork");
            exit(1);
        }
        if(id == 0)
        {
             printf("下面功能让子进程进行的\n");
             execvp(g_argv[0], g_argv); // ls -a -l -i
             exit(1);
        }
        //father
        int status = 0;
        pid_t ret = waitpid(id, &status, 0);
        if(ret > 0) printf("exit code: %d\n", WEXITSTATUS(status));
    }
   
}

运行没问题 这就完了吗?还没有 内建命令。

仔细看会发现 我们的cd命令没用啊,进入上级路径压根没有变化,那是因为子进程收到cd字这个字符串,是子进程的路径在发生变化运行完毕后了退出了,父进程压根就没有变还是当前路径。 

五.内建命令(内置命令)

//5.内置命令, 让父进程(shell)自己执行的命令,我们叫做内置命令,内建命令
        //内建命令本质其实就是shell中的一个函数调用
        if(strcmp(g_argv[0], "cd") == 0) 
        {
            if(g_argv[1] != NULL) chdir(g_argv[1]);//chdir 可以帮我们自动切换到指定路径
            continue;
        }
//这段代码放在字符串分割下面

为什么要程序替换,说简单点场景需要,举一个简单的例子:你在抖音上看直播,这个直播间在卖东西,上链接叫你赶紧拍,你在拍东西过程中,直播间你是没有退出的,但是你下单确认支付的那一瞬间,这时另一个进程就开始了 收你钱。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/452287.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端JavaScript篇之常见事件

目录 JavaScript常见事件click&#xff08;点击&#xff09;mouseover&#xff08;鼠标悬停&#xff09;keydown&#xff08;按键按下&#xff09;load&#xff08;加载&#xff09;submit&#xff08;提交&#xff09; JavaScript常见事件 JavaScript中的事件是指用户与网页元…

剑指offer C ++双栈实现队列

1. 基础 队列&#xff1a;先进先出&#xff0c;即插入数据在队尾进行&#xff0c;删除数据在队头进行&#xff1b; 栈&#xff1a;后进先出&#xff0c;即插入与删除数据均在栈顶进行。 2. 思路 两个栈实现一个队列的思想&#xff1a;用pushStack栈作为push数据的栈&#xff…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《考虑碳捕集机组与氢储能系统协调运行的源荷储低碳经济调度》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

ansible-playbook的角色(role)

1前言 角色目录如下&#xff08;分别为httpd角色和nginx角色&#xff09; handlers/ &#xff1a;至少应该包含一个名为 main.yml 的文件&#xff1b; 其它的文件需要在此文件中通过include 进行包含 vars/ &#xff1a;定义变量&#xff0c;至少应该包含一个名为 main.yml 的…

React Hooks 那些事儿

翻了波之前写的文章还有笔记&#xff0c;发现关于前端的文章并不多&#xff08;好歹也划水做过点前端开发&#xff09;。巧了&#xff0c;最近没什么好话题可写&#xff0c;做下 React Hooks 学习笔记吧。 Effect Hook 不得不说 Hook 的出现降低了我们在 React 中处理副作用&…

极简云商业版 开源源码

简化版的云商业源码已经以开源形式发布了&#xff0c;现在可以解绑卡密和查询卡密。总体而言&#xff0c;这个版本已经相当完善了。在对接示例网盘中有一个用户注册的例子&#xff0c;需要配置一个邮箱。您可以在网页上启用QQ邮箱的标准版SMTP&#xff0c;并生成一个授权码。 …

【Spring】学习Spring框架那点小事儿

Spring作者&#xff1a;Rod Johnson Rod Johnson 是一位软件开发人员和作家&#xff0c;他在软件开发领域有着广泛的影响力。他出生于澳大利亚&#xff0c;拥有计算机科学和音乐双学位&#xff08;能写出有优雅的代码一定有艺术细胞&#xff09;。 Rod Johnson 在 2002 年出版…

保研复习数据结构记(7)--散列查找(哈希表)

哈希表有什么特点&#xff1f;数据元素的关键字与其存储地址直接相关&#xff08;通过哈希函数相关&#xff09;&#xff0c;典型的用空间换时间的算法处理冲突的方法&#xff1f;拉链法&#xff08;链地址法&#xff09;&#xff0c;开放定址法&#xff0c;再散列法什么是查找…

2024年G3锅炉水处理证模拟考试题库及G3锅炉水处理理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年G3锅炉水处理证模拟考试题库及G3锅炉水处理理论考试试题是由安全生产模拟考试一点通提供&#xff0c;G3锅炉水处理证模拟考试题库是根据G3锅炉水处理最新版教材&#xff0c;G3锅炉水处理大纲整理而成&#xff0…

【YOLOv9】训练模型权重 YOLOv9.pt 重新参数化轻量转为 YOLOv9-converted.pt

【YOLOv9】训练模型权重 YOLOv9.pt 重新参数化轻量转为 YOLOv9-converted.pt 1. 模型权重准备2. 模型重新参数化2.1 文件准备2.2 参数修改2.3 重新参数化过程 3. 重新参数化后模型推理3.1 推理超参数配置3.2 模型推理及对比 4. onnx 模型导出&#xff08;补充内容&#xff09;4…

在WSL2中安装多个Ubuntu教程

文章目录 前言一、前期准备1、WSL安装2、Docker安装 二、安装第二个Ubuntu系统1.切换为WSL22.获取Ubuntu16.04的tar文件从容器中导出tar 3. 将tar文件导入WSL4. 设置默认用户 总结 前言 适用于 Linux 的 Windows 子系统 (WSL) 是 Windows 的一项功能&#xff0c;可用于在 Wind…

指针篇章-(5)+最终思维导图

sizeof和strlen的对比 sizeof不是函数 侧面证明sizeof不是函数 如果是函数 应该需要有括号 不能落下来 strlen 只针对字符串 包含头文件 string.h 并且这个是个函数 随机数值 sizeof里面有表达式的话 表达式里面是不参与计算的 下面的s求出的是4 就是因为是不参与计算的 不…

03_渲染进程调用node

我们先创建一个文件夹及文件&#xff0c;并且在 html 引入 JS 文件。 在 render.js 里面输入以下内容&#xff1a; let fs require(fs) // let是在当前代码块有效console.log(fs) // 将fs对象的内容打印到控制台供调试和查看 fs 模块&#xff1a;对文件系统进行操作&#xf…

七月论文审稿GPT第3.1版和第3.2版:通过paper-review数据集分别微调Mistral、gemma

前言 我司第二项目组一直在迭代论文审稿GPT(对应的第二项目组成员除我之外&#xff0c;包括&#xff1a;阿荀、阿李、鸿飞、文弱等人)&#xff0c;比如 七月论文审稿GPT第1版&#xff1a;通过3万多篇paper和10多万的review数据微调RWKV七月论文审稿GPT第2版&#xff1a;用一万…

使用Flask快速搭建轻量级Web应用【第127篇—Flask】

使用Flask快速搭建轻量级Web应用 在Web开发领域&#xff0c;选择适合项目需求的框架至关重要。Flask&#xff0c;一个轻量级的Python Web框架&#xff0c;以其简洁、灵活和易扩展的特性而备受开发者青睐。本文将介绍如何使用Flask迅速搭建一个轻量级的Web应用&#xff0c;并通过…

FreeRTOS学习笔记-基于stm32(5)列表和列表项

一、列表与列表项简介 列表是FreeRTOS中的一种数据结构&#xff0c;类似双向循环链表。用来跟踪FreeRTOS中的任务。列表项就是存放在列表中的项目。 二、列表 列表结构体&#xff1a; typedef struct xLIST {listFIRST_LIST_INTEGRITY_CHECK_VALUE //校验值c…

Unity 显示MeshRenderer的渲染层级

Unity 显示MeshRenderer的渲染层级 前言源码MeshRendererInspectorSkinnedMeshRendererInspector 参考 前言 Mesh Renderer和Skinned Mesh Renderer组件默认不显示Order&#xff0c;找了个工具显示一下。 源码 下面两个代码放入Editor文件夹中 MeshRendererInspector Me…

ChatGPT Prompt 的原理总结

ChatGPT Prompt 的原理总结 ChatGPT Prompt 是 OpenAI 开发的大型语言模型 ChatGPT 的一种使用方式。通过 Prompt&#xff0c;用户可以引导 ChatGPT 生成特定内容&#xff0c;例如回答问题、写故事、写代码等等。 Prompt 的原理 Prompt 本质上是一段文本&#xff0c;它告诉 C…

人工智能在增强数据安全方面的作用

近年来&#xff0c;人工智能&#xff08;AI&#xff09;的力量已被证明是无与伦比的。它不再是我们想象的主题。人工智能已经成为现实&#xff0c;并且越来越清楚地表明它可以让世界变得更美好。但人工智能能帮助我们增强数据安全吗&#xff1f; 由于技术的日益普及&#xff0…

Java JUC 笔记(2)

Java JUC 笔记&#xff08;2&#xff09; 锁框架 JDK5以后增加了Lock接口用来实现锁功能&#xff0c;其提供了与synchronized类似的同步功能&#xff0c;但是在使用时手动的获取和释放锁 Lock和Condition锁 这里的锁与synchronized锁不太一样&#xff0c;我们可以认为是Loc…