【问题标题】:Strange printk effect on linux stack size testing奇怪的 printk 对 linux 堆栈大小测试的影响
【发布时间】:2018-05-23 19:40:52
【问题描述】:
I am trying to test linux kernel stack size in 64 bit. 

我发现了这种奇怪的行为。 我编写了以下代码来使内核崩溃,但奇怪的是 仅当 printk 未注释时才会崩溃, 否则运行良好,没有错误/警告!!。

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

    static int __init crash_stack_init(void)
    {
        long arr[1024];
        long *a;

        a = &arr[0];

        //printk("%p\n", &arr[0]);

        return 0;
    }

        enter code here

    static void __exit crash_stack_exit(void)
    {
    }

    module_init(crash_stack_init);
    module_exit(crash_stack_exit);


Here is the "make" output without the printk,

make -C /lib/modules/4.4.0-53-generic/build M=/home/naveenvc/work/ker/crash_stack 模块 make[1]: 进入目录'/usr/src/linux-headers-4.4.0-53-generic' CC [M] /home/naveenvc/work/ker/crash_stack/crash_stack.o 建筑模块,第 2 阶段。 MODPOST 1 个模块 CC /home/naveenvc/work/ker/crash_stack/crash_stack.mod.o LD [M] /home/naveenvc/work/ker/crash_stack/crash_stack.ko make[1]: 离开目录'/usr/src/linux-headers-4.4.0-53-generic'

And make output with printk,

make -C /lib/modules/4.4.0-53-generic/build M=/home/naveenvc/work/ker/crash_stack modules make[1]:进入 目录 '/usr/src/linux-headers-4.4.0-53-generic' CC [M] /home/naveenvc/work/ker/crash_stack/crash_stack.o > /home/naveenvc/work/ker/crash_stack/crash_stack.c:在函数中 ‘crash_stack_init’: /home/naveenvc/work/ker/crash_stack/crash_stack.c:14:1:警告: 8200 字节的帧大小大于 1024 字节 [-Wframe-larger-than=] } ^
建筑模块,第 2 阶段。MODPOST 1 模块 CC
/home/naveenvc/work/ker/crash_stack/crash_stack.mod.o LD [M] /home/naveenvc/work/ker/crash_stack/crash_stack.ko make[1]:离开 目录'/usr/src/linux-headers-4.4.0-53-generic'

这可能是什么原因造成的?

【问题讨论】:

  • 当然 printk() 也使用了一些堆栈,所以你的函数 + printk 的组合堆栈使用量变得太多了
  • 合规性与总堆栈使用量无关(这将略高于允许大小的一半),而是该特定功能的使用

标签: c linux linux-kernel printk


【解决方案1】:

堆栈大小有据可查,上面不是正确的测试方法,特别是在使用大页面支持堆栈的旧内核中,上述代码会跳转到下一个堆栈。

带有 prink 注释的 func __crash_stack_init 是一个叶函数 - 它不调用任何东西,因此编译器确切地知道本地变量会发生什么。特别是在这段代码中,它看到不需要完整的数组,因此它没有被分配。但是,对 printk 的调用将 arr 传入。编译器不知道 func 将如何处理它,因此它必须在堆栈上保留 1024 * sizeof(long),这会导致警告。

堆栈在几年前被撞到了 16KB,您可以从这里开始阅读 https://lwn.net/Articles/600644/

【讨论】:

  • 看来 GCC 太聪明了。除非实际使用,否则它不会为数组分配内存。即使初始化数组或传递给本地函数也无关紧要。由于 printk 实际上需要打印传递给它的值,因此 GCC 正在分配数组。使用“attribute ((optimize("O0")))”禁用函数的优化也会产生没有 printk 的警告。
猜你喜欢
  • 1970-01-01
  • 2023-04-10
  • 2014-09-24
  • 2020-08-06
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
  • 2012-02-14
相关资源
最近更新 更多