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


相关推荐
李先静1 分钟前
用 gdbserver 调试 arm-linux 上的 AWTK 应用程序
linux·arm开发·awtk
地球空间-技术小鱼2 分钟前
YUM(Yellowdog Updater, Modified)和DNF(Dandified YUM)简介
linux·运维·服务器·笔记·学习
忆源3 分钟前
Linux高级--2.4.2 linux TCP 系列操作函数 -- 深层理解
linux·网络·tcp/ip
@泽栖19 分钟前
阿里云-将旧服务器数据与配置完全迁移至新服务器
服务器·阿里云
ZHOUPUYU33 分钟前
Centos常用命令,按功能分类,用户和权限管理等
linux·运维·centos
vvw&1 小时前
如何在 Ubuntu 22.04 上安装 phpMyAdmin
linux·运维·服务器·mysql·ubuntu·php·phpmyadmin
手心里的白日梦1 小时前
TCP协议
服务器·网络·tcp/ip
灰勒塔德2 小时前
Linux文件IO
linux·运维·服务器
dntktop2 小时前
解锁自动化新高度,zTasker v2.0全方位提升效率
运维·windows
我曾经是个程序员2 小时前
C#Directory类文件夹基本操作大全
服务器·开发语言·c#