Как работает список уведомлений linux (перезагрузка)?

#linux-kernel #arm #linux-device-driver #qemu

#linux-ядро #arm #linux-драйвер устройства #qemu

Вопрос:

Я тестирую хук уведомления о перезагрузке в ядре Linux 5.8, работающем на QEMU ARM64 с корневыми файлами busybox. Я впервые использую список уведомлений, поэтому я могу ошибаться. Я добавил один уведомитель о перезагрузке, который выполняется хорошо, но я также добавил второй элемент в список, используя .next , и обработчик этого уведомителя не выполняется. Вот фрагмент из моего фиктивного драйвера:

 static int reboot_handler_first(struct notifier_block *this, unsigned long action,
        void *data)
{
    printk(KERN_INFO "first reboot notifier calledn");
    return 0;
}

static int reboot_handler_second(struct notifier_block *this, unsigned long action,
        void *data)
{
    printk(KERN_INFO "second reboot notifier calledn");
    return 0;
}

static struct notifier_block reboot_notifier_second = {
    .notifier_call = reboot_handler_second,
    .next = NULL,
    .priority = INT_MAX,
};

static struct notifier_block reboot_notifier_first = {
    .notifier_call = reboot_handler_first,
    .next = amp;reboot_notifier_second,
    .priority = INT_MAX,
};
 

Здесь reboot_handler_first() вызывается, но я не вижу никакого журнала reboot_handler_second() . Я ожидал, что reboot_notifer_first() это сработает reboot_notifier_second() , но, похоже, это не так. Я что-то пропустил?

Ниже приведены журналы, которые я вижу с этим ядром и корневыми файлами busybox:

 / # reboot
/ # umount: devtmpfs busy - remounted read-only
swapoff: can't open '/etc/fstab': No such file or directory
The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL to all processes
Requesting system reboot
[   20.158023] first reboot notifier called
[   20.232718] reboot: Restarting system
[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x411fd070]
 

Редактировать

Вот как module_init(hello_init) выглядит моя функция. Я зарегистрировал только первый уведомитель о перезагрузке reboot_notifier_first , а затем установил его следующим, чтобы указать на reboot_notifier_second . Пожалуйста, поправьте меня. Я понимаю, что мне нужно зарегистрировать первый уведомитель, register_reboot_notifier() а затем мне просто нужно установить значение .next тока notifier_block , чтобы добавить новые узлы в связанный список. Таким образом, я получу цепочку блоков уведомлений.

 static int __init hello_init(void)
{
    int rc;

    rc = register_reboot_notifier(amp;reboot_notifier_first);
    printk(KERN_INFO "This is from initn");
    return 0;
}
 

Комментарии:

1. Знаете ли вы, как работают связанные списки? Существует специальный API, который вы должны вызвать, чтобы добавить узел в список. Т.е. ->next Указатель настраивается фреймворком, а не вызывающим. Вы должны показать в своем фрагменте, как вы это сделали.

2. .next = amp;reboot_notifier_second это единственное, что я подумал. Насколько я понимаю, как только мы установим next значение первого уведомителя, FW повторит этот связанный список для обработки первого уведомителя, а затем второго уведомителя последовательно

3. Вы не получили то, о чем я вас просил, и не предоставили важную часть своего кода.

4. Где вы регистрируете свой уведомитель? of the first notifier, the FW will iterate this linked list to process Какой из них «первый»? Почему вы устанавливаете .next = amp;reboot_notifier_second, вручную, а не регистрируете его? Am I missing anything? Я предполагаю, что ваш reboot_notifier_first.next просто перезаписывается при регистрации его в списке…

5. Пожалуйста, посмотрите РЕДАКТИРОВАНИЕ. Думаю, теперь я понял, что вы пытаетесь сказать. Я не должен сам редактировать .next указатель, скорее я должен продолжать вызывать register_reboot_notifier() для каждого нового блока уведомлений, и фреймворк сам настроит ссылки.