07 页分配器接口:alloc_pages Linux 内存管理 宅学部落(学习笔记)

2023年 10月 7日 23.1k 0

伙伴系统分配内存的接口(include/gfp.h)

具体函数如下:

struct page *alloc_pages(gfp_t gfp, unsigned int order);

#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)

extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);

#define __get_free_page(gfp_mask) __get_free_pages((gfp_mask), 0)

extern void __free_pages(struct page *page, unsigned int order);

extern void free_pages(unsigned long addr, unsigned int order);

#define __free_page(page) __free_pages((page), 0)

#define free_page(addr) free_pages((addr), 0)

struct page *alloc_pages(gfp_t gfp, unsigned int order);

gfp:

这些函数用于动态请求指针对齐的内存块,类似用户空间中的malloc和free,但
:c:func:kmalloc() 需要额外的标志词。重要的值:

GFP_KERNEL
可以睡眠和交换以释放内存。只允许在用户上下文中使用,但这是分配内存最可靠
的方法。

GFP_ATOMIC
不会睡眠。较 GFP_KERNEL 更不可靠,但可以从中断上下文调用。你 应该
有一个很好的内存不足错误处理策略。

GFP_DMA
分配低于16MB的ISA DMA。如果你不知道那是什么,那你就不需要了。非常不可靠。

如果您看到一个从无效上下文警告消息调用的睡眠的函数,那么您可能在没有
GFP_ATOMIC 的情况下从中断上下文调用了一个睡眠的分配函数。你必须立即修复,快点!

order: 0到MAX_ORDER-1,0代表4K ,1代表 8K,2代表2的2次方式4*4K 16K,以此类推

通过申请内存的接口从伙伴系统(4K-4M空间的内存分配)中空闲的内存块上取出合适的内存,返回给用户使用。

Class.jpg

1696577247356.png
mmzone.h

代码示例

#include
#include
#include
#include
MODULE_LICENSE("GPL");


struct page * page;
unsigned long int vir_adr;
static   int init_hello(void)
{
    page = alloc_pages(GFP_KERNEL,1);
    printk("page frame no: %lx n",page_to_pfn(page));
    printk("physical addr: %x n",page_to_phys(page));
    printk("virtual addr: %lx n",(unsigned int)page_address(page));
    vir_adr = (unsigned long)page_to_virt(page);
    printk("virtual addr: %lx n",vir_adr);
    printk("init hellon");
    return 0;
}

static  void exit_hello(void)
{
    free_pages(vir_adr,1);
    printk("exit hellon");
}

module_init(init_hello);
module_exit(exit_hello);

代码运行结果

图片.png

  • 注意事项:
    void free_pages(unsigned long addr, unsigned int order);中addr代表的是虚拟地址,不是物理地址

Q&A

  • 问题:分配的内存必须给用户空间使用吗?

    答案:不正确,伙伴系统是对用户的内存空间进行管理的。但用户空间内存,内核空间也是可以使用的。

  • 问题:伙伴系统管理的内存范围是多少?

    答案:ZONE_DMA 管理16M内存,大部分的内存都是由ZONE_NORMAL空间进行管理的。在arm系统中是没有ZONE_DMA空间的。伙伴系统管理着系统中大部分的内存,无法确定具体大小。比如struct page的内存我推测不是由伙伴系统管理的,具体细节现在我也不清楚,还有per_cup页帧缓存本分的内存也不是伙伴系统管理的,这个在操作系统的使用过程中会进行动态分配和回收

  • 问题:page_address(page)和page_to_virt(page)的区别是什么?

    答案:还不清楚

  • 问题:alloc_pages是如何申请内存的

    答案:如果申请的是4K先从pre_cup(每个CPU自己的列表中获取),如果没有再从伙伴系统中获取,如果无法申请到则对内存进行整理后在进行申请

  • Linux代码基于:linux-6.5.2

    代码运行结果基于:linux-headers-5.4.0-100-generic(Ununtu)

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论