一、问题
如何在内核中正确分配和释放page?
内核中使用内存是再平常不过的事了,但应该如何正确使用呢,尤其是在自己编写驱动时,应该如何正确的分配和释放内存,是一大问题,不理清楚的话,可能导致严重后果,比如:内存泄露、越界、野指针等。
本文只关注按页(page)分配和释放内存的方式(只是简单的介绍和对比),kmalloc、slab、vmalloc等暂不关注,后续抽空再续。


二、内存分配
内核使用内存通常使用slab(包括kmalloc),按page分配内存的地方其实不多,常见的场景如:skb中线性区和frags[]、slab自身。虽然内核中有其它方式(如slab、vmalloc),但其最终还是通过page的方式来分配的。
内核按page分配内存,主要有如下两类接口:

1、alloc_pages(包括alloc_page、alloc_pages_nomask等) ,该接口返回page结构指针,对应于物理地址。
2、get_free_pages,该接口返回虚拟(线性)地址,即分配到内存后,会进行内存映射。

三、内存释放
内核中释放page,主要有如下方式:

1、free_pages,对应于alloc_pages,参数中需要带order。如果是用alloc_pages方式分配的高阶内存(大于1个page),则必须用这种方式释放,并带上order参数。否则会出现内存泄露。因为:
    1)alloc_pages分配高阶内存时,只会设置分配到第一个的page的引用计数(为1),后面的page不会设置引用计数。
    2)如果使用put_page方式释放内存,只会释放一个page,如果该page是以alloc_pages方式分配的高阶内存,那后面的page就泄露了,无法释放了。
2、put_page,减小指定page的引用计数,当引用计数减为0时,将其释放。
两种方式的区别:
1、free_pages可释放大于一个page(order不为0)的内存块,put_page只能释放单个page
2、如果释放的内存块为一个page,两者都是将该page放到hot_cold缓存中(便于提升下次访问效率),
09-21 10:30