资讯动态

page_alloc free_pages_nolock

发布时间:2026/10/17 1:29:44 来源:尧图企业网站定制
内核中释放页面的两个不同接口free_pages_nolock()无锁释放和free_pages()按虚拟地址释放。一、free_pages_nolock()—— 可在原子上下文中调用的释放接口/* * Can be called while holding raw_spin_lock or from IRQ and NMI for any * page type (not only those that came from alloc_pages_nolock) */ void free_pages_nolock(struct page *page, unsigned int order) { ___free_pages(page, order, FPI_TRYLOCK); }1. 核心语义FPI_TRYLOCK传入FPI_TRYLOCK标志表示释放时只尝试获取 PCP 锁、不阻塞等待。如果拿不到锁就降级到伙伴系统路径或按实现走其他安全路径绝不会自旋等待。2. 注释的关键信息Can be called while holding raw_spin_lock or from IRQ and NMI这是它存在的根本原因。在某些原子上下文中持有raw_spin_lock、中断处理、NMI调用者不能睡眠、不能自旋等待因此标准的__free_pages()可能因等待 PCP 锁而不可用。for any page type (not only those that came from alloc_pages_nolock)强调它不限于alloc_pages_nolock()分配的页任何页都可以用它释放。3. 与alloc_pages_nolock()的对称free_pages_nolock()与alloc_pages_nolock()如果存在构成一对分配时也不阻塞获取锁释放时同理。这适用于网络收包NAPI、NMI 处理等极低延迟场景。二、free_pages()—— 按虚拟地址释放void free_pages(unsigned long addr, unsigned int order) { if (addr ! 0) { VM_BUG_ON(!virt_addr_valid((void *)addr)); __free_pages(virt_to_page((void *)addr), order); } }1. 参数虚拟地址 阶数与__free_pages()接收struct page *不同free_pages()接收虚拟地址通常来自__get_free_pages()的返回值。2. 三步操作if (addr ! 0)如果地址为 0表示分配失败时的返回值直接跳过不做任何事。这是对__get_free_pages()失败返回 0 的对称处理。VM_BUG_ON(!virt_addr_valid((void *)addr))调试断言。确保地址是有效的内核虚拟地址。virt_addr_valid()在调试配置下检查地址是否在直接映射区且对应有效物理页。如果传入无效地址如用户空间地址、已释放地址触发 bug。__free_pages(virt_to_page((void *)addr), order)用virt_to_page()把虚拟地址转回struct page *再调用__free_pages()完成实际释放。3. 与__get_free_pages()的对称unsigned long addr __get_free_pages(gfp, order); // 返回虚拟地址 ... free_pages(addr, order); // 按虚拟地址释放这是驱动开发中最常见的分配/释放配对。三、两个函数对比函数参数特点适用场景free_pages_nolock()struct page *FPI_TRYLOCK不阻塞等锁IRQ/NMI/持raw_spin_lock上下文free_pages()unsigned long addr按虚拟地址释放调试断言常规驱动/内核代码四、与相关函数的关系函数参数调用__free_pages(page, order)struct page *___free_pages(page, order, FPI_NONE)free_pages_nolock(page, order)struct page *___free_pages(page, order, FPI_TRYLOCK)free_pages(addr, order)unsigned long__free_pages(virt_to_page(addr), order)__free_page(page)struct page *__free_pages(page, 0)free_page(addr)unsigned longfree_pages(addr, 0)五、总结free_pages_nolock()是原子上下文安全的释放接口通过FPI_TRYLOCK标志避免阻塞等待 PCP 锁使其可在持有raw_spin_lock、IRQ 和 NMI 中调用适用于极低延迟、不能睡眠的场景。free_pages()是按虚拟地址释放的常规接口它处理地址为 0 的边界情况在调试配置下用virt_addr_valid()校验地址有效性再通过virt_to_page()转换后委托__free_pages()释放与__get_free_pages()形成对称的分配/释放配对。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑