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获取)

效果代码

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

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

相关文章

51入门之LED

目录 1.配置文件 2.点亮一个LED 2.1单个端口操作点亮单个LED 2.2整体操作点亮LED 3.LED闪烁 4.LED实现流水灯 4.1使用for循环和移位实现 4.1.1移位操作符 4.1.2使用移位操作和for循环实现 4.2使用移位函数实现LED流水灯 众所周知&#xff0c;任何一个硬件工程师…

pycharm和Spyder多行注释快捷键

1.选取注释内容 2.pycharm&#xff1a;使用Ctrl/ 3.Spyder&#xff1a;使用Ctrl1 效果图

1.k8s架构

k8s集群架构 一个Kubernetes集群至少包含一个控制平面(control plane)&#xff0c;以及一个或多个工作节点(worker node)。控制平面(Control Plane) : 控制平面负责管理工作节点和维护集群状态。所有任务分配都来自于控制平面。工作节点(Worker Node) : 工作节点负责执行由控制…

Centos-Linux安装部署MySQL-8.0

linux搭建mysql 1.使用系统的root账户 2.切换到 /usr/local 目录下 3.下载mysql wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz也可以直接在官方下载最新版本 官方下载 选择linux 4.解压mysql tar xvJf mysql-8.0.21-l…

Redux Toolkit+TypeScript最佳实践

Redux-Toolkit是为了简化使用Redux繁琐的步骤&#xff0c;可以j降低使用useReducer与useContext管理状态的频率&#xff0c;而且起到项目中状态管理规范和约束化的效果。 阅读本文需要的前置知识&#xff1a;React、Redux、Typescript、Redux hooks。 Redux-Toolkit使用步骤 …

【GO语言卵细胞级别教程】11.探索Go语言的面向对象编程之美(含源码仅此一份,先到先得)

【GO语言卵细胞级别教程】11.探索Go语言的面向对象编程之美&#xff08;含源码仅此一份&#xff0c;先到先得&#xff09; 目录 【GO语言卵细胞级别教程】11.探索Go语言的面向对象编程之美&#xff08;含源码仅此一份&#xff0c;先到先得&#xff09;1.面向对象的引用1.1简介1…

Day79:服务攻防-中间件安全IISApacheTomcatNginx弱口令不安全配置CVE

目录 中间件-IIS-短文件&文件解析&蓝屏&写权限 HTTP.SYS&#xff08;CVE-2015-1635&#xff09;主要用作蓝屏破坏&#xff0c;跟权限不挂钩 IIS短文件(iis全版本都可能有这个问题) IIS文件解析 IIS写权限 中间件-Nginx-文件解析&目录穿越漏洞&CRLF …

C++ //练习 11.14 扩展你在11.2.1节练习(第378页)中编写的孩子姓到名的map,添加一个pair的vector,保存孩子的名和生日。

C Primer&#xff08;第5版&#xff09; 练习 11.14 练习 11.14 扩展你在11.2.1节练习&#xff08;第378页&#xff09;中编写的孩子姓到名的map&#xff0c;添加一个pair的vector&#xff0c;保存孩子的名和生日。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#x…

【大数据存储】实验七 Spark RDD

Spark RDD操作实验 一、实验目的 &#xff08;1&#xff09;掌握使用Spark访问本地文件和HDFS文件的方法 &#xff08;2&#xff09;熟练掌握在Spark Shell中对Spark RDD的操作方法 &#xff08;3&#xff09;掌握Spark应用程序的编写、编译打包和运行方法 二、.实验平台 …

自动化测试框架Robot Framework入门

什么是RF RF是一个基于 Python 的、可扩展的关键字驱动的自动化 验收测试框架、验收测试驱动开发 &#xff08;ATDD&#xff09;、 行为驱动开发 &#xff08;BDD&#xff09; 和机器人流程自动化 &#xff08;RPA&#xff09;。它 可用于分布式、异构环境&#xff0c;其中自动…

VUE3和SpringBoot实现ChatGPT页面打字效果SSE流式数据展示

在做这个功能之前&#xff0c;本人也是走了很多弯路&#xff08;花了好几天才搞好&#xff09;&#xff0c;你能看到本篇博文&#xff0c;那你就是找对地方了。百度上很多都是使用SseEmitter这种方式&#xff0c;这种方式使用的是websocket&#xff0c;使用这种方式就搞复杂了&…

STM32 PWM方式读取AS5600磁编码器数据

HAL STM32 PWM方式读取AS5600磁编码器获取角度例程 &#x1f4cd;相关篇《STM32 软件I2C方式读取AS5600磁编码器获取角度例程》 &#x1f4cc;《HAL STM32 硬件I2C方式读取AS5600磁编码器获取角度例程》 &#x1f341;先通过IIC读取的角度值和逻辑分析仪抓取的AS5600 OUT引脚…

MySQL - 基础二

6、表的增删改查 CRUD : Create(创建), Retrieve(读取)&#xff0c;Update(更新)&#xff0c;Delete&#xff08;删除&#xff09; 6.1、Create 语法&#xff1a; INSERT [INTO] table_name[(column [, column] ...)]VALUES (value_list) [, (value_list)] ...value_list: v…

SQL注入---盲注

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一.盲注概述 注是一种SQL注入攻击的形式&#xff0c;在这种攻击中&#xff0c;攻击者向目标应用程序发送恶意注入代码&#xff0c;然后通过观察应用程序的响应来推断出数据库中的信息。与常规的…

@Order和@DependsOn的区别

这里写自定义目录标题 一、区别二、demo演示1、Order2、DependsOn 一、区别 Order&#xff1a;改变Bean注入的顺序DependsOn&#xff1a;改变Bean创建的顺序 二、demo演示 1、Order 类 A B 都实现了接口 I &#xff0c;且 A B都由Spring容器创建并且管理 public class A im…

【Qt】:常用控件(二:QWidget核心属性)

常用控件&#xff08;二&#xff09; 一.cursor&#xff08;光标形状&#xff09;二.font&#xff08;字体信息&#xff09;三.toolTip&#xff08;提示显示&#xff09;四.focusPolicy&#xff08;焦点&#xff09;五.styleSheet&#xff08;文本样式&#xff09; 一.cursor&a…

Windows Docker 部署 Firefly III 开源记账软件

一、简介 Firefly III是一款开源的记账软件&#xff0c;支持全球多种语言。它可以帮助用户追踪和管理个人账目、预算和账单&#xff0c;减少支出&#xff0c;节省更多。该软件支持多种货币、银行账户和投资账户&#xff0c;并提供了丰富的报表功能&#xff0c;帮助用户更好地了…

预处理指令详解

前言 上一节我们了解了文件操作的相关内容&#xff0c;本节我们来了解一下预处理指令&#xff0c;那么废话不多说&#xff0c;我们正式开始今天的学习 预定义符号 在C语言中&#xff0c;设置了一些预定义的符号&#xff0c;可以供我们直接使用&#xff0c;预定义符号是在程序…

拓扑排序--有向无环图中一个节点的所有祖先

题目描述 给你一个正整数 n &#xff0c;它表示一个 有向无环图 中节点的数目&#xff0c;节点编号为 0 到 n - 1 &#xff08;包括两者&#xff09;。 给你一个二维整数数组 edges &#xff0c;其中 edges[i] [fromi, toi] 表示图中一条从 fromi 到 toi 的单向边。 请你返…

基于SpringBoot和Vue的金融融资管理系统的设计和实现【附源码】

1、系统演示视频&#xff08;演示视频&#xff09; 2、需要交流和学习请联系