1.程序地点空间的引入
fork()函数在调用的时间子假如是子进程则返回0,假如是父进程则返回子进程的pid,在代码中我们分别在子进程和父进程读取全局变量g_val的时间居然出现了俩个不同的值。如下:
- #include<stdio.h>
- #include<unistd.h>
- #include<stdlib.h>
- int g_val = 0;
- int main()
- {
- pid_t id = fork();
- if(id == 0)
- {
- g_val = 100
- int i = 5;
- while(i--)
- {
- printf("我是子进程,g_val值为:%d,g_val的地址:%p\n",g_val,&g_val);
- sleep(1);
- }
- }
- else
- {
- int i=5;
- while(i--)
- {
- printf("我是父进程,g_val值为:%d,g_val的地址为:%p\n",g_val,&g_val);
- sleep(1);
- }
- }
- return 0; }
复制代码 实行结果:
[xvjiyi@hecs-399428 20240712_pragramAddressSpace]$ ./mytest
我是父进程,g_val值为:0,g_val的地点为:0x7ffd52f7b964
我是子进程,g_val值为:100,g_val的地点为:0x7ffd52f7b964
我是父进程,g_val值为:0,g_val的地点为:0x7ffd52f7b964
我是子进程,g_val值为:100,g_val的地点为:0x7ffd52f7b964
我是父进程,g_val值为:0,g_val的地点为:0x7ffd52f7b964
我是子进程,g_val值为:100,g_val的地点为:0x7ffd52f7b964
我是父进程,g_val值为:0,g_val的地点为:0x7ffd52f7b964
我是子进程,g_val值为:100,g_val的地点为:0x7ffd52f7b964
我是父进程,g_val值为:0,g_val的地点为:0x7ffd52f7b964
我是子进程,g_val值为:100,g_val的地点为:0x7ffd52f7b964
这个时间我们发现明明读取的地点相同为什么会读出俩个不同的值呢?既然读出了俩个值,阐明这俩个值存在不同空间里,定然不大概地点相同,唯一的表明就是这个地点不是真实的地点。事实也正是如许,这里读取到的地点是虚拟地点,虚拟地点空间也就是程序地点空间的产物,接下来我们来看程序地点空间,以及虚拟地点的实现机制。
2.程序地点空间
2.1虚拟地点空间介绍
程序地点空间本质是一个结构体(我们认为是 struct mm_struct),这个结构体记录着不同内存区间的在这个程序地点空间的相对地点(不是真正的物理地点),映射关系如下:
2.2页表
当进程访问地点的时间访问的是虚拟地点,那我们终极是怎样访问到物理地点的呢?当进程地点空间建立时,操作系统会建立一张页表完成虚拟地点到物理地点的映射,如下:
2.3 子进程父进程访问全局变量出现俩个不同值
接下来我们回到开头的问题,为什么我们会在同一个地点上访问到俩个不同的值。这是因为子进程继承了父进程的地点空间,父子进程在访问这个全局变量时访问的虚拟地点是一致的,而这俩个虚拟地点映射的物理地点不同,而我们的数据是存放在物理内存中的,也就造成了同一个地点出现了俩个不同值的假象。(至于为什么会存放在不同的物理内存中在下一节进程控制中给大家讲解,为了确保进程的独立性相互之间不影响,发生了写时拷贝)。
3.扩展
3.1为什么要有地点空间
假如没有进程地点空间,物理内存就可以被随意访问,可以随意改动不属于自己的空间,系统安全性大大降低。我们有了地点空间有以下长处:
- 1.当进程访问到不属于该进程的空间时,操作系统可在页表映射时拒绝进程的访问,有效杜绝了物理地点被随意访问,大大包管了物理内存和其他进程的安全。
- 2.将进程管理与内存管理解耦合。
- 3.让进程以统一的视角看待自己的代码和数据。
3.2 malloc申请空间的实质
当进程利用malloc申请空间时,在访问页表的时间操作系统不会给你立马分配物理地点,而会发生缺页中断,在进程需要访问这块空间时才给你分配空间。
3.3程序的加载
程序编译在加载的时间并不是一股脑全部加载到物理内存中,而是实行多少加载多少,一边实行一边加载。(源代码在被编译时早就将源代码和数据按照程序地点空间的方式完成了编址)
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |