当前位置: 首页 > news >正文

Linux:minishell

目录

1.实现逻辑

2.代码及效果展示

1.打印字符串提示用户输入指令

2.父进程拆解指令

3.子进程执行指令,父进程等待结果

4.效果

3.实现过程中遇到的问题

1.打印字符串的时候不显示

2.多换了一行

3.cd路径无效

4.优化

1.ll指令

2.给文件或目录加上颜色

代码链接


模拟实现shell程序

所用知识

1.基础的C语言知识,fgets,fflush(刷新缓冲区)

2.字符串相关的函数:strtok

3.进程的创建(fork)进程的等待(waitpid) 进程的替换(exec*函数) 进程的终止(exit)

shell运行原理

父进程等待&&解析指令,子进程执行指令

1.实现逻辑

shell需要一直等待用户输入指令,然后执行指令,因此写一个死循环

1.打印出字符串"[zy@localhost myshell]# "提示用户输入信息

    --使用fflush刷新缓冲区

2.父进程分析指令

    --定义一个字符数组cmd来存放完整的指令(使用fgets函数,将命令读取到字符数组cmd中)

    --定义一个字符指针数组来存放拆解后的指令(使用strtok函数,将其拆解)

    --创建子进程执行指令,然后阻塞等待执行的结果

3.子进程执行指令

    --调用execvp函数,执行拆解好的指令

2.代码及效果展示

--预备工作

--定义一个字符数组cmd来存放完整的指令(使用fgets函数,将命令读取到字符数组cmd中)

--定义一个字符指针数组来存放拆解后的指令(使用strtok函数,将其拆解)

--定义一个分割符(使用#define定义SEP为空格)

1.打印字符串提示用户输入指令

 19     //1.打印字符串,提示用户输入指令                                                                                                        20     printf("[zy@localhost myshell]# ");                                                                                                    21     fflush(stdout);                                                                                                                        22     memset(cmd,'\0',sizeof(cmd));//初始化                                                                                                  23                                                                                                                                            24     if(fgets(cmd,sizeof(cmd),stdin)==NULL) continue;//读取用户输入的指令,若输入为NULL直接跳过                                             25     cmd[strlen(cmd)-1] = '\0';//由于是从键盘读取,会读取到\n,我们将其置为\0 

--fflush是用来刷新缓冲区的

--memset将cmd数组初始化,也清除了上一次输入的指令

--fgets函数:参数:char *str,int num ,FILE* stream

1.存储从输入流中读取的字符串  2.读取的最大字符数  3.从那读

2.父进程拆解指令

代码:

 27     //2.拆解指令,放进g_argv中,后面调用execvp的时候直接传递                                                                                      28     int index = 0;                                                                                                                              29     g_argv[index++] = strtok(cmd,SEP);                                                                                                          30     while(g_argv[index++]=strtok(NULL,SEP)); 

--strtok:参数:char* str , const char *strDelimit  (要分割的字符串,用来分割的字符)

第一次调用后,下一次还要继续分割这个字符,传递NULL即可,它会记录分割点的位置

3.子进程执行指令,父进程等待结果

4.效果

3.实现过程中遇到的问题

1.打印字符串的时候不显示

字符串不显示

使用fflush,刷新缓冲区即可

效果:

2.多换了一行

代码:

这里可以看到多换了一行

原因:fgets从键盘读取数据会把\n也读进cmd中,我们需要把\n置为'\0'

方法:cmd[strlen(cmd)-1] = '\0';  strlen遇到\0就不在计数了,通过其找到'\n'的位置

效果:

3.cd路径无效

原因

1.子进程是父进程的一份拷贝,直接用pwd显示的路径就是父进程的路径

2.如果使用cd指令,exec函数执行完就退出了,再执行pwd就是重新调用,父进程会生成一个新的子进程, 显示的是父进程的路径

解决:加一个判断,如果是cd命令,直接使用chdir改变当前父进程的路径

   33     if(strcmp(g_argv[0],"cd")==0)//特殊处理一下cd指令34     {35       if(g_argv[1]!=NULL) chdir(g_argv[1]); 36       continue;37     }

解决:

4.优化

1.ll指令

解决:特殊处理一下

   32     if(strcmp(g_argv[0],"ll")==0)//特殊处理一下ll指令33     {34       g_argv[0] = (char*)"ls";35       g_argv[index++] = (char*)"-l";                                                                                                                              36     }

原来:

解决:

2.给文件或目录加上颜色

思路:特殊处理

这是ls加上颜色的指令:

代码:

   32     if(strcmp(g_argv[0],"ls")==0)//特殊处理ls指令,为其加上颜色33     {34       g_argv[index++] = (char*)"--color=auto";35     }36 37     if(strcmp(g_argv[0],"ll")==0)//特殊处理ll指令38     {39       g_argv[0] = (char*)"ls";40       g_argv[index++] = (char*)"--color=auto";41       g_argv[index++] = (char*)"-l";

效果:

代码链接

链接:myshell · 朱垚/C++与Linux实例 - 码云 - 开源中国 (gitee.com)

相关文章:

Linux:minishell

目录 1.实现逻辑 2.代码及效果展示 1.打印字符串提示用户输入指令 2.父进程拆解指令 3.子进程执行指令,父进程等待结果 4.效果 3.实现过程中遇到的问题 1.打印字符串的时候不显示 2.多换了一行 3.cd路径无效 4.优化 1.ll指令 2.给文件或目录加上颜色 代码链接 模…...

STM32驱动步进电机

前言 (1)本章介绍用stm32驱动42步进电机,将介绍需要准备的硬件器材、所需芯片资源以及怎么编程及源代码等等。 (2)实验效果:按下按键,步进电机顺时针或逆时针旋转90度。 (3&#xff…...

计算机视觉——飞桨深度学习实战-深度学习网络模型

深度学习网络模型的整体架构主要数据集、模型组网以及学习优化过程三部分,本章主要围绕着深度学习网络模型的算法架构、常见模型展开了详细介绍,从经典的深度学习网络模型以CNN、RNN为代表,到为了解决显存不足、实时性不够等问题的轻量化网络…...

用c动态数组(不用c++vector)实现手撸神经网咯230901

用c语言动态数组(不用c++的vector)实现:输入数据inputs = { {1, 1}, {0,0},{1, 0},{0,1} };目标数据targets={0,0,1,1}; 测试数据 inputs22 = { {1, 0}, {1,1},{0,1} }; 构建神经网络,例如:NeuralNetwork nn({ 2, 4,3,1 }); 则网络有四层、输入层2个nodes、输出层1个节点、第…...

视频讲解|基于DistFlow潮流的配电网故障重构代码

目录 1 主要内容 2 视频链接 1 主要内容 该视频为基于DistFlow潮流的配电网故障重构代码讲解内容,对应的资源下载链接为基于DistFlow潮流的配电网故障重构(输入任意线路),对该程序进行了详尽的讲解,基本做到句句分析和讲解(讲解…...

Ultralytics(YoloV8)开发环境配置,训练,模型转换,部署全流程测试记录

关键词:windows docker tensorRT Ultralytics YoloV8 配置开发环境的方法: 1.Windows的虚拟机上配置: Python3.10 使用Ultralytics 可以得到pt onnx,但无法转为engine,找不到GPU,手动转也不行&#xff0…...

springboot之@ImportResource:导入Spring配置文件~

ImportResource的作用是允许在Spring配置文件中导入其他的配置文件。通过使用ImportResource注解,可以将其他配置文件中定义的Bean定义导入到当前的配置文件中,从而实现配置文件的模块化和复用。这样可以方便地将不同的配置文件进行组合,提高…...

阿里云服务器免费申请入口_注册阿里云免费领4台服务器

注册阿里云账号,免费领云服务器,最高领取4台云服务器,每月750小时,3个月免费试用时长,可快速搭建网站/小程序,部署开发环境,开发多种企业应用。阿里云百科分享阿里云服务器免费领取入口、免费云…...

ES6中的async、await函数

async是为了解决异步操作,其实是一个语法糖,使代码书写更加简洁。 1. async介绍 async放在一个函数的前面,await则放在异步操作前面。async代表这个函数中有异步操作需要等待结果,在一个async函数中可以存在多个await&#xff0…...

代码随想录算法训练营第五十六天 | 动态规划 part 14 | 1143.最长公共子序列、1035.不相交的线、53. 最大子序和(dp)

目录 1143.最长公共子序列思路代码 1035.不相交的线思路代码 53. 最大子序和(dp)思路代码 1143.最长公共子序列 Leetcode 思路 本题和718. 最长重复子数组 区别在于这里不要求是连续的了,但要有相对顺序,即:“ace” …...

【数据挖掘】2021年 Quiz 1-3 整理 带答案

目录 Quiz 1Quiz 2Quiz 3Quiz 1 Problem 1 (30%). Consider the training data shown below. Here, A A A and B B B</...

【软件设计师-中级——刷题记录6(纯干货)】

目录 管道——过滤器软件体系结构风格优点&#xff1a;计算机英语重点词汇&#xff1a;单元测试主要检查模块的以下5个特征&#xff1a;数据库之并发控制中的事务&#xff1a;并发产生的问题解决方案:封锁协议原型化开发方法&#xff1a; 每日一言&#xff1a;持续更新中... 个…...

微信小程序点单左右联动的效果实现

微信小程序点单左右联动的效果实现 原理解析&#xff1a;   点击左边标签会跳到右边相应位置&#xff1a;点击改变rightCur值&#xff0c;转跳相应位置滑动右边&#xff0c;左边标签会跳到相应的位置&#xff1a;监听并且设置每个右边元素的top和bottom&#xff0c;再判断当…...

Socket通信

优质博文IT-BLOG-CN 一、简介 Socket套接字&#xff1a;描述了计算机的IP地址和端口&#xff0c;运行在计算机中的程序之间采用socket进行数据通信。通信的两端都有socket&#xff0c;它是一个通道&#xff0c;数据在两个socket之间进行传输。socket把复杂的TCP/IP协议族隐藏在…...

TCP 如何保证有效传输及拥塞控制

TCP&#xff08;传输控制协议&#xff09;可以通过以下机制保证有效传输和拥塞控制&#xff1a; 确认机制&#xff1a;TCP使用确认机制来保证数据的有效传输。发送方在发送数据的同时还会发送一个确认请求&#xff0c;接收方收到数据后会回复确认响应。如果发送方没有收到确认响…...

PyQt5+Qt设计师初探

在上一篇文章中我们搭建好了PyQt5的开发环境&#xff0c;打铁到趁热我们基于搭建好的环境来简单实战一把 一&#xff1a;PyQt5包模块简介 PyQt5包括的主要模块如下。 QtCore模块——涵盖了包的核心的非GUI功能&#xff0c;此模块被用于处理程序中涉及的时间、文件、目录、数…...

rust cargo

一、cargo是什么 Cargo是Rust的构建工具和包管理器。 Cargo除了创建工程、构建工程、运行工程等功能&#xff0c;还具有下载依赖库、编译依赖等功能。 真正编写程序时&#xff0c;我们不直接用rustc&#xff0c;而是用cargo。 二、使用cargo &#xff08;一&#xff09;使用…...

CANoe.Diva生成测试用例

Diva目录 一、CANoe.Diva打开CDD文件二、导入CDD文件三、ECU Information四、时间参数设置五、选择是否测试功能寻址六、勾选需要测试服务项七、生成测试用例 一、CANoe.Diva打开CDD文件 CANoe.Diva可以通过导入cdd或odx文件&#xff0c;自动生成全面的测试用例。再在CANoe中导…...

openGauss学习笔记-89 openGauss 数据库管理-内存优化表MOT管理-内存表特性-使用MOT-MOT使用查询原生编译

文章目录 openGauss学习笔记-89 openGauss 数据库管理-内存优化表MOT管理-内存表特性-使用MOT-MOT使用查询原生编译89.1 查询编译&#xff1a;PREPARE语句89.2 运行命令89.3 轻量执行支持的查询89.4 轻量执行不支持的查询89.5 JIT存储过程89.6 MOT JIT诊断89.6.1 mot_jit_detai…...

python获取时间戳

使用 datetime 库获取时间。 获取当前时间&#xff1a; import datetime print(datetime.datetime.now()) . 后面的是微秒&#xff0c;也是一个时间单位&#xff0c;1秒1000000微秒。 转为时间戳&#xff1a; import datetimedate datetime.datetime.now() timestamp date…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...