c - 使用 vmalloc 为内核模块分配大量内存

标签 c linux-kernel kernel-module

我正在尝试使用 vmalloc() 为内核模块分配大内存。 我无法在具有 64GB 内存的 64 位 Linux (3.10.0-514.2.2.el7.x86_64) 上分配超过 2GB 的内存。

这些是相关的代码部分:

...

static int logical_block_size = 512;
module_param(logical_block_size, int, 0);
static int nsectors = 1024; /* How big the drive is */
module_param(nsectors, int, 0);

...

/*
 * The internal representation of our device.
*/
static struct sbd_device {
    unsigned long size;
    spinlock_t lock;
    u8 *data;
    struct gendisk *gd;
} Device;

...

static int __init sbd_init(void) {
    /*
     * Set up our internal device.
     */
   Device.size = nsectors * logical_block_size;
   spin_lock_init(&Device.lock);
   Device.data = vmalloc(Device.size);
   ...

可通过vmalloc 分配的内存大小是否有限制?有没有其他方法可以为内核模块分配大量内存?

最佳答案

您引用这里的代码:Simple Block Driver在评论中,这是回答您的问题所必需的。

原因是,您正在尝试分配 16 艾字节 的数据。 sbd_init()中的这个计算是原因:

Device.size = nsectors * logical_block_size;

Device.size 是unsigned long,而模块参数nsectorslogical_block_size 是整数。

现在,当您将 locgical_block_size 设置为 1024 并将 nsectors 设置为 2097152(总计 2GB 空间)时,计算将以有符号整数,因此结果是:

1024 * 2097152 = -2147483648

当它隐式转换为 unsigned long(通过分配给 Device.size)时,结果为 18446744071562067968,然后传递给 vmalloc( ),(可能)略微超过物理内存和 vmalloc 保留区域,在 linux x86_64 上为 32TB。

解决方案是以unsigned long的形式执行计算:

Device.size = (unsigned long) nsectors * logical_block_size;

然后它应该按预期工作。

关于c - 使用 vmalloc 为内核模块分配大量内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44259749/

相关文章:

c - strcpy 将一个项目从 dirent 转换为 char[]

linux - kmalloc 中 GFP_USER 标志的用途是什么?

linux-kernel - 我的中断处理程序应该禁用中断还是 ARM 处理器自动执行此操作?

linux-kernel - copy_from_user 需要什么

c - 如何从 Netlink 套接字中注册的回调函数以外的函数发送和接收消息?

c - 分配给类型 'struct compartido' 时不兼容的类型

c - 在没有 bzero 的 sockaddr_in 上套接字绑定(bind)失败

c - 如何在 Linux 中通过 inode 结构查找套接字端口?

c - 开发与内核通信的应用程序

c++ - 回归基础——将字符串复制到静态数组的惯用方法