linux进程的内存分配内存空间,Linux进程的内存管理之malloc和mmap

本文深入探讨了Linux系统中进程内存的管理方式,介绍了进程内存的基本单位vma,并详细解析了heap和mmap在动态内存分配中的作用。文章还具体讲解了malloc函数如何根据分配内存大小选择使用brk或mmap进行内存分配。
摘要由CSDN通过智能技术生成

通过《Linxu进程的内存管理》,我们知道了进程内存的最小单位是vma,根据不同的用处又划分了不同类型的vma,比如

heap: 动态分配和释放的内存

stack: 存放局部变量和实现函数调用

mmap:文件区间映射到虚拟地址空间的内存映射

text,data,bss

这篇我们就看下进程动态申请的内存,我们知道进程动态申请内存的函数是malloc,这篇讲下其涉及到的vma,即heap和mmap。

malloc

在linux标准libc库种,malloc函数的实现会根据分配内存的size来决定使用哪个分配函数,当size小于等于128KB时,调用brk分配;当size大于128KB时,调用mmap分配内存。size可由M_MMAP_THRESHOLD选项调节。如下图:

ba463d2f7f3f387823dd00507cffbd01.png

sys_brk分配过过程主要是调整brk位置

sys_mmap分配过程中主要是在堆和栈中间(memory mapping segment)找一段空闲的虚拟内存

cc8f5ae0eeec7e722e2163c164e318c8.png

brk

堆内存是由低地址向高地址方向增长。分配内存时,将heap段的最高地址指针mm->brk往高地址扩展。释放内存时,把mm->brk向低地址收缩。

96d6350ed0f3ee46ff21e622d3a93f2b.png

完成这段申请后,只是开辟了一段区域,通常还不会立马分配物理内存,物理内存的分配会发生在访问时出现缺页异常后再处理,这个后续文章咱们再进一步分析。

SYSCALL_DEFINE1(brk, unsigned long, brk)

{

......

//都需要页对齐,方便映射,mm->brk可以理解为end_brk,即当前进程堆的末尾

newbrk = PAGE_ALIGN(brk);

oldbrk = PAGE_ALIGN(mm->brk);

if (oldbrk == newbrk)

goto set_brk;

/* Always allow shrinking brk. */

if (brk <= mm->brk) {

//对heap收缩,调用free就会满足这个条件,减少堆,执行unmap

if (!do_munmap(mm, newbrk, oldbrk-newbrk, &uf))

goto set_brk;

goto out;

}

/* Check against existing mmap mappings. */

next = find_vma(mm, oldbrk);

if (next && newbrk + PAGE_SIZE > vm_start_gap(next))

goto out;

/* Ok, looks good - let it rip. */

//对heap扩展,是brk函数的核心,里面创建一个vma,然后instert全局链表中

if (do_brk_flags(oldbrk, newbrk-oldbrk, 0, &uf) 

goto out;

set_brk: //设置这次请求的brk到进程描述符mm->brk中

mm->brk = brk;

populate = newbrk > oldbrk && (mm->def_flags & VM_LOCKED) != 0;

up_write(&mm->mmap_sem);

userfaultfd_unmap_complete(mm, &uf);

if (populate)

mm_populate(oldbrk, newbrk - oldbrk);

return brk;

out:

retval = mm->brk;

//释放信号量

up_write(&mm->mmap_sem);

return retval;

}

大概流程整理如下:

fce7700a7116e25dac6c2e183a757dc3.png

mmap

私有匿名映射:通常用于内存分配,堆,栈

共享匿名映射:通常用于进程间共享内存,在内存文件系统中创建/dev/zero设备

私有文件映射:通常用于加载动态库,代码段,数据段

共享文件映射:通常用于文件读写和进程间通信

33b1297435fc619a10c06399c1ead78b.png

如果想进一步了解释,请参考文章《告别“一页障目”》。

unsigned long do_mmap(struct file *file, unsigned long addr,

unsigned long len, unsigned long prot,

unsigned long flags, vm_flags_t vm_flags,

unsigned long pgoff, unsigned long *populate,

struct list_head *uf)

{

......

//获取未映射区域

addr = get_unmapped_area(file, addr, len, pgoff, flags);

if (offset_in_page(addr))

return addr;

addr = mmap_region(file, addr, len, vm_flags, pgoff, uf);

......

return addr;

}

整理流程如下:

5f80e7ec46974f0591c3860d8cee2555.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值