c - linux内核模块中的最大指针/数组大小

标签 c linux-kernel kernel

我怎么知道在分配之前,我可以创建多大的数组?或者如何定位我的数组,使其不与内存映射中的内容冲突?

我有这个配置

VM running on Virtualbox with
Operating system: Centos 7
Memory: 2GB
Processor: E7500@2,9Ghz
Host OS: Suse Leap 41 

我有这段代码:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_DESCRIPTION("linux module");
MODULE_AUTHOR ("doald duck");

static int __init KM () {
    size = 100000;
    size = 10*100000;
    printk( "creating an int aray of %d 1st ....\n",size);

    int ia [size];
    int ia_ = -1;
    while (++ia_ < size ){
        ia [ia_] = ia_ +2000;
    }
    return 0;
}

static void __exit  _KM () {
    printk ("unloading 'za module ");
}

module_init (KM);
module_exit (_KM);

如果大小保持在 100000 ;该模块正在加载并且 rmmod 完美运行.. 如果我以某种方式执行 size = 10*100000 那么内核 panic 就会发生并重新启动

调用跟踪是:

[  155.751747] creating an aray of 1000000 1st ....
[  155.753448] BUG: unable to handle kernel paging request at ffff88007c408000
[  155.753629] IP: [<ffffffffa0037037>] KM+0x37/0x1000 [kernel_module1]
[  155.753962] PGD 3f32067 PUD 3f35067 PMD 3ed00063 PTE 800000007c408161
[  155.754065] Oops: 0003 [#1] SMP 
[  155.754170] Modules linked in: kernel_module1(POE+) ip6t_rpfilter ip6t_REJECT ipt_REJECT xt_conntrack ebtable_nat ebtable_broute bridge stp llc ebtable_filter ebtables ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6 ip6table_mangle ip6table_security ip6table_raw ip6table_filter ip6_tables iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack iptable_mangle iptable_security iptable_raw iptable_filter vfat fat snd_intel8x0 snd_ac97_codec ac97_bus snd_seq iTCO_wdt iTCO_vendor_support ppdev snd_seq_device snd_pcm snd_timer snd soundcore parport_pc pcspkr parport lpc_ich mfd_core sg i2c_piix4 video i2c_core ip_tables xfs libcrc32c sr_mod cdrom sd_mod ata_generic crct10dif_generic crc_t10dif crct10dif_common pata_acpi ahci libahci ata_piix serio_raw libata e1000 dm_mirror
[  155.754955]  dm_region_hash dm_log dm_mod
[  155.754979] CPU: 0 PID: 2562 Comm: insmod Tainted: P           OE  ------------   3.10.0-327.13.1.el7.x86_64 #1
[  155.755086] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[  155.755190] task: ffff88007c72f300 ti: ffff88007c668000 task.ti: ffff88007c668000
[  155.755286] RIP: 0010:[<ffffffffa0037037>]  [<ffffffffa0037037>] KM+0x37/0x1000 [kernel_module1]
[  155.755391] RSP: 0018:ffff88007c29b450  EFLAGS: 00010287
[  155.755487] RAX: 000000000005b2ec RBX: ffffffff81951020 RCX: ffff88007c29b450
[  155.755594] RDX: 000000000005babc RSI: 0000000078e678e4 RDI: 0000000000000246
[  155.755687] RBP: ffff88007c66bd58 R08: 0000000000000086 R09: 0000000000000269
[  155.755782] R10: 0000000000000000 R11: ffff88007c66ba6e R12: ffff8800026609c0
[  155.755877] R13: ffffffffa0037000 R14: 0000000000000000 R15: ffffffffa03e4000
[  155.755974] FS:  00007f6dfdbc4740(0000) GS:ffff88007da00000(0000) knlGS:0000000000000000
[  155.756074] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[  155.756164] CR2: ffff88007c408000 CR3: 000000007c606000 CR4: 00000000000006f0
[  155.756262] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[  155.756356] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[  155.756451] Stack:
[  155.756527]  000007d1000007d0 000007d3000007d2 000007d5000007d4 000007d7000007d6
[  155.756635]  000007d9000007d8 000007db000007da 000007dd000007dc 000007df000007de
[  155.756745]  000007e1000007e0 000007e3000007e2 000007e5000007e4 000007e7000007e6
[  155.756842] Call Trace:
[  155.756923] Code: e5 e8 23 81 5f e1 be 40 42 0f 00 48 c7 c7 48 30 3e a0 31 c0 e8 10 81 5f e1 48 81 ec 08 09 3d 00 31 c0 48 89 e1 8d 90 d0 07 00 00 <89> 14 81 48 ff c0 48 3d 40 42 0f 00 75 ec 48 c7 c7 3b 30 3e a0 
[  155.757153] RIP  [<ffffffffa0037037>] KM+0x37/0x1000 [kernel_module1]
[  155.757246]  RSP <ffff88007c29b450>
[  155.757329] CR2: ffff88007c408000

大部分原因是因为它到达了一个无法分配的地址......

最佳答案

在内核空间中运行的进程的默认堆栈大小为 8192 字节,但根据体系结构可能会更小。

要请求足够大的内存,请使用 kmalloc 和它的 friend 。

size_t sz = 10000;
int *ia = kmalloc(sz, GFP_KERNEL);
if (ia == NULL)
{
    /* allocation failed, handle error */
    return -1;
}
/* OK, though it may have allocated more than you asked for */

关于c - linux内核模块中的最大指针/数组大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36648221/

相关文章:

c - 使用按键的 GLUT 旋转相机无法正常工作

c++ - 将 double 与整数进行同一性比较时,什么会转换成什么?

c++ - 如何在没有 IO 窗口(命令行窗口)的情况下运行 exe?

linux - 还可以恢复启动分区吗? (QQZM N5063网络摄像头)

c - 全局变量在 C 内核 .rdata 部分中不起作用

Linux 内核更改默认 CPU 调度程序

c - 使用 double 调用函数后所有小数都将被删除

Linux:获取空闲空间物理 block 号(空闲空间位图)

sockets - 在Linux内核中发送UDP数据包

linux - ttyS1/uart1已初始化但无法通过/dev/ttyS1访问