- 论坛徽章:
- 9
|
(1)slab是内核为较高频率出现的内核结构cache的,其大小都是固定的某个结构体的大小,用户态随机malloc若干个byte应该不会从slab中分配才对,malloc大小是随机的,slab不可能做到这样的cache。
Glib 在能使用 malloc 之前就已经从内核申请一定量的内存来充当缓存,malloc 分配的都是这些缓存.但从 malloc 的缓存来源角度讲,这段内存也是从 slab 或者 buddy 中分配来的.
但由于 malloc 是用户空间的函数,只有 malloc 的缓存用到一定的底线,才会向内核发起的申请.请注意,不是用 malloc 分配内存就这的会从内核分配物理内存给你用,这是策略性问题,
只有对 malloc 分配的内存进行写操作,才会真正的为它分配真实的物理内存.
(2)16字节对齐的问题,多了16字节是对其的,那没有这16字节也是对齐的,不太明白。
这个问题是内存对齐问题,只有是内存分配器,都要使用各自的内存对齐策略.
(3)伙伴系统所管理的块大小有1/2/4/8/16/32....个page的,也就是说最小管理1个page,所以分配1个page应该也会从伙伴分配。
从 buddy 中分配内存已经是内核空间的问题,当需要分配一个 page 大小的内存时,使用 kmalloc() 进行分配,kmalloc 会根据传入其中的参数 GFP 标志来计算相关的分配策略,
这些值包括从哪一个 struct zone 上分配内存,也包括这个页的 migrate 类型,以及分配内存的 size.有了这些值之后,内核首先在 SLAB 中查找有没有匹配 size 的缓存,如果有,
就使用 kmem_cache_alloc() 进行分配,如果没有,内核就从 PCP 分配器中分配内存,也就是 Per-CPU Allocator,更传统的说就是内核在 SLAB 和 Buddy 中缓存了一个分 page,这些
page 保存在 Hot 和 cold 链表中,随着内核的更新,内核将这两个链表合成一个链表,hot page 保存在表头,cold page 保存在链表尾,如果这个链表中有空闲的页,就从这里分配内存.
如果 PCP allocator 里没有空闲页,最后才从 Buddy 里通过 get_page_from_freelist() 函数,结合之前 GFP 标志获得 zone 和 migratetype 来获得空闲 page.
(4)我在实例中发现,不管我怎么分配空间,包括改变分配大小,改变分配顺序,地址始终是接续的,不符合伙伴的策略啊。
您只在用户空间使用 malloc 分配,它只会返回 0 ~ 3G 的一段连续虚拟地址给您,是不能直接从 buddy 中反应出来的,毕竟里面还有很多堆,匿名映射,文件映射,swap 等等内容,
不是简单就可以看到的,如果您想了解 Buddy Allocator 的话.直接到内核空间研究就可以! |
|