LINUX.ORG.RU

Не могу заюзать функцию ядра Linux.

 , ,


0

2

Здравствуйте. Возникла задача - прочесть параметры, с которыми запущено ядро из загружаемого модуля. Вернее, не ядро, запущенное из модуля, а в одном из модулей ядра мне ядерные параметры получить надо. В исходниках ядра нашел функцию, которая, возможно, умеет это делать. Вот она:

include/linux/mm.h: int get_cmdline(struct task_struct *task, char *buffer, int buflen);
Пытаюсь заюзать эту функцию в модуле. Вот код:
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mm.h>

MODULE_LICENSE( "GPL" );

static int __init getcmdline_init(void)
{
        char buf[128];
        get_cmdline(0,buf,128);
        printk("cmd: %s\n", buf);
        printk("cmd: Hello\n");
        return 0;
}

static void __exit getcmdline_exit(void)
{
}

module_init(getcmdline_init);
module_exit(getcmdline_exit);

Собираю таким Makefile-ом:

CURRENT = $(shell uname -r)
KDIR = /lib/modules/`uname -r`/build
PWD = $(shell pwd)
obj-m += getcmdline.o
default: 
        $(MAKE) -C $(KDIR) M=$(PWD) modules

При сборке получаю варнинг:

WARNING: "get_cmdline" [/root/fun/getcmdline/getcmdline.ko] undefined!
Само собой, модуль не грузится, выдает ошибку:
insmod: ERROR: could not insert module getcmdline.ko: Unknown symbol in module
При просмотре journalctl видно, что не находит именно символ get_cmdline. Но в загруженном ядре он есть и объявлен как экспортируемый:

$ grep get_cmdline /proc/kallsyms 
ffffffff81181790 T get_cmdline

В незапакованном ядре она тоже присутствует:

$ nm -n  /lib/modules/3.18.4-1-selinux/build/vmlinux | grep get_cmdline
ffffffff81181790 T get_cmdline

В чем здесь магия? Ведь printk, который объявлен в ядре точно так же, я использую безо всяких дополнительных определений. Подскажите пожалуйста, почему функцию увидеть не могу?

Ответ на: комментарий от tailgunner

Не могу проверить, я ядро сразу с SELinux собирал. Но он выключен в параметрах ядра + я не применял еще политики безопасности, поэтому вряд ли он влияет.

esvstn ()
Ответ на: комментарий от i-rinat

Спасибо, попробую. А без пересборки ядра никак его не получить? Мне просто тогда еще вручную все модули пересобирать придется под новое ядро, а это тупо долго. И зачем, интересно он тогда в /proc/kallsyms отображается, если получить его нельзя?

esvstn ()
Ответ на: комментарий от metawishmaster

Ну это я только для проверки сделал, так как пока не разобрался, как ему передать структуру таска ядра) Если вообще этот таск существует.

esvstn ()

Вот смотри пример:

http://lxr.free-electrons.com/source/fs/proc/cmdline.c

В ядре есть глобальная переменная saved_command_line, которая и содержит параметры ядра.

Раз: http://lxr.free-electrons.com/source/init/main.c#L124

Два: http://lxr.free-electrons.com/source/include/linux/init.h#L147

post-factum ★★★★★ ()
Последнее исправление: post-factum (всего исправлений: 1)
Ответ на: комментарий от post-factum

Мммда... Пожалуй, вы правы. Про saved_command_line почитал, но, к сожалению, она не экспортируется во внешние модули. Придется вручную, а это опять грозит пересборкой ядра(

esvstn ()

тебе небось надо параметр модулю передать, а не комманд лайн парсить, типа модуль.параметр=10

dimon555 ★★★★★ ()
Ответ на: комментарий от dimon555

Передача параметров модулю возможна только если модуль вкомпилен в ядро. А мой модуль должен дергать API проприетарного модуля, поэтому я не имею права так делать.

esvstn ()
Ответ на: комментарий от post-factum

Да, только тред 5-илетней давности, и ответ его автор так и не получил(

esvstn ()
Ответ на: комментарий от post-factum

Думал уже об этом. Но опять же, проблема в том, что модуль в ramfs будет находиться. Мне нужно получить возможность отключать мой модуль, когда он не нужен. А он в свою очередь будет отключать проприетарный. Пересобирать ramfs для этого каждый раз - не выход. Вот пока только в голову приходит через параметры ядра это делать. Вроде, задачка-то вполне логичная. Только решения все какие-то костыльные выходят...

esvstn ()
Ответ на: комментарий от anonymous

Там нельзя получить вывод программы. Можно только запустить ее с аргументами и передать ей что-нибудь через пайп. Но решение найдено. Оставлю ссылку, если кому понадобится:

https://www.ibm.com/developerworks/ru/library/l-linux_kernel_36/

Можно прочесть просто из файла /proc/cmdline. Всем большое спасибо.

esvstn ()
Ответ на: комментарий от post-factum

Не скажите, по ссылке, которую я приложил, написано, что это единственный способ загружаемому модулю считать свои параметры. Они же в ФС находятся. Я немного сомневался, не выйдет ли чего, если я читаю из /proc. Но нет, все в порядке.

esvstn ()
Ответ на: комментарий от esvstn

это единственный способ загружаемому модулю считать свои параметры

Если речь о параметрах модуля, а не ядра, то нет.

Если речь о параметрах ядра, а не модуля, то это костыль.

post-factum ★★★★★ ()
Ответ на: комментарий от esvstn

зато можно получить код возврата программы ;) можно рядом с модулем положить скрипт который парсит cmdline и возвращает коды в соответствии с результатом, например

anonymous ()
Ответ на: комментарий от esvstn

странно, а я всегда считал, что для передачи модулю параметров используется module_param_*() - там много вариантов. Есть варианты с callback для отслеживания изменения параметров.

Поменять параметр можно на ходу через /sys/module/<mod_name>/parameters/<param>

Задать параметр можно при загрузки модуля и через cmdline ядра

vel ★★★★★ ()
Ответ на: комментарий от esvstn

Передача параметров модулю возможна только если модуль вкомпилен в ядро.

Честно говоря, я толком на реализации способов передачи параметров модулям не смотрел, но вот сейчас у меня получается задавать параметр модулю через init_command_line при загрузке.

Модуль не вкомпилен в ядро. Он собран отдельно, но установлен в дерево модулей, в смысле в Makefile есть строчки

@install -d $(INSTALLDIR);
@install -c $(TARGET_OBJ) $(INSTALLDIR);
и загружаю я его через modprobe, а не insmod

metawishmaster ★★★★ ()
Последнее исправление: metawishmaster (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.