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


相关推荐
2501_907136824 分钟前
离线工具箱 内含53个小工具
linux·服务器·网络
时空潮汐12 分钟前
神卓N600 NAS身份核验功能深度解析
linux·运维·网络·神卓nas·神卓n600 pro·家庭轻nas
哈哈浩丶19 分钟前
安卓系统全流程启动
android·linux·驱动开发
小李独爱秋19 分钟前
模拟面试:用自己的话解释一下lvs的工作原理
linux·运维·面试·职场和发展·操作系统·lvs
百锦再41 分钟前
Jenkins 全面精通指南:从入门到脚本大师
运维·后端·python·servlet·django·flask·jenkins
隔壁老王的代码42 分钟前
Jenkins的流水线详解
运维·servlet·jenkins
一路往蓝-Anbo1 小时前
第 7 章:内存地图 (Memory Map) 深度设计——DDR 与 SRAM
linux·stm32·单片机·嵌入式硬件·网络协议
珹洺1 小时前
Java-servlet(五)手把手教你利用Servlet配置HTML请求与相应
java·运维·服务器·前端·servlet·html·maven
BHXDML1 小时前
VMware Workstation Pro 安装详细教程(超详细图文讲解)
linux·虚拟机
一路往蓝-Anbo1 小时前
第 8 章:M33 领航——引导 A35 加载 U-Boot 与 Linux 内核
linux·运维·服务器·stm32·单片机·嵌入式硬件·网络协议