23linux 自定义shell文件系统

打印环境变量,把当前子进程所有环境变量打印出来

环境变量也是一张表(指针数组以null结尾,最后条件不满足就退出了 )

用子进程调用

结论1

当我们进行程序替换的时候 ,子进程对应的环境变量(子进程的环境变量是直接从父进程来的)

那么父进程的环境变量是从哪里来的呢? bash父亲,myprocess子,mytest孙子

给bash导入一个变量

执行mytest后果然继承了bash的变量

putenv

把变量到入myprocess(注意pitenv是char*类型的)

子进程mytest也可以看到,最终子进程的环境变量会越来越多

结论2.

环境变量被子进程继承下去是一种默认行为,为什么不受程序替换的影响 原理? 

程序替换,只替换新程序的代码和数据,环境变量不会被替换

命令行参数在栈上

通过地址空间可以让子进程继承父进程的环境变量数据 (子进程也可以看到)

子进赋值他的pcb和进程地址空间 

environ

也可以打印环境变量 

execle

a:直接传环境变量

第一个绝对路径,第二个参数以null结尾代表就三个,最后一个传环境变量environ(他是char**的)而execle点个参数是指针数组,数组传参发生降为就是char**的

b:我们想传递自己的环境变了怎么办

我们不传给他系统默认的环境变量,而是自己写一个传给他(自定义了一个myenv表)

 这就拿到了我们自己传的环境变量表

结论:

选了带e的 我们可以直接构造环境变量表,给子进程传递,并且带e的不是在原有的环境变量基础上新增你自定义的变量表,而是覆盖上去,只有你的环境变量表(全新的环境变量表)

 c:当我们想在原有的基础上新增呢?

当我们在父进程创建变量后,直接传自己的环境变量就会把新创建的变量传递给子进程(新增)

结论

程序替换可以将命令行参数,和环境变量通过自己的参数,传递给被替换程序的main函数中

 execvpe和execle

左边都是号手册,只有execve是2号手册

上面个最终都会转化成execve(他是真正的系统调用)

都会转成execve的参数(文件名,命令行参数,环境变量)为什么呢?

主要是为了满足各种调用使用场景(选择合适的)

 自己实现shell

env查看环境变量中的USER,hostname,pwd我们用getenv来获取(头文件stdlib.h)

如果存在return,没有返回none 

成功创建自己的命令行提示符,下一步把光标卡在这里,并不是自动调到下一行

定一个命令行usercommand[num],把输入的内凡在userconmand里面(这样就可以停住了)

                要把\n去掉

ls -a -l回显测试 但是只显示ls 因为scanf遇到 空格 就结束了,所以我们不用scanf

直接用fgets/gets

获取成功了就是字符串的起始地址,失败就是none

stream(stdin)读到缓冲区(char*,int size)

c语言默认会打开三个输入输出流 stdin键盘 stdout显示器 stderr显示器(他们的类型FILE*)

可以用sizeof直接求数组大小么?一般是sizeof(usercommand)是可以的

获取成功返回r失败返回1,然后printf回显打印出来,但是多了一个空行!

去掉prif中\n虽然没有换行但是重新另起一个命令行了,因为最终你输入ls-a-l 还有一个\n

怎么去掉最后一个\n呢?他是最后一个字符

把\n的位置改成\0,但是会不会越界呢? strlen(userconmand)-1<0?      不会!

因为敲完命令最少有一个\n

完成,获得了命令行输出

封装上面代码 

1 打印提示符&&获取用户命令字符串获取成功

2 分割字符串

分割成 ls,-a,-l  首先定义一个指针数组(以null结尾),怎么切割呢?每个子串后面加\0(独立起来)

我们用c的话用分割函数(1变多)

size定义成64把argv初始化为空

strtok

把字符串按照 指定的 分隔符,打散成子串

截取成功返回起始地址,失败返回null

每次按照分隔符提取一个子串,然后后面的传null就会继续分割后序的子串

当前子串在usercommand【num】里面 ,然后后面的传null就会继续分割后序的子串

截取成功返回起始地址,失败返回null,最后一次截取正好为null让argv以null结尾 

此时argv里面存的就是 ls,-a ,-l ,null

截取测试

截取成功

封装字符串切割函数 

 

至此切割完成

3 执行分割命令

 当前是一个进程,用fork函数  

子进程去执行 exec command (调用程序替换接口) 创建子进程(不让子进程往后走用exit(1))

父进程做的是等待子进程 此时引入 waitpid(等待的id,退出码,退出方式)

然后用子进程调用程序替换函数接口,我们选择(做更少的工作,不用导环境变量)

我们选择execvp

 argv[0]就是ls,我们想怎么执行程序(在命令行怎么传)就用 argv 

但是我们的命令行只能跑一次

用while循环套起来就可以一直执行了 

当我们一直敲回车r就会返回1

 把获取到的字符串的长度返回(可能为0空串可能大于0 )

获取返回的长度,如果n<=0说明获取失败(-1),或者是空串 那么就continue跳出下面的语句

执行命令封装

id<o创建子进程失败返回-1

cd..路径并没有不变,为什么呢?

是子进程执行的cd..,当我们自己执行命令时候是bash环境中进行的

shell的内建命令

(就是bash自己执行的,类似于自己内部的一个函数)

所以有一批命令不能交给子进程执行,只能由父进程来执行

所有执行命令前要知道他是否是 内建命令(所以我们要检查)

只有带color我们执行的命令才会带颜色(按照颜色方式执行)

4.检查是否是内建命令 

n=doBuildfin(argv)  

1表示是内建命令 0表示不是内建命令

首先确认是否 是内建命令用strcmp(跟内建命令比较)

比如跟cd比较 是cd并且执行cd 并返回1

是内建命令就continue不继续往下走了 循环看下一个指令

如果不是就返回0 继续往下走

如果argv[1]参数没有设置(cd后加没有命令(没东西))走到cd parh一定不为空

 

来到cd函数,我们要切换哪一个路径呢? 怎么样让自己对应的当前进程,去执行一个接口,能够把我们当前的路径变了

chdir

谁调用chdir就把谁当前的工作路径更改,所以我们改argv[1]

更改后 chdir谁就改成了谁的路径

 但是我们=命令行的路径没有变,为什么呢?

因为我们吗每次执行时候获取的环境变量都没有变

 方法二

sprintf

把格式化的字符串format往str里面打印

当前环境变量叫做pwd

把对应的格式化的内容“PWD=%s”导入到cwd里面去,同时用putenv导入到当前环境变量,谁掉putenv就导入到谁中,此时路径确实变了,此时env找不到pwd了(因为路径已经变了)

因为环境变量的存储空间不能在临时空间里面去存,必须永久有效

函数调用时有,putenv导入后只是把cwd【】的地址导进去了(表里面)但是地址没有

所以改成全局变量  此时env可以看到pwd了

getcwd 

把当前进程所在的绝对路径放在缓冲区里面,返回值是获取成功时获取的内容

获取当前绝对路径后再通过sprintf(把格式化的字符串format往str里面打印)放在cwd里面

此时cwd拿的就是chdir之后的 当前进程的 绝对工作路径(经过getcwd),这次不怕临时空间了,因为我们把整个emp格式化到cwd里面了,再putenv 重新导入

让子进程导入export,第一次env可以看到

但是再次env就看不到6666666666666666了

因为argv[1]是由 *argv【size】指向的,而该指针数组指向的是usercommand【num】里面子串

而usercommand【num】每次都再输入指令是都会覆盖写入,下次usercommand【num】里面的缓冲区已经被改变了,所以将环境变量不能用临时缓冲器缓冲(比如刚才全局变量cwd)

所以我们定义一个大的全局变量表,导入进去

导环境变量的动作 用strcpy

此时我们就存到我们定义的enval里面,然后导出就导出我们的enval(enval不受其他用户影响)

如果export后是空就退出ruturn 1

提取最近一个进程退出时的退出码(echo $?/$PATH)

argv[1]应该指向$+1就指向PATH,后面的是? 

既如果argv[1]是?就是查看退出码,是PATH就是查看环境变量(用getenv获取)

效果代码

新增:

内建命令判断附加

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

聚焦ChatGPT:学术写作全攻略

ChatGPT无限次数:点击直达 聚焦ChatGPT&#xff1a;学术写作全攻略 引言 在当今信息爆炸的时代&#xff0c;学术写作对于研究人员和学生来说是至关重要的技能。而随着人工智能的不断发展&#xff0c;ChatGPT作为一个强大的自然语言处理工具&#xff0c;为学术写作带来了全新的…

Mybatis执行器(Executor)

Executor简介 Executor Executor是MyBatis的核心接口之一&#xff0c;其中定义了数据库操作的基本方法。在实际应用中经常涉及的SqlSession接口的功能&#xff0c;都是基于Executor接口实现的。 BaseExecutor BaseExecutor是一个实现了Executor接口的抽象类,它实现了Execut…

pytorch 与 python版本对应关系

pytorch 与 python版本对应关系 torchtorchvisionPythonmain / nightlymain / nightly>3.8, <3.112.20.17>3.8, <3.112.10.16>3.8, <3.112.00.15>3.8, <3.111.130.14>3.7.2, <3.101.120.13>3.7, <3.101.110.12>3.7, <3.101.100.11&…

word文档拆分

Word如何拆分文档&#xff1f;-Word将文档拆分的方法 - 极光下载站 (xz7.com) 可以参考这篇&#xff0c;注意需要全部选中后再创建。 最需要注意的是&#xff0c;拆分后原文档不存在了&#xff0c;最多可以显示引用的拆分的文档&#xff0c;如果拆分有误&#xff0c;则无法恢复…

Yolov8-pose关键点检测:特征融合 | CAMixing:卷积-注意融合模块和多尺度提取能力 | 2024年4月最新成果

💡💡💡本文独家改进:CAMixingBlock更好的提取全局上下文信息和局部特征,包括两个部分:卷积-注意融合模块和多尺度前馈网络; 💡💡💡如何跟YOLOv8结合:1)放在backbone后增强对全局和局部特征的提取能力;2)放在detect前面,增强detect提取能力; 提供多种改进方…

RabbitMQ3.13.x之十一_RabbitMQ中修改用户密码及角色tgs

RabbitMQ3.13.x之十一_RabbitMQ中修改用户密码及角色tgs 文章目录 RabbitMQ3.13.x之十一_RabbitMQ中修改用户密码及角色tgs1. 修改用户的密码1. 修改密码语法2. 修改案例 2.修改角色tags1. 修改标签(tags)语法2. 修改案例 可以使用 RabbitMQ 的命令行工具 rabbitmqctl 来修改用…

【MATLAB源码-第180期】基于matlab的PTS,SLM,CPFilter三种降低OFDM系统的PAPR仿真。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. 限幅和滤波&#xff08;Clipping and Filtering&#xff09; 原理简介 限幅和滤波是一种基础且直观的方法&#xff0c;用于降低OFDM信号的PAPR。在限幅阶段&#xff0c;信号的幅度在达到设定阈值时会被削减&#xff0c;…

皮具5G智能制造工厂数字孪生可视化平台,推进企业数字化转型

皮具5G智能制造工厂数字孪生可视化平台&#xff0c;推进企业数字化转型。随着信息技术的快速发展&#xff0c;数字化转型已成为企业提升竞争力、实现可持续发展的关键路径。皮具行业&#xff0c;作为一个传统的手工制造业&#xff0c;正面临着巨大的市场变革和技术挑战。如何在…

红队打靶:holynix打靶流程-文件包含-文件上传-修改伪设备提权(vulnhub)

目录 开头 1.主机发现和端口扫描 2.80端口-万能密码-文件泄露 sql注入万能密码 文件泄露-读取/etc/passwd文件 sqlmap POST注入| SQL注入实现越权 | 水平越权 最后构造的sql语句,为什么这么构造嘞&#xff1f; 3.文件上传、文件解析漏洞利用 浏览器怎么访问家目录啊&…

你不知道的10个光伏冷知识!

对于光伏发电许多人都不是很了解&#xff0c;今天小编整理了10个光伏方面的冷知识分享。 1.光伏是如何诞生的&#xff1f; 1839年&#xff0c;19岁的法国贝克勒尔做物理实验时&#xff0c;发现在导电液中的两种金属电极用光照射时电流会加强&#xff0c;从而发现了“光生伏打…

C语言指针—指针和指针类型

指针是什么&#xff1f; 指针是什么&#xff1f; 指针理解的2个要点&#xff1a; 指针是内存中一个最小单元的编号&#xff0c;也就是地址 平时口语中说的指针&#xff0c;通常指的是指针变量&#xff0c;是用来存放内存地址的变量 总结&#xff1a;指针就是地址&#xff0c;口…

Flutter 单例模式的多种实现方法与使用场景分析

单例模式是一种常用的设计模式&#xff0c;用于确保一个类只有一个实例&#xff0c;并提供一个全局访问点。在Flutter应用程序中&#xff0c;单例模式可以有效地管理全局状态、资源共享和对象的生命周期。本文将介绍Flutter中实现单例模式的多种方法&#xff0c;并分析它们的使…

【leetcode面试经典150题】19.最后一个单词的长度(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

loopvar 改动不同版本的影响-defer,closures

defer示例代码 package mainimport ("fmt""runtime" )func main() {fmt.Println("golang version:", runtime.Version())defer_demo() }func defer_demo() {defer println()for counter, n : 0, 0; n < 3; n {defer func(v int) {fmt.Print(…

Windows深度学习环境----Cuda version 10.2 pytorch3d version 0.3.0

Requirements Python version 3.8.5Pytorch version: pytorch1.6.0 torchvision0.8.2 torchaudio0.7.0 cudatoolkit10.2.89pytorch3d version 0.3.0Cuda version 10.2 感觉readme文件里的不适配&#xff0c;跟pytorch官网不同 以前的 PyTorch 版本 |PyTorch的 # CUDA 10.2 c…

2024-04-08 问AI: 介绍一下AI 大神 吴恩达

文心一言 吴恩达&#xff08;Andrew Ng&#xff09;是AI领域的一位重要人物&#xff0c;他的贡献和影响力在学术界、工业界以及在线教育领域都极为显著。 吴恩达出生于1976年&#xff0c;是一位华裔美国人&#xff0c;他在斯坦福大学担任计算机科学系和电子工程系的副教授&am…

充电桩项目,开源啦!

好&#xff0c;我是田哥 很多人&#xff0c;最近都在关注我的充电桩项目&#xff0c;之前建了一个微服务架构的项目&#xff0c;也有单体项目的代码开源。 今天&#xff0c;我把最新版微服务架构的充电桩项目源代码开源。 充电桩的输入端与交流电网直接连接&#xff0c;输出端都…

WindowServer2019远程桌面无法连接问题及处理方法

WindowServer2019远程桌面无法连接问题及处理方法 文章目录 WindowServer2019远程桌面无法连接问题及处理方法1. 问题描述1. 连接问题2. 原因分析 2. 解决方法1. 零时解决方法2. 永久解决方法1. 打开注册表编辑器2. GracePeriod的权限权限设置3. 删除REG_BINARY4. 重启 1. 问题…

VMware配置环境(安装运行问题)及系列dns端口网络类型IP远程连接学习之(详谈8000字)

安装vmware快速配置步骤 下载VMware安装包 在下载好VMware安装包之后双击运行 接受条款 关闭VMware自动更新 勾选快捷键方式 安装VMware安装 输入许可证&#xff08;有需要私信小编&#xff09; 安装完成 重启电脑即可 最终成功界面: 安装Linux系统 创建虚拟机 选择…

【代码随想录】【贪心算法】day36:无重叠子区间,划分字母区间,合并区间

class Solution(object):def eraseOverlapIntervals(self, intervals):""":type intervals: List[List[int]]:rtype: int"""intervals.sort(keylambda x:x[0])count0# 可以记录重叠子区间的个数&#xff0c;然后让整个数组的长度减去重叠的个数#…