> Он проверен и работаетНевероятно, но факт. Специально проверил на своем ядре 3.11, до последнего не верил что заработает. Как минимум, за самостоятельное решение оценку вы заработали. Но покритиковать код надо.
> Решила проблему по-своему – просто изменила обработчик так, чтобы при вызове он напрямую
> обращался к функции вывода символа в системный журнал.
Оценку "отл." за такое надо вам поставить. "Обманула Товарища Лектора" то есть :)
Вы делаете всю работу в хардварном прерывании, избавившись от bottom half. Чтобы не портировать код workqueue. Но:
1. Ведь BH там был не просто так: обработчик прерывания должен завершаться как можно быстрее, а printk, как и любая операция ввода/вывода, занимает весьма немало времени. Так что, как говорится, за изобретение ставлю пять, а за экзамен...
2. Более того, в этом же была суть задания -- спортировать весь код, а вы просто половину кода выкинули.
> free_irq(1, NULL);
Будет матюкаться в журнал ядра (dmesg), что невозможно освободить незанятое прерывание. Я уже выше описывал, почему этого делать нельзя. Просто проверьте свой dmesg после insmod.
> #define SA_SHIRQ IRQF_SHARED
Интересный способ портирования устаревших флагов...
> int init_module()
> void cleanup_module()
Забыли указать аргументы void в них, это важно. Ну и надо заметить, в новых ядрах принято использовать макросы module_init() и module_exit() для этого.
> irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs)
Посмотрите, какая сигнатура для ISR функций в новом ядре (88-я строка):
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux....
В общем, с вашим подходом правильно было бы "спортировать" так:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <asm/io.h>static irqreturn_t kbd2_isr(int irq, void *dev_id)
{
char scancode;
scancode = inb(0x60);
pr_info("Scan Code %x %s\n",
scancode & 0x7F, scancode & 0x80 ? "Released" : "Pressed");
return IRQ_HANDLED;
}
static int __init kbd2_init(void)
{
return request_irq(1, kbd2_isr, IRQF_SHARED, "kbd2", NULL);
}
static void __exit kbd2_cleanup(void)
{
free_irq(1, NULL);
}
module_init(kbd2_init);
module_exit(kbd2_cleanup);
MODULE_LICENSE("GPL");