文章目录
- 1.程序地址空间回顾
- 2.进程地址空间
1.程序地址空间回顾
我们在讲C语言的时候,老师给大家画过这样的空间布局图
可是我们对他并不理解!
来段代码感受一下:
#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 : %p\n", getpid(), g_val, &g_val);
}
else
{ //parent
printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);
}
sleep(1);
return 0;
}
输出
//与环境相关,观察现象即可
parent[2995]: 0 : 0x80497d8
child[2996]: 0 : 0x80497d8
我们发现,输出出来的变量值和地址是一模一样的,很好理解呀,因为子进程按照父进程为模版,父子并没有对变量进行进行任何修改。可是将代码稍加改动:
#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 : %p\n", getpid(), g_val, &g_val);
}
else
{ //parent
sleep(3);
printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);
}
sleep(1);
return 0;
}
//与环境相关,观察现象即可
child[3046]: 100 : 0x80497e8
parent[3045]: 0 : 0x80497e8
输出结果:
//与环境相关,观察现象即可
child[3046]: 100 : 0x80497e8
parent[3045]: 0 : 0x80497e8
我们发现,父子进程,输出地址是一致的,但是变量内容不一样!能得出如下结论:
-
变量内容不一样,所以父子进程输出的变量绝对不是同一个变量
-
但地址值是一样的,说明,该地址
绝对不是物理地址
! -
在Linux地址下,这种地址叫做
虚拟地址
。 -
我们在用C/C++语言所看到的地址,全部都是虚拟地址!
物理地址,用户一概看不到
,由OS统一管理。
OS必须负责将 虚拟地址 转化成 物理地址 。
2.进程地址空间
所以之前说‘程序的地址空间’是不准确的,准确的应该说成 进程地址空间
,那该如何理解呢?看图:
说明:
- 上面的图就足矣说名问题,同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了不同的物理地址!