C标准库里的3个分配函数
- malloc 不负责把分配的内存空间清零
- calloc 会负责把分配的内存空间用字节0填充
- realloc 调整已分配的内存大小
POSIX标准中定义的分配函数 alloca 不是在堆上分配空间,而是在调用者函数的 栈帧上分配空间,类似于 C99 的变长数组,当调用者函数返回时自动释放栈帧 所以不需要free 这个函数不属于 C 标准库,而是在 POSIX 标准中定义的。
- 内核中采用了同时能适用于32位和64位的内存模型
- 对于32位系统,两级也表足够
- 对于x86_64位系统,使用了四级页表(PGD,PUD,PMD,PT)
- 默认情况内核使用4KB的页框大小作为标准分配单元
实际应用中,经常需要分配一组连续的页框,而频繁的申请和释放不同大小连续页框必然会导致在已分配页框的内存块中分散许多小块的空闲页框,这样即使这些页框是空闲的,其他需要分配连续页框的应用也很难得到满足
为了避免出现这种情况,linux内核中引入来伙伴系统算法(Buddy System)把所有空闲的页框分组为11个块的链表,每个链表分别包含大小为1,2,4,8,16,32,64,128,256,512,1024个连续页框的页框块,最大可以申请1024个连续页框(1024x4KB = 4MB)
假设需要申请一个256个页框的块,先从256个页框的链表中查找空闲的块,如果没有,就去512个页框的链表中找,找到了则将页框分为2个256个页框的块,一个分配给应用,另外一个移动到256个页框的链表中。如果512个页框的链表中仍然没有空闲块,则继续在1024个页框的链表中查找,没有则返回错误
页框块在释放时,会主动将两个连续的页框合并为一个较大的页框块
- slab分配器用于管理特定大小对象的缓存
- slab分配器直接工作于伙伴系统上
- __get_free_pages,直接分配页框,一次最多分配4MB连续物理内存
- kmem_cache_alloc,基于slab分配器,适用于频繁分配和释放同一大小内存(一次对大分配128KB)
- kmalloc,通过kmem_cache_alloc来实现
- vmalloc,分配物理上不连续的大段内存块(适用于对内存请求不是很频繁,需要大内存块场景)
- dma_alloc_coherent,(同__get_free_pages),用于DMA使用
- ioremap,直接将已有的物理地址映射到内核地址空间,并不是分配一段新的物理内存,多用于设备驱动
- BootMemroy,需要分配连续大量物理内存,alloc_bootmem绕开伙伴系统,在开机前设置号该内存块
- 通过开机启动参数mem=size,来预留一段内存也能申请大块内存,进系统后通过ioremap来申请这段内存