Linux:环境变量、地址空间

目录

一、环境变量

1、什么是环境变量

2、常见的环境变量

3、环境变量相关命令

二、地址空间

1、进程地址空间

2、虚拟地址空间


一、环境变量

1、什么是环境变量

首先先举个环境变量的例子:

我们在Linux中,运行ls、pwd之类的命令,直接输入就能运行,输入路径**/usr/bin/ls/pwd**当然也能运行

那我们有一个可执行文件test,为什么不能直接输入test运行,必须要输入**./test**或是它的具体路径才能运行,如下:

其实很简单,因为像ls/pwd这些命令,是在环境变量path中已经配置过了,所以是默认可被找到的,如下图可见**echo path**:环境变量前加就可以看到里面内容

里面的路径是用冒号分割开的

可以看到里面有/usr/bin这个路径,而我们上面的pwd、ls都是在这个搜索路径当中

而我们的可执行程序并不在环境变量的搜索路径中,所以我们也就没办法直接执行

但是下面的export命令可以帮我们做到这一点


2、常见的环境变量

PATH:指定命令的搜索路径

HOME:指定用户的主工作目录

SHELL:当前的shell值,一般是/bin/bash


3、环境变量相关命令

①查看某个环境变量的值

echo $环境变量名字

②查看全部环境变量

查看当前系统全部的环境变量:env

③设置一个新的环境变量

export

执行export PATH=$PATH:/home/fcy/lesson后,再echo,就可以发现我们的/home/fcy/lesson这个路径,也被添加到搜索路径当中了

④清除环境变量

unset

⑤显示定义本地的shell变量和环境变量

set


二、地址空间

1、进程地址空间

首先回顾一下,地址空间的布局如下图:

下面用Linux验证一下地址空间的布局:

运行结果:

可以清楚看到,运行结果从上到下,分别是代码区,已初始化,未初始化,堆,栈

从上面的分布图可以知道,代码区,已初始化,未初始化,堆,栈是从低地址到高地址存储的,所以运行结果也是从小到大的


我们也可以发现,堆和栈的差别是非常大的,因为堆是由低地址向高地址存储,而栈是由高地址向低地址存储的,所以他们中间相隔的地址是很大的

下面验证堆是由低地址向高地址存储,而栈是由高地址向低地址存储的:

我们malloc的数据时在堆中开辟的,所以变量p0、p1、p2、p3是在堆上的,而开辟出来的p0、p1、p2、p3变量的地址是存在栈上的

结果如下:

观察结果可以看到,堆从heap0到heap3是在递增的,而栈从stack0到stack3是递减的

说明我们上面所说的堆是由低地址向高地址存储,而栈是由高地址向低地址存储的:

堆栈相对而生


static修饰的局部变量,本质就是将该变量开辟在全局区域

下面的内存打印结果可以看出来:

观察打印的地址可以看到,局部变量a1是栈里的,而a2前面加上了static,这时a2的地址就到了val与un_val那里得全局区域了

这就是为什么static修饰的局部变量,它的生命周期是全局属性的


2、虚拟地址空间

我们要知道虚拟地址空间的存在,至于怎么证明这个虚拟地址空间是存在的,看下面的证明:

有一个全局变量val,赋初始值为5,然后执行fork函数,有两个进程,分别进入if和else语句执行死循环,其中子进程在运行三次后,改变val的值,而父进程不改变,每次循环都打印val和val的地址

结果如下:

可以发现,在第四次循环后,子进程由于改变了val值,打印时val变为10,而父进程val仍为5,并且观察他们打印出来的val的地址,都是0x60103c

这时我们可以明白,一个变量val,值不同,一个5一个10,反而val的地址却是相同的,所以这里打印出来的0x60103c肯定不是真实的物理地址,而是虚拟地址

所以证明了虚拟地址空间的存在


接下来用虚拟地址空间解释一下上面代码中出现的情况

首先父子进程被创建,子进程继承了父进程的许多属性,所以他们的地址空间分布也基本一样,所以父子进程的val在虚拟地址空间中所处的位置也就相同,页表的映射关系也一样,所以父子进程的val打印出来的的虚拟地址相同

而当子进程通过页表的映射关系,想要找到对应的物理地址改变自己的val值时,操作系统又会给给子进程的val重新开辟一段物理空间,并改变子进程页表的映射关系,这时虽然父子进程val的虚拟地址相同,但通过页表映射的物理地址却是不同的了

所以做到了val值不同,打印出来的虚拟地址却是相同的

这种情况就叫做写时拷贝


那么为什么要有地址空间的存在呢?

1、地址空间和页表都是OS创建并维护的,所以想要使用地址空间和页表进行映射,都是在OS的监管之下的,所以凡是非法的访问或者映射,OS都会识别到,并终止这个进程,从而有效的保护了物理内存

2、地址空间的存在,可以将进程管理和内存管理通过页表进行解耦,两个模块互不影响,只需要通过页表建立映射关系即可

3、以统一的视角看待所有的进程,在系统底层用页表映射到不同的物理内存处,完成进程独立性的实现


相关推荐
JoyCong19983 分钟前
参数测评:ToDesk个人版、团队版、企业版的设备数、并发通道与安全能力对比
运维·服务器·网络·安全·智能手机·远程工作
zxanz16 分钟前
多域名、泛域名 SSL 怎么选?避开证书采购的溢价陷阱
服务器·网络协议·ssl
pirateeee14 分钟前
Yocto 构建基于官方 imx6ull-14x14-evk 的 ubuntu 镜像
linux·嵌入式硬件
梦想的初衷~19 分钟前
CESM2 完整实操学习大纲:环境搭建、案例运行、耦合模拟与代码开发
linux·地球系统模式·cesm2·气候模式模拟·clm 陆面模型·cam 大气模式·模式移植编译
无敌糖果21 分钟前
Nginx 后端error.log疯狂刷盘问题分析
运维·nginx
a59865224 分钟前
原生ARM云手机实测|ARM服务器底座,主流手游兼容性、闪退、帧率专项测试
服务器·arm开发·智能手机·云手机
a59865226 分钟前
工作室批量多开云手机|ARM 服务器方案成本解析、架构选型与踩坑总结
服务器·arm开发·智能手机·云手机
逐流人28 分钟前
ELK企业级日志分析系统:从零搭建集中化日志平台
运维·elk·云原生·云计算·日志分析
叼烟扛炮30 分钟前
Linux 学习笔记(三):文件管理与文本查看
linux·笔记·学习
Iruoyaoxh34 分钟前
linux-进程概念
linux