一、程序地址空间
验证
1 #include<stdio.h>
2 #include<unsitd.h>
3 #include<stdlib.h>
4
5 int g_val = 0;
6 int main()
7 {
8 pid_t id = fork();
9 if(id > 0){
10 perror("fork");
11 return 0;
12 }
13 else if(id == 0){//child
14 printf("child[%d]:%d:%p\n",getpid(),g_val,&g_val);
15 }
16 else{//parent
17 printf("parent[%d]:%d:%p\n",getpid(),g_val,&g_val);
18 }
19 sleep(1);
20 return 0;
21 }
发现父进程和子进程输出来的变量值和地址一样。
原因:子进程按照父进程为模板,父进程并没有对变量进行任何修改
将上述代码稍微改动:
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<stdlib.h>
4
5 int g_val = 0;
6
7 int main()
8 {
9 pid_t id = fork();
10 if(id < 0){
11 perror("fork");
12 return 0;
13 }
14 else if(id == 0){//child
15 g_val = 50;
16 printf("child[%d]:%d:%p\n",getpid(),g_val,&g_val);
17 }
18 else{//parent
19 sleep(2);
20 printf("parent[%d]:%d:%p\n",getpid(),g_val,&g_val);
21 }
22 sleep(1);
23 return 0;
24 }
发现:父子进程的地址是一样的,但变量值使不一样的
结论:
·变量内容不一样,所以父子进程输出的变量绝对不是同一个变量
·但地址值是一样的,说明,该地址绝对不是物理地址
·在Linux下,这种地址叫虚拟地址
·在C/C++语言看到的都是虚拟地址,而物理地址用户是看不到的
二、进程的地址空间
1、早期内存管理机制
相关内容:
(1)要运行一个程序,会把这些程序全部装入内存
(2)当计算机同时运行多个程序时,必须要保证这些程序要用到的内存总量小于计算机实际物理内存的大小
(3)进程地址空间不隔离
(4)内存使用效率低
(5)程序运行的地址不确定
三、分段
相关介绍:
(1)在编写代码时,只要指明了所属段,代码段和数据段中出现的所有地址都是从0开始,映射关系完全由操作系统维护
(2)CPU将内存分成了不同的段,于是指令和数据的有效地址并不是真正的物理地址而是相对于段首地址的偏移地址
所解决的问题:
(1)因为段寄存器的存在,使得进程的地址空间得以隔离,越界问题很容易就被判断出来
(2)实际代码和数据中的地址都是偏移量,所以第一条指令可以从0开始系统会自动进行转化映射,解决了程序运行的地址不确定
(3)分段问题并没有解决
四、分页&虚拟地址空间
同一个变量,地址相同其实是虚拟地址相同,内容不同是因为被映射到了不同的物理地址