在Linux中,内核模块的大小是否有限制?

10
我有一个加载内核模块的问题,有一个大数据结构,大小约为2GB的内存 - 无论我是否预分配表格(使其在执行size -A module.ko时显示在.bss中)或尝试在加载时使用vmalloc(),都会出现insmod: error inserting 'module.ko': -1 Cannot allocate memory错误导致模块加载失败。
我尝试在用户模式linux上调试该问题,但我得到了一堆段错误(可以在gdb中继续,但最终会出现控制台消息overflow in relocation type 10 val <value in the ball park of 6G>'module' likely not compiled with -mcmodel=kernel)。我假设在Kbuild中,-mcmodel应该是正确的,对吗?
因此,问题如下:
  1. Linux内核模块大小是否存在通用的2G限制?
  2. 在用户模式linux中,内核模块是否存在2G限制(我想我曾经注意到,一个大的内核模块需要一个干净、连续的内存块……)?
  3. 我可以为内核模块指定-mcmodel=large并期望它能正常工作吗?
我在debian squeeze、64位、2.6.32-5-amd64(主机)和4G内存的uml中尝试了这个问题,所以这不应该是普通的内存不足问题。
如果存在此类限制,可以解决此限制的方法将获得额外的奖励 :)

2GB的代码+数据段?你开玩笑吧!你为什么不直接使用mmap映射你的数据,而不是编译它呢? - user405725
不幸的是,我没有开玩笑。 - Kimvais
3个回答

8

关于您的第一个问题 - 模块本身的限制是64兆字节。模块加载器将拒绝加载超过此大小的模块。来自kernel/module.c

if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL)
        return ERR_PTR(-ENOMEM);

对于2.6.32版本和更新的内核,包括3.3版本,这都是真实的情况。

编辑:在内核版本3.4中,64 Mb的限制被移除。现在,实际的限制取决于vmalloc()可以分配多少内存。


1

请记住,内核空间内存与用户空间内存是不同的 -- 在32位Linux上,内核只有1Gb的地址空间。在64位Linux上,内核有更多的地址空间,但内核文档建议模块只能使用1536MB。


在64位系统上,实际上没有地址空间限制(好吧,限制是很多TB)。 - Roland
关于x86-64,可能内核空间中的内存区域的简要描述可以帮助:Documentation/x86/x86_64/mm.txt。上限可以从那里推导出来,尽管实际上限当然可以更低。 - Eugene
如果我使用动态vmalloc(),似乎可以获得尽可能多的内存(只要有可用的内存)。请参阅我的测试代码:http://paste.pocoo.org/show/406020/。 - Kimvais

0
如果我将表定义为static - 模块加载确实会失败 - 这可能是由于Andrew Aylett的答案中提到的1.5G限制。
但是,如果我进行动态vmalloc()调用,在具有8Gb内存的主机上,我能够获得高达7680Mb的内存(直到内核杀死一些关键进程并且我的X挂起)。
所以回答我的问题:
1. 是的,但仅适用于编译为static的数据。 2. 看起来不是这样。 3. 没有必要这样做。
额外加分:只需执行vmalloc()
这仅适用于新于2.6.10的Linux内核 - 在此之前,vmalloc()限制为64 Mb。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接