之前笔者写过C/C++的程序内存区域划分
https://blog.csdn.net/qq_43909184/article/details/96652054
关键点来了,这并不是计算机内存的实际使用情况,我们看到的程序地址空间实际是一个虚拟地址空间,实际上是操作系统通过mm_ struct这 个结构体为进程描述的一个空间,因此有时候也称作内存描述符。
#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 -1;
} 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
- 变量内容不一样,所以父子进程输出的变量绝对不是同一个变量
- 但地址值是一样的,说明,该地址绝对不是物理地址!
- 在Linux地址下,这种地址叫做 虚拟地址
- 我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS统一管理
如下图解释上述代码运行结果的原因:
OS是如何管理内存的
分页式:把进程虚拟地址空间分成一页一页,物理内存分成一块一块,页和块的大小相同。通过地址中的页号去页表找到页表项,通过页表项中的物理页号加上页内偏移获取到物理地址。
可以通过下面例题理解
分段式:通过地址中的段号去段表找到段表项,通过段表项中的物理段号加上地址中的段内偏移获取到物理地址。
段页式:通过段号在段表中找到段表项中的段内页表地址找到段内页表,通过地址中的段内页号在段内页表中找到页表项,通过页表项中的物理页号与页内偏移组成物理地址。