1. __free_pages()
所在头文件: #include <linux/gfp.h>
函数实现位置: mm/page_alloc.c
函数定义: void __free_pages(struct page *page, unsigned int order);
功能: __free_pages()函数用来释放页面块,该函数从给定的页面page开始,释放的页面块格式为 1<<order 个。
参数:
page: page结构体指针,指向呆释放的物理页中的第一个页结构体。
order: 指要释放的物理页数,其取值为2的order次方。
2. __get_free_pages()
所在头文件: #include <linux/gfp.h>
函数实现位置: mm/page_alloc.c
函数定义: unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
功能: __get_free_pages()函数用于以gfp_mask分配方式分配2的order次方个连续的物理页。它返回所分配的连续物理页中第一个页的虚拟地址。
参数:
gfp_mask: 是分配标志,它提供了多种分配内存的方式,指示内核如何分配以及在哪里分配所需的内存。
gfp_t类型的标记用于控制申请内存时的内存分配方式和分配行为, 此标记有两类,一类是不带下划线的,一类是带双下划线的。
不带双下划线前缀的GFP标志:
GFP_ATOMIC: 用来从中断上下文和进程上下文之外的其他代码中分配内存,从不睡眠。
GFP_KERNEL: 内核内存的正常分配方式,它可能睡眠。
GFP_USER: 用来为用户空间分配内存,可能睡眠。
GFP_HIGHUSER: 和GPF_USER有相同的属性,但如果有高端内存,就从高端内存分配。
带双下划线前缀的GFP标志:
__GFP_DMA: 要求分配可用于DMA的内存。
__GFP_HIGHMEM: 分配的内存可以位于高端内存。
__GFP_COLD: 正常地分配器尽力地返回“缓冲热(可能在处理器缓冲中找到的页)”的页;而这个标志请求返回一个“冷(一段时间内没有使用的页)”页。
__GFP_NOWARN: 当一个分配无法满足时,阻止内核发出警告。
__GFP_HIGH: 高优先级请求,允许为紧急状况消耗被内核保留的最后一页内存页。
__GFP_REPEAT: 分配器满足一个分配有困难时,努力再尝试一次,仍有可能失败。
__GFP_NOFAIL:分配器满足一个分配有困难时, 告诉分配器尽最大努力来满足要求,始终不返回失败。
__GFP_NORETRY: 分配器满足一个分配有困难时, 告知分配器如果无法满足请求,立即返回。
order: 指要释放的物理页数,其取值为2的order次方。
返回值: __get_free_pages()函数返回所分配的连续物理页中第一个页的逻辑地址,如果分配失败的话,则返回0.
例子:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gfp.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Text for __get_free_pages() API");
MODULE_AUTHOR("rony <tclrony@163.com>");
static int __init __get_free_pages_init(void);
static void __exit __get_free_pages_exit(void);
unsigned long addr = 0;
int __init __get_free_pages_init(void)
{
addr = __get_free_pages( GFP_KERNEL, 3 ); // 8 pages allocated
if (!addr) {
printk(KERN_ERR "error for __get_free_page()\n");
return -ENOMEM;
} else {
printk(KERN_INFO "__get_free_pages() Successfully!, addr = 0x%lx\n", addr);
}
return 0;
}
void __exit __get_free_pages_exit(void)
{
if (addr) {
free_pages(addr, 3);
//__free_pages(virt_to_page((void *)addr), 3);
printk(KERN_INFO "free_pages ok!\n");
}
printk(KERN_INFO "exit!\n");
}
module_init(__get_free_pages_init);
module_exit(__get_free_pages_exit);
Makefile内容:
obj-m := get_free_pages.o
get_free_pages-objs := __get_free_pages.o
编译方法:
当前目录下运行如下命令:
make -C /lib/modules/$(kernel-version)/build M=`pwd`
编译结果:
生成的文件其中包括get_free_pages.ko
运行:
加载模块:sudo insmod get_free_pages.ko
卸载模块: sudo rmmod get_free_pages.ko
察看运行log: dmesg