OK6410A 开发板 (八) 51 linux-5.11 OK6410A glibc提供的mmap与malloc

本文详细探讨了glibc-2.18中的mmap和malloc函数。mmap主要用于文件读写,通过不同的flags实现私有匿名映射、共享匿名映射、私有文件映射和共享文件映射。而malloc则是用户空间内存分配器,使用mmap和brk系统调用管理内存。在内存不足时,malloc会通过brk和mmap向内核申请。文章还介绍了内存分配的多个阶段和glibc中的内存管理结构。
摘要由CSDN通过智能技术生成
glibc

根据 rootfs中的动态链接库来源 可以看到 glibc 来自于 交叉编译工具链,且glibc版本为 glibc-2.18

我们探究一下 glibc-2.18 中 mmap 以及 malloc 函数的定义以及实现
glibc 代码 在 http://ftp.gnu.org/gnu/glibc/
mmap
  • 简介
mmap 是glibc提供的函数,也是系统调用
  • 应用
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);

mmap 函数 有个参数 flags , 可以根据 flags 将 mmap 分为四种情况
	A1. 私有匿名映射	: 用于 分配大块内存(128KB及以上)
		fd = -1 flags=MAP_ANONYMOUS|MAP_PRIVATE
	A2. 共享匿名映射  : 用于 父子进程通信
		fd = -1 flags=MAP_ANONYMOUS|MAP_SHARED
	B1. 私有文件映射	: 用于 加载动态共享库
		fd >=0 flags=MAP_PRIVATE
	B2. 共享文件映射	: 用于 读写文件/进程间通信
		fd >=0 flags=MAP_SHARED


可以这么讲,mmap就是为了读写文件存在的,读写文件流程一直在优化,在linux上,分为几个阶段
	1. 直接读写磁盘 // 缺点是每次读写都要陷入内核空间,都要转动磁盘
	2. 页缓存技术	  // 缺点是每次读写都要陷入内核空间
	3. 页缓存技术+fread/fwrite // 缺点是增加了数据在不同缓冲区复制的次数
	4. mmap技术 	  // 优点 : 减少系统调用和内存复制的次数

  • 具体实现

glibc-2.18/ports/sysdeps/unix/sysv/linux/generic/wordsize-32/mmap.c
__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
	return (__ptr_t) INLINE_SYSCALL (mmap2, 6, addr, len, prot, flags, fd, offset >> MMAP_PAGE_SHIFT);
weak_alias (__mmap, mmap)

linux-5.11/arch/arm/include/generated/uapi/asm/unistd-common.h
155 #define __NR_mmap2 (__NR_SYSCALL_BASE + 192)

malloc
  • 简介
malloc 是glibc提供的函数,不是系统调用
底层封装的是 系统调用mmap 和 系统调用brk
  • 应用
用于 申请小块内存(128KB以下,不包括)
  • 实现理论
用户空间的 内存分配器
为了减少系统调用带来的开销(提高内存申请效率)
在 glibc 中实现了用户空间的内存分配器(ptmalloc/ptmalloc2)
用户申请的内存被 ptmalloc 管理 , 每一个内存块被称为 chunk,用 malloc_chunk 表示
将相同种类的 chunk 放到 链表bin中,128个bin
128个bin 被分类为
	unsorted bin
	fast bins
	small bins
	large bins

但是如果 用户空间的 内存管理器 没有内存的话,还是要向内核申请内存
用的是系统调用,包括两种
	1. brk
	2. mmap



1.获取分配区的锁。  

2.根据用户的需要申请的大小算出给与的大小。

3.判断所需要的大小 <= max_fast,是就跳转第5步,否则下一步

4.首先在fast bin 找,找不到就下一步,否则下一步

5.size <= 512B ,判断是否在small bin 中,如果在就下一步,否则就第66.找到一个合适的chunk 大小,否则就下一步

7.到了这一步,可以看到这是一个很大size了,先遍历fast bins 合并空闲块到unsorted bin 再次合并这个块里的大小,再次比对大小信息,如果可以分配就切割大小并且将剩下的部分加入到small bin 或者 large bin 中。如果依然 < SIZE 调转下一步。

8.此时我们就表示我们从fast small unsorted 都找不到合适的块的大小,所以我们就到large bin 中寻找合适的大小。如果没有找到,就调转下一步了。

9.走到这里基本上就是说这个块非常打了,所以我们就动用TOP chunk 改变堆的大小了,如果依然不能满足需求。调转下一步。

10.这时候判断SIZE 和 mmap()分配阀值的大小。如果大于分配阀值就使用mmap()函数分配,否则调用sbrk()扩大堆的大小。

  • 具体实现
glibc-2.18/misc/sbrk.c
33 __sbrk (intptr_t increment)
	__brk
weak_alias (__sbrk, sbrk)


glibc-2.18/ports/sysdeps/unix/sysv/linux/arm/brk.c
__brk (void *addr)
	__curbrk = newbrk = (void *) INLINE_SYSCALL (brk, 1, addr);
weak_alias (__brk, brk)
linux-5.11/arch/arm/include/generated/uapi/asm/unistd-common.h
36 #define __NR_brk (__NR_SYSCALL_BASE + 45)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值