计算机得物理内存大小是固定的,就是计算机主板内存槽上的实际物理空间,CPU可以直接继续寻址,物理内存的容量是固定的,但是寻址的卡空间取决于CPU地址线的数量。32位系统上,线性地址空间可达4G,那么这4G的内存是如何分配的呢?一般情况下,是以3:1来分配的,用户进程配有3G的空间,而内核独自配有1G的内存。 在C语言的学习期间,大家都学习了这样得空间分布图:
写段代码来测试一下吧
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int val = 10;
int main()
{
pid_t id = fork();
if(id<0){
perror("fork");
return 0;
}
if(id == 0){
//child
printf("child[%d] val = %d &val = %p\n",getpid(),val,&val);
}
else{
//parent
printf("parent[%d] val = %d &val = %p\n",getpid(),val,&val);
}
sleep(1);
return 0;
}
//打印结果:
/*
parent[1297] val = 10 &val = 0x60104c
child[1298] val = 10 &val = 0x60104c
*/
我们发现,输出出来的变量和地址是一模一样的,难道是因为子进程是按照父进程位模板,父子并没有对变量进行任何修改?
那么我们换一个代码版本来看看。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int val = 10;
int main()
{
pid_t id = fork();
if(id<0){
perror("fork");
return 0;
}
if(id == 0){
//child
val = 100;
printf("child[%d] val = %d &val = %p\n",getpid(),val,&val);
}
else{
//parent
sleep(3);//让子进程先运行完
printf("parent[%d] val = %d &val = %p\n",getpid(),val,&val);
}
sleep(1);
return 0;
}
//打印结果
/*
child[1948] val = 100 &val = 0x60104c
parent[1947] val = 10 &val = 0x60104c
*/
什么!一样的地址居然存放着不同的值!这是不可能的。 那么真相就出来了。
先前所说的程序的地址空间是不正确的,准确的应该说成进程地址空间,那该如何理解呢?
同一个变量,地址相同,其实是虚拟地址相同,内容不同是因为映射到了不同的物理地址。
页表的概念:
在早期的时候,计算机还没有虚拟机制,程序指令所访问的内存地址就是物理地址,所以就要将所有程序都加载到内存中,但是我们实际的物理内存是有限的,那么就会出现一些问题: