文章目录
- 初识进程地址空间
- 进程地址空间的具体分布和演示
- 用户空间 VS 内核空间
- Linux VS Windows
初识进程地址空间
首先我们用代码演示一个问题大家思考一下。
#include <stdio.h>
#include <unistd.h>
int g_val = 100;
int main()
{
pid_t id = fork();
if(id == 0)
{
//子进程5秒后更改g_val的值
int cnt = 0;
while(1)
{
printf("I am child pid:%d ppid:%d g_val:%d &g_val:%p\n",getpid(),getppid(),g_val,&g_val);
if(cnt == 5)
{
g_val = 200;
printf("g_val changed success\n");
}
cnt++;
sleep(1);
}
}
else
{
//父进程g_val的值一直不变
while(1)
{
printf("I am father pid:%d ppid:%d g_val:%d &g_val:%p\n",getpid(),getppid(),g_val,&g_val);
sleep(1);
}
}
return 0;
}
代码运行结果:
这里我们可以看到一个现象,同一个地址的g_va,同时读取的时候,竟然会出现两个不同的值!
所以为什么会出现这样的现象?后面博客解释。
进程地址空间的具体分布和演示
代码验证:
运行结果:
堆栈相对而生的
验证:
运行结果:
我们可以看到,堆的地址一直在增大,栈的地址一直在减小。
我们学过static,static修饰变量是表示把该变量变为全局变量,那么该变量在进程地址空间中的地址是在栈区还是在全局区?
代码演示:
运行结果:
我们以前面的认知可以看出这是在全局区域。
用户空间 VS 内核空间
我们从上面的地址空间图可以看出进程地址空间分为
用户地址空间和内核地址空间
32位操作系统下:
用户地址空间范围:[0,3GB]
内核地址空间:[3GB,4GB]
Linux VS Windows
前面的哪些验证代码,在Windows下会跑出不一样的结果。
之前的结果默认在Linux下有效。