Модуль ядра: внешний, только если установлен определенный параметр

Я хотел бы использовать функцию, определенную в другом модуле ядра. Обычно вы делаете это так:

другой модуль

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/…

0andriy 16.05.2019 13:47

Но что, если я не могу изменить другой модуль? В любом случае спасибо, идея классная

ataraxis 16.05.2019 14:49

Если вы знаете имя символа, вы можете попытаться найти его в таблице символов компоновщика.

0andriy 17.05.2019 00:05

Если вам не нужно принимать решение по таймеру выполнения, должен ли присутствовать другой модуль или нет, вы можете обернуть extern ... под ifdefs.

yashC 17.05.2019 08:37

Возможно, вы сможете что-то сделать, используя 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);, чтобы освободить ссылку.

Ian Abbott 21.05.2019 19:59

@IanAbbott Думаю, это решение! Я попробую и отчитаюсь.

ataraxis 22.05.2019 11:40

@IanAbbott Вот оно! Большое спасибо! Если вы переформулируете его как официальный ответ, я отмечу эту проблему как решенную, а ваш ответ - как принятый.

ataraxis 22.05.2019 12:55

Я никогда не использовал его раньше. Это было просто предложение для вас кое-что исследовать. Я предлагаю вам представить свой собственный ответ с вашими выводами.

Ian Abbott 22.05.2019 13:34

Я так и сделаю, как только перепробую все кейсы ;) Еще раз спасибо!

ataraxis 22.05.2019 13:52
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
10
527
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Основываясь на комментарии Яна Эбботта, вот одно из возможных решений:

В мой_модуль:

  1. объявите функцию как extern, иначе компилятор будет жаловаться на do_sth в symbol_get()

    extern void do_sth();
    
  2. объявить указатель, который позже будет указывать на функцию do_sth в другом модуле

    void (*__do_sth)();
    
  3. назначьте указатель, увеличьте счетчик использования, чтобы ядро ​​​​знало, что кто-то использует другой модуль

    __do_sth = symbol_get(do_sth);
    if (__do_sth)
        __do_sth();
    
  4. При удалении модуля или, возможно, раньше, когда вам больше не нужен другой модуль: Уменьшите счетчик использования. В противном случае будет невозможно удалить другой модуль, поскольку ядро ​​считает, что он все еще используется.

    if (__do_sth)
        symbol_put(do_sth);
    
  5. Кроме того, вам нужно будет убедиться, что другой модуль каким-то образом загружается по мере необходимости, для этого я использую правило UDEV.

Разве код не должен вызывать __do_sth(), а не do_sth()? В противном случае мой_модуль по-прежнему напрямую связан с do_sth в другой_модуль, что делает этот трюк немного бессмысленным.

Ian Abbott 23.05.2019 14:32

Другие вопросы по теме