概述
Linux概念——进程地址空间
- <1> 进程地址空间
- Q1:什么是地址空间?
- <2> 虚拟地址空间
- Q2:为什么要有地址空间?
- Q3: 地址空间时怎么工作的?
- <3> 页表
<1> 进程地址空间
对于C语言学习,我们并不陌生这张图
我们编写一段C语言代码来验证上述图的准确性
#include<stdio.h>
#include<stdlib.h>
int g_val = 100;
int g_unval;
int main(int argc, char* argv[], char* env[])
{
//环境变量
printf("env addr:%pn", env[0]);
printf("env addr:%pn",env[1]);
//命令行参数
printf("argv addr:%pn",argv[0]);
printf("argv addr:%pn",argv[argc-1]);
char* mem = (char *)malloc(sizeof(char)*4);
//栈
printf("Stack addr:%pn",&mem);
//堆
printf("Heap addr:%pn",&mem);
//未初始化数据
printf("uninit addr:%pn",&g_unval);
//初始化数据
printf("init addr:%pn",&g_val);
//正文代码
printf("code addr:%pn",&main);
return 0;
}
结果
可以看到对于程序中定义的变量打印出来的地址全部都一一对应了
Q1:什么是地址空间?
地址空间是对物理内存的一种虚拟化表示,在Linux内核中以结构体的形式划分为不同的区域。
<2> 虚拟地址空间
既然前面说到了进程空间是一种虚拟化表示,我们运行下面代码来验证进程地址空间
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int g_val = 0;
int main()
{
pid_t id = fork();
if(id < 0)
{
perror("fork");
return 0;
}
else if(id == 0)
{ //child
printf("child[%d]: %d : %pn", getpid(), g_val, &g_val);
}
else
{ //parent
printf("parent[%d]: %d : %pn", getpid(), g_val, &g_val);
}
sleep(1);
return 0;
}
由结果可以看出,父进程的全局变量地址和子进程的全局变量地址相同,正好对应了进程空间地址那张图,那么我们稍作修改
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int g_val = 0;
int main()
{
pid_t id = fork();
if(id < 0)
{
perror("fork");
return 0;
}
else if(id == 0)
{ //child ,子进程肯定先跑完,也就是子进程先修改,完成之后,父进程再读取
g_val = 100;
printf("child[%d]: %d : %pn", getpid(), g_val, &g_val);
}
else
{ //parent
sleep(3);
printf("parent[%d]: %d : %pn", getpid(), g_val, &g_val);
}
sleep(1);
return 0;
}
我们发现,父子进程,输出地址是一致的,但是变量内容不一样!
能得出如下结论:
- 变量内容不一样,所以父子进程输出的变量绝对不是同一个变量
- 但地址值是一样的,说明该地址绝对不是物理地址!
- 在Linux地址下,这种地址叫做虚拟地址。
- 我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS统一管理
Q2:为什么要有地址空间?
- 如果没有地址空间,那么进程访问的地址都是物理地址,当一个进程的指针去读写另一个进程的地址时,出现野指针现象,导致别人的空间遭到破坏,从而违背了进程的独立性原则。
- 进程数据存放的位置时不连续的,因此访问难度较大,也增加了异常越界的概率。
Q3: 地址空间时怎么工作的?
- 既然地址空间时虚拟的,那么OS必须负责将 虚拟地址 转化成 物理地址 , 这中间就需要建立映射关系——页表来进行转换。
- 由操作系统去访问物理内存,人为干扰的进程非法行为将被禁止,堆内存起到了保护作用。
<3> 页表
上面的图就足矣说名问题,同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了不同的物理地址!
最后
以上就是热心大树为你收集整理的Linux概念——进程地址空间的全部内容,希望文章能够帮你解决Linux概念——进程地址空间所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复