LINUX进程地址空间

文章探讨了C/C++中虚拟地址的概念,解释了Linux下虚拟地址的原理,涉及页表如何映射虚拟地址到物理地址,以及栈、堆的内存管理。还讨论了fork函数的工作机制,写时拷贝以及虚拟地址到物理地址的转换过程由MMU完成。
摘要由CSDN通过智能技术生成

目录

1.虚拟地址

2.页表 

3.总结

4.拓展知识细节


引言:想必大家在学习c语言的时候都看到过,这样的一张图片,再c语言的学习时候呢,我们都知道局部变量是存在栈区的动态开辟的内存是存在堆区的常量字符串是存在字符常量区的等等,但是这样图你是否是真的了解了呢,我们动态开辟的内存是不是真的就在内存中开辟一块的空间呢?

1.虚拟地址

这段代码,我们用fork创建了一个子进程,父进程和子进程会同时执行printf

#include<stdio.h>
#include<unistd.h>

int main()
{
    pid_t pid = fork();
    printf("pid:%d path:%p\n",pid,&pid);
    return 0;
}

执行结果

我们神奇的发现,pid一个变量竟然有两个值而且这两货的地址还是相同的,由这个现象可以得出2个结论

(1)变量的内容不同,所以这两个pid绝对不是一个pid

  (2)   地址不同,这个地址绝对不是内存中真实的地址。

解释:(1)在linux下这种地址叫做虚拟地址

             (2)  c/c++中的地址一概是虚拟地址,真实的物理地址是由操作系统统一管理,用户看不到,这也是一种对操作系统的保护

2.页表 

简单理解:页表可以分为两块,左边存储着虚拟地址,右边存着物理地址,页表把虚拟的地址经过映射,映射到物理地址。

虚拟地址------>映射关系------>物理地址

3.总结

有了上面的知识储备,我们也就能解释,为什么一个变量有两个值,地址是相同的问题。

虽然这两变量的虚拟地址是相同的,但是别忘了,映射关系可以不同,修改一下映射关系,子进程pid地址就可以映射到物理地址的其他位置。

下图可以非常清楚的表示

4.拓展知识细节

1.在地址空间,栈和堆的大小,其实是由个整形变量维护的,就像画了两条线,这两条线之间就是堆或者栈的大小。

2.当在虚拟地址空间动态开辟内存时,不会直接为其分配物理内存,使用时会引发缺页中断,这个时候操作系统介入,为其分配物理内存。

3.fork()创建子进程,首先会以父进程为模板,创建task_struct,然后指向父进程的地址空间,当子进程要对变量修改时会发生写时拷贝。

4.fork()之后代码子进程和父进程共享

5.虚拟地址到物理地址的转换,是cpu中一个叫MMU的寄存器做的

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值