23linux 自定义shell文件系统

news2024/10/7 20:30:15

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

环境变量也是一张表(指针数组以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.coloradmin.cn/o/1580949.html

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

相关文章

2024年3月30日~2024年4月7日周报

文章目录 一、前言二、创意收集2.1 多任务学习2.1.1 多任务学习的定义与优势2.1.2 多任务学习的分类 2.2 边缘检测2.2.1 基础理论2.2.2 sobel代码介绍2.2.3 canny代码介绍 三、《地震速度模型超分辨率的多任务学习》3.1 M-RUDSR架构3.2 详细介绍3.3 实验设置 四、实验五、小结5…

网工内推 | 深信服、宁德时代,最高20K招安全工程师,包吃包住

01 深信服科技 招聘岗位&#xff1a;安全服务工程师 职责描述&#xff1a; 1.负责现场安全服务项目工作内容&#xff0c;包含渗透测试、安全扫描、基线核查、应急响应等&#xff1b; 2.协助用户完成安全测试漏洞整改、复测工作&#xff1b; 3.为用户提供网络、主机、业务系统等…

数据库讲解---(数据查询)【MySQL版本】

零.前言 数据库讲解&#xff08;MySQL版&#xff09;&#xff08;超详细&#xff09;【第一章】-CSDN博客 数据库-ER图教程_e-r图数据库-CSDN博客 数据库讲解&#xff08;MySQL版&#xff09;&#xff08;超详细&#xff09;【第二章】【上】-CSDN博客 数据库讲解---(SQL语…

[从0开始AIGC][Transformer相关]:算法的时间和空间复杂度

一、算法的时间和空间复杂度 文章目录 一、算法的时间和空间复杂度1、时间复杂度2、空间复杂度 二、Transformer的时间复杂度分析1、 self-attention 的时间复杂度2、 多头注意力机制的时间复杂度 三、transformer的空间复杂度 算法是指用来操作数据、解决程序问题的一组方法。…

专题十二、字符串

字符串 1. 字符串字面量1.1 字符串字面量中的转义序列1.2 延续字符串字面量1.3 如何存储字符串字面量1.4 字符串字面量的操作1.5 字符串字面量与字符常量 2. 字符串变量2.1 初始化字符串变量2.2 字符数组与字符指针 3. 字符串的读和写3.1 用 printf 函数和 puts 函数写字符串3.…

通俗白话了解资产负债现金利润三张表

看到一本小书不错《财务小白轻松入门》&#xff0c;里面通俗说了三张表之间的关系。贴图摘录下&#xff1a;

SSL证书添加与ICP备案,对于SpringBoot的要求

配置了SSL证书之后&#xff0c;在SpringBoot的resources文件夹里的application.properties会添加以下代码&#xff1a; server.port443 不需要添加server.address。不然会报错。 https类型的请求默认在Postman里面不可请求。 经过SSL证书处理的网页&#xff0c;链接中使默认…

RAG文本加载和分块调研

文本加载和分块 一、文本加载 文本加载是RAG文本增强检索重要环节。文件有不同类型&#xff08;excel、word、ppt、pdf、png、html、eps、gif、mp4、zip等&#xff09;&#xff0c;衍生出了很多第三方库。使用python处理文件是各种python开发岗位都需要的操作。主要涉及到的标准…

TryHackMe - HTTP Request Smuggling

学完、打完后的复习 HTTP 1 这部分比较简单&#xff0c;直接略过 HTTP2请求走私 首先要了解HTTP2的结构&#xff0c;与HTTP1之间的一些差异 HTTP2中不再使用CRLF来作为字段的边界限定&#xff0c;而是在二进制中直接通过长度、名字、值长度、值&#xff0c;来确认边界 而这…

【C++】用红黑树封装map和set

我们之前学的map和set在stl源码中都是用红黑树封装实现的&#xff0c;当然&#xff0c;我们也可以模拟来实现一下。在实现之前&#xff0c;我们也可以看一下stl源码是如何实现的。我们上篇博客写的红黑树里面只是一个pair对象&#xff0c;这对于set来说显然是不合适的&#xff…

软件可靠性基本概念_1.定义和定量描述

1.软件可靠性定义 软件可靠性&#xff08;Software Reliability&#xff09;是软件产品在规定的条件下和规定的时间区间完成规定功能的能力。规定的条件是指直接与软件运行相关的使用该软件的计算机系统的状态和软件的输入条件&#xff0c;或统称为软件运行时的外部输入条件&am…

【MATLAB源码-第183期】基于matlab的图像处理GUI很全面包括滤波,灰度,边缘提取,RGB亮度调节,二值化等。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. RGB颜色亮度调整 1.1 RGB颜色模型 RGB颜色模型是一种加色模型&#xff0c;使用红色&#xff08;R&#xff09;、绿色&#xff08;G&#xff09;、蓝色&#xff08;B&#xff09;三种颜色的不同组合来表示各种颜色。每种…

OceanBase V4.2 MySQL模式下,如何通过DBLINK实现跨数据源访问

概述 跨数据源访问可通过 DBLINK&#xff08;以下简称DBLINK&#xff09;实现&#xff0c;从而使得业务代码能够像访问本地数据库一样轻松访问远端数据库。原先&#xff0c;DBLINK主要服务于Oracle模式&#xff0c;但由于OceanBase 的MySQL模式租户同样存在访问远端数据库的需…

【二分查找】Leetcode 点名

题目解析 LCR 173. 点名 算法讲解 1. 哈希表 class Solution { public:int takeAttendance(vector<int>& nums) {map<int, int> Hash;for(auto n : nums) Hash[n];for(int i 0; i < nums[nums.size() - 1]; i){if(Hash[i] 0)return i;}return nums.si…

【ZZULIOJ】1053: 正弦函数(Java)

目录 题目描述 输入 输出 样例输入 Copy 样例输出 Copy code 题目描述 输入x&#xff0c;计算上面公式的前10项和。 输入 输入一个实数x。 输出 输出一个实数&#xff0c;即数列的前10项和&#xff0c;结果保留3位小数。 样例输入 Copy 1 样例输出 Copy 0.841 c…

Python学习笔记11 - 列表

1. 列表的创建与删除 2. 列表的查询操作 3. 列表的增、删、改操作 4. 列表元素的排序 5. 列表生成式

PostgreSQL入门到实战-第十弹

PostgreSQL入门到实战 PostgreSQL数据过滤(三)官网地址PostgreSQL概述PostgreSQL中OR操作理论PostgreSQL中OR实操更新计划 PostgreSQL数据过滤(三) 了解PostgreSQL OR逻辑运算符以及如何使用它来组合多个布尔表达式。 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列…

免费SSL证书跟付费SSL证书有什么区别?

免费SSL证书与付费SSL证书的主要区别如下&#xff1a; 1. 类型与验证级别&#xff1a; - 免费SSL证书通常仅提供域名验证&#xff08;DV&#xff09;&#xff0c;这是一种最基本的验证级别&#xff0c;仅验证域名的所有权&#xff0c;确认申请者对所申请域名的有效控制。 - 付费…

如何在 iOS 项目中集成 MiniApp SDK,快速构建智能小程序?

本文介绍如何在 iOS 项目中&#xff0c;集成 MiniApp SDK&#xff0c;使之能够构建智能生活小程序&#xff0c;运行在你的 IoT App 上。 准备工作 在集成 MiniApp SDK 之前&#xff0c;您需要在 涂鸦 IoT 开发平台 上&#xff1a; 注册开发者账号、创建产品、创建功能点等。…

汇智知了堂:AIGC引领数字营销新革命,你准备好了吗?

ChatGPT火了&#xff0c;带火的还有AIGC。 经过长时间的蓄力&#xff0c;AIGC技术落地的应用场景呈平铺式展开&#xff0c;已经逐渐渗透到各行各业中&#xff0c;AIGC时代已来。 AIGC浪潮来袭&#xff0c;电商行业从业者该如何应对&#xff1f; AIGC技术会给电商行业带来哪些变…