2017-05-30 86 views
3

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

这些都是相关的部分代码:

... 

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分配?有没有另一种方式来分配大量的内存到内核模块?

+0

从理论上讲,限制应该是32TB或物理可用的RAM,无论先到先得;)在尝试分配内存时,你是否收到内核发来的消息? – Ctx

+0

向我们展示你使用'vmalloc()'的方式。 – syntagma

+2

在内核模块中分配2GiB RAM听起来像是一个非常糟糕的主意。看起来像一个XY问题。 – Olaf

回答

0

您在此处引用代码:Simple Block Driver,这对于回答您的问题至关重要。

原因是,您正试图分配16 Exabytes的数据。 该计算在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; 

那么它应该工作正常。

0

在旧版本的Linux内核中,vmalloc()可以分配的内存限制为64 MB,但在版本3.10.*中理论上应该受物理内存的限制。

+1

这应该是一个评论,因为它并没有真正帮助解决OPs问题 – Ctx

+0

@Ctx:这**在一个提问者的问题上回答** * - 是否对内存大小有限制?可以通过vmalloc分配吗?'所以可以是*答案*。 – Tsyvarev