You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux v6.0中alloc_pages_node未递增所有分配页的_refcount问题咨询

关于Linux v6.0中alloc_pages_node分配内存时struct page _refcount的疑问解答

问题背景

在Linux v6.0中使用alloc_pages_node分配物理连续内存时,仅分配区域首页的struct page中的_refcount被递增为1,其余页的_refcount均为0。相关代码及输出如下:

运行代码

order = get_order(nr_pages << PAGE_SIZE);
p = alloc_pages_node(node, gfp_mask, order);
if (!p)
    return;
for(i =  0; i < nr_pages; i++, p++) 
    printk("_refcount = %d", p->_refcount);

输出结果

_refcount = 1
_refcount = 0
_refcount = 0
...

参数说明

  • gfp_mask为(THREADINFO_GFP & ~__GFP_ACCOUNT) | __GFP_NOWARN | __GFP_HIGHMEM,其中THREADINFO_GFP & ~__GFP_ACCOUNT由alloc_thread_stack_node传入,__GFP_NOWARN | __GFP_HIGHMEM由__vmalloc_area_node添加;
  • nr_pages为4,因此order = get_order(nr_pages << PAGE_SIZE) = 2。

用户咨询两个问题:

  1. 这是否为正确/预期行为?
  2. 该函数是否仅适用于特定场景,从而无需关注非首页的_refcount?

解答

1. 属于预期行为

伙伴分配器处理连续页分配时,仅会对分配区域的首页设置_refcount为1,其余页的_refcount保持初始值0,这是内核的设计逻辑:

  • 连续页分配是以"页块"为单位管理的,首页作为整个块的代表,其引用计数负责跟踪整个块的使用状态;
  • 非首页的struct page在连续分配场景下不会被单独引用或释放,因此不需要维护独立的引用计数。

而vmalloc这类非连续分配API分配的是离散页,每个页都需要独立跟踪引用状态,所以会递增所有页的_refcount,这和伙伴分配器的连续页管理逻辑完全不同。

2. 函数适用场景与引用计数关注点

alloc_pages*系列函数适用于需要物理连续内存的场景,比如:

  • 内核早期启动阶段的栈分配(如你提到的init进程和kthreadd栈设置);
  • 设备驱动中需要直接访问物理连续地址的硬件缓冲区;
  • 高性能内存分配场景,避免TLB miss带来的性能损耗。

在这些场景下,开发者只需关注首页的_refcount:

  • 释放时使用__free_pages或对应释放函数,传入首页指针和分配时的order,内核会自动处理整个连续页块的释放,无需操作非首页的引用计数;
  • 非首页的struct page不会被单独操作,其_refcount为0是正常状态,不影响内存的管理和使用。

内容的提问来源于stack exchange,提问作者TSG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 07:25:20