linux内核 - vmalloc 介绍

一:概述

vmalloc 是内核中的一个分配器。它返回的内存 在虚拟地址空间中是连续的,但底层的物理页帧是分散的。

vmalloc分配的内存在物理上并不连续。此外, vmalloc 返回的内存总是来自 HIGH_MEM 区域。返回的地址是 纯虚拟地址(而非逻辑地址),无法直接转换为物理地址或总线地址,因为无法保证其对应的物理内存是连续的。

这意味着,vmalloc() 返回的内存 不能在微处理器之外使用(例如,不能直接用于 DMA 操作)。vmalloc() 适合用于分配 存在于软件中的大块连续页序列(例如网络缓冲区),而不是仅仅分配一页内存。

需要注意的是,vmalloc() 比 kmalloc() 和页分配器函数慢,因为它不仅要获取内存,还需要建立页表,甚至可能重新映射为虚拟连续区域,而 kmalloc() 则无需执行这些操作。

vmalloc() 会分配 非连续的物理页,并将它们映射到 连续的虚拟地址区域。这些 vmalloc 的虚拟地址位于 内核空间的一定区域内,由 VMALLOC_START 和 VMALLOC_END 限定,这两个值依赖于具体的体系结构。

内核提供了 /proc/vmallocinfo 文件,用于显示系统中 所有通过 vmalloc 分配的内存。

二:相关函数和示例

cpp 复制代码
#include <linux/vmalloc.h>

void *vmalloc(unsigned long size);
void *vzalloc(unsigned long size);
void vfree(void *addr);
cpp 复制代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/kernel.h>
#include <linux/string.h>  // for memset

static void *ptr;  // 静态指针用于保存 vmalloc 地址
#define ALLOC_SIZE 8192  // 分配 2 x 4KB 内存

static int __init my_vmalloc_init(void)
{
    pr_info("Initializing vmalloc example module\n");

    // 分配内存
    ptr = vmalloc(ALLOC_SIZE);
    if (!ptr) {
        pr_err("Memory allocation failed\n");
        return -ENOMEM;
    }

    // 初始化内存
    memset(ptr, 0, ALLOC_SIZE);

    pr_info("Memory allocated successfully at virtual address %p\n", ptr);
    return 0;
}

static void __exit my_vmalloc_exit(void)
{
    if (ptr) {
        vfree(ptr);
        pr_info("Memory freed\n");
    }
}

module_init(my_vmalloc_init);
module_exit(my_vmalloc_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("your_email@example.com");
MODULE_DESCRIPTION("A simple vmalloc() example kernel module");