Странный эффект printk при тестировании размера стека в Linux

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 modules 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-large-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'

Что может быть причиной этого?


person Naveen Kumar V C    schedule 09.12.2017    source источник
comment
Конечно, printk () тоже использует некоторый стек, поэтому комбинированное использование стека вашей функцией + printk становится слишком большим.   -  person nos    schedule 10.12.2017
comment
соответствие не касается общего использования стека (который будет чуть больше половины допустимого размера), а использования этой конкретной функции   -  person employee of the month    schedule 10.12.2017


Ответы (1)


Размер стека хорошо документирован, и приведенное выше не является правильным способом тестирования, в частности, в старых ядрах, которые использовали огромные страницы для поддержки стека, вышеупомянутый код перескакивал бы на следующий стек.

Func __crash_stack_init с закомментированным prink является листовой функцией - она ​​ничего не вызывает, поэтому компилятор точно знает, что происходит с локальными переменными. В частности, в этом коде он видит, что полный массив не нужен и, следовательно, он не выделяется. Однако вызов printk передает arr. Компилятор не знает, что с ним будет делать функция, поэтому он должен зарезервировать 1024 * sizeof (long) в стеке, что приводит к предупреждению.

Стеки были увеличены до 16 КБ несколько лет назад, вы можете начать читать здесь https://lwn.net/Articles/600644/

person employee of the month    schedule 09.12.2017
comment
Похоже, GCC слишком умен. Он не будет выделять память для массива, если она действительно не используется. Даже инициализация массива или переход к локальной функции не имеет значения. Поскольку printk действительно нужно распечатать переданное значение, GCC выделял массив. Отключение оптимизации для функции с атрибутом ((optimize (O0))) также приведет к предупреждению без printk. - person Naveen Kumar V C; 10.12.2017