1.程序地址空间的概率(C/C++的说法不够准确)
写一段代码来来证明C/C++程序地址空间是按上图分布的:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int uninit;
int init=100;
int main()
{
printf("code addr:%p\n",main);
const char* s="hello world!";
printf("string addr:%p\n",s);
printf("uninit addr:%p\n",&uninit);
printf("init addr:%p\n",&init);
const int* ph=(int*)malloc(40);
const int* ph1=(int*)malloc(20);
printf("heap addr1:%p\n",ph);
printf("heap addr2:%p\n",ph1);
printf("stack addr1:%p\n",&ph);
printf("stack addr2:%p\n",&ph1);
return 0;
}
执行结果:
2.进程地址空间
先看一段代码,证明进程的地址空间不是真实的物理内存:
#include<iostream>
#include<unistd.h>
using std::cout;
using std::endl;
int main()
{
int tmp=10;
if(fork()==0)
{
tmp=20;
cout<<"tmp:"<<tmp<<" addr:"<<&tmp<<endl;
}
else
{
cout<<"tmp:"<<tmp<<" addr:"<<&tmp<<endl;
}
return 0;
}
执行结果:相同的地址当时不同的变量值,那么说明父进程和子进程的地址空间不是真实的物理内存
进程PCB有指向mm_struct的指针
通过页表让虚拟地址和物理内存建立映射
解释上面父子进程地址相同数值不同
3.为什么要有进程地址空间或者说它有什么优势呢?
1.通过进程地址空间,完成且有效的对于进程操作内存进行权限管理,本质就是保存物理内存及各个进程的数据安全
#include<stdio.h>
int main()
{
char* s="hello wrold!";
*s='H';//字符常量区的数据是不可以改变的
return 0;
}
2.内存申请和内存使用分离的概念在时间上划分清楚;
例如:申请1000int的空间,先把虚拟地址写到页表,直到你使用才把物理内存地址写到页表中,可以让资源得到更好的应用