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

Linux内核5.8及以上版本如何分配可执行内存?

内核5.8及以上版本分配可执行内存的替代方案

背景说明

自Linux 5.8内核发布后,__vmalloc()函数的签名发生变更:
旧签名:

void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)

新签名:

void *__vmalloc(unsigned long size, gfp_t gfp_mask)

这意味着无法再通过该函数直接指定内存属性来分配可执行内存。常规适配代码如下:

#if LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0)
return __vmalloc(len, GFP_KERNEL, PAGE_KERNEL_EXEC);
#else
return __vmalloc(len, GFP_KERNEL);
#endif

但这种适配方式下,若不使用内核noexec参数,内核5.8及以上版本无法通过vmalloc分配可执行内存。请问此时有什么替代方案?

可行替代方案

  • 使用vmalloc_exec()专用接口
    内核提供了vmalloc_exec()函数,专门用于分配具备可执行属性的虚拟内存,内部已封装好页属性设置逻辑,直接适配5.8及以上内核:

    void *exec_buf = vmalloc_exec(size);
    if (!exec_buf) {
        // 处理内存分配失败逻辑
    }
    
  • 先分配内存再修改页属性
    若需要更灵活的内存分配控制,可先通过vmalloc()或__vmalloc()分配普通内存,再调用set_memory_x()将目标内存区域设置为可执行:

    void *buf = vmalloc(size);
    if (!buf) {
        // 处理分配失败
    }
    // 按页对齐计算需要修改的页数
    unsigned int pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
    if (set_memory_x((unsigned long)buf, pages) != 0) {
        // 修改属性失败,释放已分配内存
        vfree(buf);
        buf = NULL;
    }
    

    注意:set_memory_x()要求操作的内存区域页对齐,且部分内核配置可能限制此类内存属性修改操作,需确保权限足够。

  • 使用__vmalloc_node_range()指定页属性
    如果需要指定内存节点、对齐规则等复杂参数,可使用__vmalloc_node_range()函数,该函数保留了pgprot_t prot参数,直接传入PAGE_KERNEL_EXEC即可分配可执行内存:

    void *exec_buf = __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,
                                        GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, __builtin_return_address(0));
    if (!exec_buf) {
        // 处理分配失败逻辑
    }
    

    该函数参数较多,需注意对齐值(此处为1表示按字节对齐)、内存范围、NUMA节点编号等参数的正确设置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 11:35:13