环境变量和进程地址空间

news2024/12/25 12:13:29

目录

环境变量:

env:显示所有的环境变量:

echo +$环境变量名表示查看环境变量的值

 理解环境变量:

getenv:显示环境变量的值

export

 set命令:显示所有变量

 unset取消变量:

 pwd:当前路径

自主实现pwd环境变量:

问题:环境变量是怎么被子进程继承的(思考题目)

命令行参数:

 main函数的第三个参数:

environ 

putenv

stat

 我们提出一个问题:

现象:

现象:

echo的问题:

程序地址空间

感性理解虚拟地址空间

操作系统如何画饼呢?


环境变量:

一般是指在 操作系统 中用来指定操作系统运行环境的一些参数

我们使用指令来具体理解环境变量。

env:显示所有的环境变量:

 这就是所有的环境变量。

echo +$环境变量名表示查看环境变量的值

例如:

 PATH上一节课我们已经讲过,PATH是一个环境变量,它的值等于Linux系统指令所在的路径。

 我们再举几个例子:

假如我们想要显示家目录:

假如我们想要显示登录账户的名字:

 

 理解环境变量:

我们输入指令env,显示所有的环境变量:

 我们可以在这些环境变量中找到名字为USER的环境变量:

 这里表示当前登录的用户名。

接下来,我们切换到root用户:

 

 

我们输入env指令:

 

 当我们切换用户的时候,我们的USER环境变量发生了变化。

环境变量是可以随着我们运行环境的变化而发生更改的。

接下来,我们写一串代码帮助理解:

 我们首先创建一个源文件

 我们再写出mycmd.c的源文件对应的解决方案文件Makefile

我们使用vim对Makefile进行文本编辑:

 

 我们对这串指令进行分析:

表示mycmd的依赖对象是mycmd.c

 这是对应的依赖方法:gcc表示我们要进行编译 -o表示我们要进行编译链接形成可执行程序,$@表示左依赖列表,也就是mycmd,@^表示的是右依赖列表,也就是mycmd.c,表示我们要把mycmd.c经过编译链接形成对应的可执行程序mycmd

.PHONY有两层含义:含义1表示我们的clean是一个为目标,没有对应的依赖对象,含义2:.PHONY修饰的目标不会关心文件的修改时间,总是被执行,clean对应的依赖方法是强制删除文件mycmd.c

getenv:显示环境变量的值

 该函数的返回值列表如图:

 我们举一个例子:

我们通过echo得到了环境变量USER的值,我们通过getenv函数也能得到相同的结果。

我们对mycmd.c源文件进行文本编辑:

 我们调用getenv函数,函数的参数是字符串"USER",char*类型的who用来接收返回时,然后我们以字符串的形式打印who

我们输入make,默认执行的是Makefile的第一个解决方法:

 接下来,我们通过./mycmd来调用该程序:

所以我们的who指向的bbb,我们可以得出结论:

getenv函数的作用:

 name是环境变量的名字,返回的结果是环境变量的值,假如调用失败时,我们返回空指针。

接下来,我们切换到用户root

我们调用该可执行程序:

 我们并没有对mycmd.c的源文件的文本进行修改,但是USER发生了变化,所以我们打印的结果也就发生了变化。

所以这里的USER环境变量的作用就是标识当前使用的Linux用户。

我们再切换会原来的bbb用户

 对mycmd.c进行文本修改:

 我们调用strcmp,假如who等于root时,我们显示用户名,陷入who不是root时,我们提示权限不足。

 我们当前的账户名为bbb

我们make之后调用该可执行程序:

显示我们权限不足,我们切换成为root用户:

 

 所以我们可以通过判定环境变量USER的值来决定那些用户有权限,而哪些用户没有权限。

这里的环境变量起到了身份认证的作用,当我们想要执行一个操作时,我们先检测环境变量USER的值,假如USER拥有这个权限,我们再执行这个操作。

 所以sudo的本质就是相当于把我们的环境变量USER的值由原来的bbb切换成为root。

我们也可以自己设置一些环境变量,例如:

 我们设置变量myval的值为1234

我们调用echo

 我们显示了该变量的值,接下来,我们调用env,从env中找这个myval的变量。

 我们并没有找到myval的值,原因是什么?

原因是env显示的是所有的环境变量,而echo既可以显示普通的变量,也可以显示环境变量,我们这里的myval很明显是一个普通变量,所以env无法显示。

我们可以把这里的myval理解为局部变量,把env显示的环境变量理解为全局变量。

那我们该如何链接环境变量的全局性和这个局部变量呢?

我们进行解释:

首先对mycmd.c进行文本编辑。

我们调用getenv函数 看是否能够得到myenv的值。

 所以myval值并不是一个环境变量。

接下来,我们介绍export指令

export

export的作用是定义环境变量;假如一个变量已经存在,export+该变量能够将该变量导成环境变量。

例如:

 我们把myval导成环境变量。

这个时候,在env中就能找到该环境变量了。

接下来我们调用mycmd,因为我们的myval变量变成了全局变量。

 

所以可以显示该变量的值。

 重点:bash是一个系统进程,在该进程内部我们创建了环境变量和普通变量,mycmd是bash创建的子进程,子进程可以继承父进程的环境变量,但是无法继承普通变量,所以环境变量具有全局属性,我们有了环境变量,就可以做身份识别,查找指令路径等工作了

本地变量只在bash进程中有效,无法在被子进程mycmd继承。

 set命令:显示所有变量

 

我们创建一个本地变量,我们通过env无法显示,这个时候,我们可以使用set命令

 set既显示所有的环境变量,也显示所有的本地变量

假如我们想要把youval导成环境变量,我们可以用export

 

 unset取消变量:

 

 set和env都找不到这个变量。

export定义环境变量的写法:

 

 pwd:当前路径

我们提出一个问题:

为什么我们可以调用这个指令?

我们知道,ls是系统给的指令,环境变量PATH中对应的就是系统路径,所以我们知道路径,就可以直接调用该指令,但是mycmd呢?我们知道,调用一个指令要么知道绝对路径,要么知道相对路径,最标准的写法应该是这样:

 因为我们有环境变量PWD

 我们输入env查看环境变量。

 我们可以找到环境变量PWD

这里表示的就是当前路径,因为我们的ls是bash的子进程,子进程继承了父进程的环境变量,也就继承了PWD,所以我们知道了当前的路径,所以我们可以这样写:

 

 我们退到上级目录:

 

环境变量PWD也发生了改变。

原因:环境变量是在bash中维护,当当前路径发生改变时,bash就会修改环境变量PWD的值。

所以这里实质的原因是:ls也是一个进程,是bash的子进程,PWD是bash的环境变量,环境变量可以由子进程来继承,所以ls继承了PWD,所以ls知道了当前的路径,所以也就知道了mycmd的位制。

自主实现pwd环境变量:

非常简单,因为我们有了PWD环境变量,我们直接调用getenv就能实现PWD

 我们也可以把mycmd的路径添加到环境变量PATH中。这样不需要./就可以调用我们自己实现的PWD。

问题:环境变量是怎么被子进程继承的(思考题目)

命令行参数:

main函数的参数列表叫做命令行参数。

 我们思考一个问题:main函数的参数可以有几个

main函数最多有三个参数,但是我们正常见的main函数一般只有两个参数。

 我们对这两个参数进行解释:

参数argc是一个整型,argv是一个指针数组 ,argv指向的数组的元素个数是argc个。

这两个参数是谁传给main函数的?

答:我们可以理解为父进程或者系统传递给main函数。

我们对mycmd进行文本编辑:

 

 当在命令行中输入的内容不断增多时,数组的内容也会自动变多。

我们可以这样理解:

 例如我们在Linux中可以这样调用指令:

 所以ls是一个程序,本质上也就是main函数,main函数的第一个参数我们不需要输入,随着第二个参数输入,第一个参数自动匹配,这里的-a -l -d表示我们向argv[]指针数组中传递的内容。

命令行参数的本质是依次把程序名和选项传递给数组argv

一共有几个选项,我们的argc就是多少,我们的argv数组的元素个数就是多少。

我们画图加强理解:

例如我们调用这样一个指令:

 

 

 然后把这些字符传递给argv数组,ls传向第一个元素位置,a传到第二个元素位置等等。

这个数组的最后元素位置存放的是空指针。

从把我们写的指令进行解析,到把每一个字符放到argv数组中,都是由我们的命令行解释器,也就是shell完成的。

但是传这些选项的意义又是什么呢?

我们对mycmd.c进行编辑:

 我们进行调用:

 所以我们可以通过命令行中的选项来决定我们要调用什么的功能。

这和我们的这些指令是等价的:

 main函数的第三个参数:

 env是一个环境变量参数,是一个指针数组。

数组env存储的是指向环境变量的指针。

环境变量数组的末尾也是空指针。

所以环境变量就能被我们的进程拿到了,我们就可以使用环境变量了。

接下来,我们对观点进行证明:

 如果我们的观点正确的话,我们应该可以打印出许多环境变量。

main函数最多三个参数

 第一个参数argc是第二个参数数组argv的元素的个数,第二个参数是指针数组argv,我们可以通过输入指令(字符串)来决定我们调用什么程序的什么选项,这些程序和选项就被存放到数组argv中,第三个参数是指针数组env,数组中存放的是环境变量,我们通过该数组可以访问环境变量。

所以我们通过指令+选项+环境变量最终调用成功了一个进程。

 所以解决上述一个问题:shell是怎么把环境变量传递给子进程的。

通过命令行参数,我们在shell中输入指令本质上就是调用main函数,我们把shell的环境变量以数组指针的形式传递给子进程,子进程就能够继承到环境变量了。

 正常情况下,假如我们的main函数并没有传递环境变量数组,我们怎么拿到环境变量。

我们可以通过getenv的形式得到环境变量。

 这里表示打印系统指令所在路径:

environ 

environ是一个二级指针,指向的是环境变量表:

 我们使用environ进行尝试:

 environ[i]表示*(environ+i),表示指向环境变量的指针,我们根据该指针就能打印出对应的环境变量。

显示了所有的环境变量。

 获取环境变量的三种方式:

最重要的是第一个getenv 

putenv

 表示更改或添加一个环境变量的值

stat

表示查看一个文件的所有属性:

例如:

 我们提出一个问题:

这是我们当前的目录,假如我们重新登录我们的用户:

 

 为什么pwd发生了变化。

因为我们的shell命令在我们重新登入用户时,检测我们的用户是bbb,用户的家目录是/home/bbb,然后我们通过某些cd命令就到了该路径下。

现象:

 

这两个到的路径是相同的,原因是cd ~检测到我们要到的路径是家目录,我们直接找到HOME环境变量,跳到HOME所在的路径处。

现象:

 我们在main函数进行传参时,传递的env[]数组实际上传递的是environ,为什么呢?因为函数传参要发生降维,例如我们要把整型a传递给main函数,我们要传递a的地址,否则我们只能完成值拷贝,env是指针数组,发生降维,降维之后的结果就是二级指针,也就是environ。

echo的问题:

echo是一个进程,是shell的子进程,echo可以继承环境变量,但是无法继承本地变量,为什么这里还能显示本地变量val的值。

程序地址空间

 我们之前讲的c++地址空间,这些空间的实质是什么?是内存吗?

不是内存,我们用现象进行解释:

 把全局的mycmd替换成为mytest

我们首先理解一个理念:

只要是一个进程,就要被操作系统管理,只要被操作系统管理,在创建子进程时,就要拷贝父进程的内核数据结构,例如父进程有pcb,在创建子进程时拷贝父进程的pcb。

我们对mytest.c进行文本编辑:

 我们创建一个变量global_value,接下来,我们创建子进程,当id<0表示fork失败,当id为0时,表示进行的是子进程,当id不为0时,表示进行的是父进程,我们在子进程运行到一定时间时修改global_value的值。

 当我们修改了global_value的值,该变量的地址没有修改,两个地址相同的变量值却不同证明了这里的地址并不是真实的内存。

换言之:我们c语言学到的所有的地址,空间等等都不是真实的内存。

所以这里的地址以及我们c语言学的地址都是虚拟地址(线性地址)

感性理解虚拟地址空间

 有一个大富翁,他有十亿美金,他有三个私生子,这些私生子都不知道彼此的存在,大富翁为了鼓励这些私生子努力工作,分别与三个孩子单独会面并且许诺他们在自己死后把全部的资产继承给这个孩子,所以所有的私生子都非常努力的工作,而且所有的私生子都认为十亿美金迟早是自己的。

但是私生子也需要花钱,于是每一个私生子就问大富翁要钱,每次只要1w美金。

 所以,这十个亿的美金只是大富翁给所有私生子画的一个大饼。

我们以系统的方式进行理解:

大富翁就是操作系统,十亿美金就是内存,这三个私生子就是进程,所有的进程都认为自己会独占系统资源(实际上,这只是操作系统给进程画的饼)。

所有私生子要的1w美金只是进程申请的资源和空间。

给每一个儿子画的大饼就是进程地址空间。

操作系统如何画饼呢?

首先,画饼的本质是老板给员工的脑海了构建一个蓝图,如图所示:

 假如有500个员工,老板和员工a许诺你以后要当部门总监,之后又对员工a许诺你以后要当总经理,这不就是乱套了吗?

所以不仅员工要被管理,老板画的饼也要被管理,老板画的饼叫做地址空间。

如何管理呢?

先描述,再组织。

所有的进程都以结构体的形式先描述,然后再以某种数据结构的形式再进行组织。

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

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

相关文章

Django框架之模型查询-关联查询

关联查询 查询书籍为1的所有人物信息 查询人物为1的书籍信息由一到多的访问语法&#xff1a; 一对应的模型类对象.多对应的模型类名小写_set 例&#xff1a; >>> book BookInfo.objects.get(id1) >>> book.peopleinfo_set.all() <QuerySet [<Peopl…

buntu18 安装 openpose(GPU)环境

openpose环境 搭建 很费劲&#xff0c; 需要装软件也多&#xff0c; 还必须要考虑版本的问题。我主要是参考链接 ubuntu18安装openpose详细步骤_litbo的博客-CSDN博客_ubuntu安装openpose 其中&#xff0c;我的实验中 有如下需要更改。 1、我的是 cuda-10.2 2、gcc 和g 必…

Linux下Socket编程利用多进程实现一台服务器与多台客户端并发通信

文章目录前言一、服务器 server二、客户端 client三、并发通信演示四、程序源码前言 前些日子同“ Linux应用编程 ”专栏中发布过的TCP及UDP在Linux或Windows下的通信都为单进程下的Socket编程&#xff0c;若还存在一些套接字相关函数模糊不清&#xff0c;读者可移步“Socket编…

整合K8s+SpringBoot+gRpc

本文使用K8s当做服务注册与发现、配置管理&#xff0c;使用gRpc用做服务间的远程通讯一、先准备K8s我在本地有个K8s单机二、准备service-providerpom<?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.…

Python3 模块实例及演示

在前面的几个章节中我们基本上是用 python 解释器来编程&#xff0c;如果从 Python 解释器退出再进入&#xff0c;那么定义的所有的方法和变量就都消失。 为此 Python 提供了1个办法&#xff0c;把这些定义存放在文件中&#xff0c;为一些脚本或者交互式的解释器实例使用&…

[oeasy]python0085_ASCII之父_Bemer_COBOL_数据交换网络

编码进化 回忆上次内容 上次 回顾了 字符编码的 进化过程 IBM 在数字化过程中 作用 非常大IBM 的 BCDIC 有 黑历史 &#x1f604; 6-bit的 BCDIC 直接进化成 8-bit的 EBCDIC补全了 小写字母 和 控制字符 在ibm就是信息产业的年代 ibm的标准 怎么最终 没有成为 行业的标准 呢…

OCR标注方法

虽然说标注工作不是由算法工程师负责的&#xff0c;但是如何标注&#xff0c;标注要求却是由算法工程师指导标注人员去实施的&#xff0c;如果标注工作人员标注的数据有问题&#xff0c;就会出现模型训练不收敛的问题&#xff0c;导致很多问题的出现&#xff0c;所以标注要求很…

MySql调优基础知识

MySql调优 调优金字塔 系统设计&#xff1a;数据不适合放入mysql&#xff0c;es、MQ、Redis、读写分离。 mysql调优&#xff1a;主要是索引且要熟悉业务。 mysql导致慢查询的原因是因为数据太多了。 1.sql查询 1.1尽量使用覆盖索引 1.2数据表结构&#xff0c;统计汇总&am…

普通单双面板的生产工艺流程之图形转移,华秋一文告诉你

衔接上文&#xff0c;继续为朋友们分享普通单双面板的生产工艺流程。 如图&#xff0c;第五道主流程为图形转移。 图形转移的目的为&#xff1a; 利用光化学原理&#xff0c;将图形线路的形状转移到印制板上&#xff0c;再利用化学原理&#xff0c;将图形线路在印制板上制作出…

Tomcat- AJP协议文件读取/命令执行漏洞(CVE-2020-1938 / CNVD-2020-10487)

CVE-2020-1938 1.概述1.1 tomcat概述1.2 gostcat概述 - 漏洞概述2. 漏洞成因2.1 前置基础2.1.1 Tomcat Connector(连接器)2.1.2 Servlet(服务程序)2.1.3 Tomcat内部处理请求流程2.2 源码追踪分析两个利用方案的执行流程2.2.1 获取利用poc2.2.2 文件读取漏洞关键点1&#xff1a;…

CSDN城市开发者联盟、C友会期待你的加入

文章目录&#x1f31f; 课前小差&#x1f31f; chatGPT&#x1f31f; CSDN中的持续学习&#x1f31f; 23年原力计划&#x1f31f; C友会、CDC&#x1f31f; 如何关联本地的开发者&#xff1f;&#x1f31f; 写在最后&#x1f31f; 课前小差 哈喽&#xff0c;大家好&#xff0c…

2月datawhale组队学习:大数据

文章目录一、大数据概述二、 Hadoop2.1 Hadoop概述2.2 su:Authentication failure2.3 使用sudo命令报错xxx is not in the sudoers file. This incident will be reported.2.4 创建用户datawhale&#xff0c;安装java8&#xff1a;2.5 安装单机版Hadoop2.5.1 安装Hadoop2.5.2 修…

excel报表技巧:几个关于汇报演示方面的小功能

年终了&#xff0c;总结汇报避免不了。如果你的PPT还不够好&#xff0c;那就直接用Excel做汇报吧~这里有5条小技巧&#xff0c;可以帮助你最高效地展示自己的成绩报表&#xff01;想象一下&#xff0c;用SHIFTCTRLF1全屏显示你的工作表&#xff0c;配合上CtrlPageDown进行工作表…

WMS系统解决方案,数据从“人工采集”转为“自动采集”

今年以来&#xff0c;新冠疫情危机促使国内企业重新审视自我发展&#xff0c;加速了行业转型的步伐。很多制造企业放慢了规模扩张的脚步&#xff0c;应需而变&#xff0c;从规模速度型向质量效率型转型升级。纵观市场现状&#xff0c;很多制造企业面临产能过剩、成本上升、库存…

CHAPTER 4 监控全网服务器

监控全网服务器4.1 需求说明4.2 规划方案4.2.1 api接口使用&#xff08;curl&#xff09;4.3 具体实施规划4.3.1 硬件、系统、网络监控4.3.2 应用服务监控4.3.3 监控服务通用方法4.4 实施全网监控4.4.1 使用自动发现规则4.4.2 监控备份服务器1. 添加模板2. 添加应用集3. 添加监…

【观察】Solidigm P44 Pro SSD评测:原厂品质+软硬兼施=性能怪兽

众所周知&#xff0c;目前SSD&#xff08;固态硬盘&#xff09;已取代HDD&#xff08;机械硬盘&#xff09;成为电脑中常见的存储设备&#xff0c;特别是在技术创新的持续推动下&#xff0c;如今SSD的速度和效率都在不断地提高&#xff0c;从SATA2 3GB发展到SATA3 6GB&#xff…

计算机组成原理学习笔记:循环冗余校验码

循环冗余校验码 CRC 码 循环冗余校验码 (cyclic redundancy Check, CRC) 十进制除法 从熟悉的十进制出发&#xff0c;假设现在你要给另一个人传送882这样的一个10进制数据&#xff0c;为了防止传送数据的过程中某一个数据发生错误你可以和你的另一个小伙伴约定一个除数&…

英文论文(sci)解读复现【NO.5】让RepVGG再次变得更强大:一种量化感知方法

此前出了目标检测算法改进专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读发表高水平学术期刊中的SCI论文&am…

2023年可见光通信(LiFi)研究新进展

可见光无线通信Light Fidelity&#xff08;LiFi&#xff09;又称“光保真技术”&#xff0c;是一种利用可见光进行数据传输的全新无线传输技术。LiFi是一种以半导体光源作为信号发射源&#xff0c;利用无需授权的自由光谱实现无线连接的新型无线通信技术&#xff0c;支持高密度…

内网渗透(三十六)之横向移动篇-Password Spraying密码喷洒攻击和域内用户枚举横向移动

系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内网渗透(五)之基础知识-Active Directory活动目录介绍和使用 内网渗透(六)之基…