当前位置: 首页 > 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…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

【网络安全】开源系统getshell漏洞挖掘

审计过程&#xff1a; 在入口文件admin/index.php中&#xff1a; 用户可以通过m,c,a等参数控制加载的文件和方法&#xff0c;在app/system/entrance.php中存在重点代码&#xff1a; 当M_TYPE system并且M_MODULE include时&#xff0c;会设置常量PATH_OWN_FILE为PATH_APP.M_T…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...