Я хотел бы использовать функцию, определенную в другом модуле ядра. Обычно вы делаете это так:
другой модуль
void do_sth() {
/* ... */
}
EXPORT_SYMBOL(do_sth);
мой_модуль
extern void do_sth();
void some_function(void) {
/* ... */
do_sth();
/* ... */
}
В моем случае я хочу использовать функцию do_sth() только в том случае, если установлен other_module или, наоборот, если для моего модуля задан определенный параметр (что-то вроде use_other_module=y)
Проблема в том, что - как только я объявляю функции как extern (глобально) - модуль больше не может быть загружен, если other_module не установлен или не загружен.
Итак, мои вопросы:
другой_модуль должен зарегистрироваться в мой_модуль и предоставить набор обратных вызовов. Подобный случай описан здесь: stackoverflow.com/questions/27769368/…
Но что, если я не могу изменить другой модуль? В любом случае спасибо, идея классная
Если вы знаете имя символа, вы можете попытаться найти его в таблице символов компоновщика.
Если вам не нужно принимать решение по таймеру выполнения, должен ли присутствовать другой модуль или нет, вы можете обернуть extern ... под ifdefs.
Возможно, вы сможете что-то сделать, используя symbol_get, определенный в <linux/module.h>. Например, если у вас есть указатель на функцию static void (*my_do_sth)(void);, вы можете назначить его во время выполнения с помощью my_do_sth = symbol_get(do_sth);. Если это не удается, my_do_sth будет NULL, иначе он будет указывать на функцию. Он должен быть соединен с вызовом symbol_put_addr(my_do_sth); или symbol_put(do_sth);, чтобы освободить ссылку.
@IanAbbott Думаю, это решение! Я попробую и отчитаюсь.
@IanAbbott Вот оно! Большое спасибо! Если вы переформулируете его как официальный ответ, я отмечу эту проблему как решенную, а ваш ответ - как принятый.
Я никогда не использовал его раньше. Это было просто предложение для вас кое-что исследовать. Я предлагаю вам представить свой собственный ответ с вашими выводами.
Я так и сделаю, как только перепробую все кейсы ;) Еще раз спасибо!





Основываясь на комментарии Яна Эбботта, вот одно из возможных решений:
В мой_модуль:
объявите функцию как extern, иначе компилятор будет жаловаться на do_sth в symbol_get()
extern void do_sth();
объявить указатель, который позже будет указывать на функцию do_sth в другом модуле
void (*__do_sth)();
назначьте указатель, увеличьте счетчик использования, чтобы ядро знало, что кто-то использует другой модуль
__do_sth = symbol_get(do_sth);
if (__do_sth)
__do_sth();
При удалении модуля или, возможно, раньше, когда вам больше не нужен другой модуль: Уменьшите счетчик использования. В противном случае будет невозможно удалить другой модуль, поскольку ядро считает, что он все еще используется.
if (__do_sth)
symbol_put(do_sth);
Кроме того, вам нужно будет убедиться, что другой модуль каким-то образом загружается по мере необходимости, для этого я использую правило UDEV.
Разве код не должен вызывать __do_sth(), а не do_sth()? В противном случае мой_модуль по-прежнему напрямую связан с do_sth в другой_модуль, что делает этот трюк немного бессмысленным.
Возможный дубликат как в этом случае экспортировать символ из модуля ядра?