linux 内存布局 mmap,进程的内存布局

进程的内存布局

内存地址由高到低依次是:

kernel space

stack:向下增长

dynamic libraries:共享库载入的空间

heap:向上增长

read/write sections(.data .bss):属于可执行文件映像

readonly sections(.init .rodata .text):属于可执行文件映像

reserved:内存中受到保护而禁止访问的内存区域

动态库和栈之间,动态库和堆之间仍有可使用的空间,因此栈和堆才能增长。此外,其他区域之间也并不是一定是连续的。

段错误(segment default):非法指针解引用所引起的错误。例如,指针指向不允许读写的地址,或者指针指向的地址并没有映射到实际的物理内存。

多线程下的内存布局

上面所说的内存布局是《程序员的自我修养》上讲的,在《Linux环境编程》上提到了多线程进程的内存布局:

ea32347848e2

《Linux环境编程》插图7-7

mmap区域指的是执行系统调用mmap()所分配出来的区域,这块区域又称为文件映射区。mmap()的作用是向操作系统申请一块虚拟地址空间。可以指定某个文件来填充这块空间(文件映射),也可以不指定(分配匿名空间)。

mmap()调用后,仅仅是消耗了虚拟地址空间,创建/更改了内存映射所需的数据结构(页表),并没有映射到物理页。当进程后续访问这些虚拟地址的时候,会发现这些虚拟内存页没有对应的物理页,然后发生页错误(Page Default)。在处理页错误的过程中才分配物理页(如果调用mmap时指定了文件,就把磁盘中的文件拷贝到物理页中),并建立映射。此时分配的虚拟内存才变得真正可用。

页错误也是缺页中断。除了第一次访问mmap分配的页(因为没有映射到物理页)会引发页错误外,后续访问时,如果物理页已经换出到外存,也会引发页错误。

glibc中malloc的实现

在标准C库中,提供了malloc函数来分配一块虚拟内存空间。

glibc下malloc获取的空间的来源有两个:brk系统调用,mmap系统调用。

(有人把malloc管理的空间统称为堆,也有人只把brk系统调用分配的空间称之为堆,下面说的都取前者的含义)

brk的作用是设置进程数据段的结束地址。如果把数据段的结束地址向高地址移动,那么扩大的那部分空间就可以拿来作为堆空间使用。

mmap是在进程的虚拟地址空间中(brk分配的空间和栈之间的一块内存,称为文件映射区)分配一块空闲的虚拟内存。

对于小于128KB的请求,malloc会在现有的堆空间里面,按照堆分配算法分配一块空间并返回;对于大于128KB的请求,malloc会使用mmap系统调用分配一块匿名空间,然后在这块匿名空间中为用户分配空间。

这两种方式分配的都是虚拟内存,没有分配物理内存。在第一次访问已分配的虚拟地址空间的时候,发生缺页中断,操作系统负责分配物理内存,然后建立虚拟内存和物理内存之间的映射关系。

Reference

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值