我正在尝试使用vmalloc()
为内核模块分配一个大内存。
我无法在具有64GB RAM的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
分配的内存大小是否有限制?是否有另一种方法可以为内核模块分配大量内存?
答案 0 :(得分:0)
在早期版本的Linux内核中,vmalloc()
可以分配的内存限制为64 MB,但在版本3.10.*
中,它理论上应该受到物理内存的限制。
答案 1 :(得分:0)
您可以在评论中引用此处的代码:Simple Block Driver,这对于回答您的问题至关重要。
原因是,您尝试分配 16 Exabytes 数据。
sbd_init()
中的此计算是原因:
Device.size = nsectors * logical_block_size;
Device.size为unsigned long
,而模块参数nsectors
和logical_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;
然后它应该按预期工作。