if (request_irq(IRQ_NUM, irq_handler, 0, DEV_NAME, NULL)) {
printk("My module: IRQ allocation failed\n");
release_mem_region(MEM_START, MEM_QTY);
release_region(PORT_START, PQRT_QTY);
return -EBUSY;
}
printk("My module: IRQ allocated\n");
return 0;
}
void cleanup_module {
// Освобождаем порты ввода-вывода
release_region(PORT_START, PORT_QTY);
printk("My module; release io ports\n");
//
Освобождаем память
release_mem_region(MEM_START, MEM_QTY);
printk("My module: release memory\n");
// Освобождаем прерывание
free_irq(IRQ_NUM, NULL);
printk("My module: release irq\n");
// Отменяем регистрацию устройства
if (unregister_chrdev(Major, DEV_NAME) < 0){
printk("My module: cannot to unregister device\n");
}
printk("My module: device unregistered\n");
return;
}
При загрузке модуля вы увидите следующее сообщение:
My module: device registered, major number = 255
Конечно, кроме этого сообщения будут и другие, но нас они не интересуют. Почему именно это сообщение так важно для нас? В первой части сообщения говорится, что наше устройство успешно зарегистрировано, а во второй сообщается старший номер устройства, который мы будем использовать для создания устройств /dev/device0 и /dev/device1.
Вы не забыли, что нам еще нужно создать два устройства типа device, чтобы программы могли работать с ними? Перейдите в каталог
/dev
и от имени суперпользователя выполните команды:
# mknod device с 255 0
# mknod device с 255 1
Здесь 255 — это старший номер устройства (у вас он будет другим), 0 и 1 — младшие номера устройств. После выполнения данных команд будут созданы два файла устройств —
/dev/device0
и
/dev/device1
.
После регистрации устройства функцией register_chrdev мы пытаемся захватить диапазон портов. Для этого предназначена функция request_region, но перед ее вызовом мы должны убедиться, что нужный нам диапазон не используется (функция check_region). Затем, если нужно, мы резервируем память для нашего устройства. Для резервирования памяти используется функция request_mem_region, а для проверки возможности захвата памяти предназначена функция check_mem_region. После успешной регистрации памяти можно попытаться захватить IRQ — функция request_irq.
Предположим, что на каком-то этапе регистрации модуля произошла ошибка. Если мы не смогли зарегистрировать порты ввода/вывода, вряд ли имеет смысл продолжать работу. Если же ошибка произошла при резервировании памяти, то перед завершением работы модуля нам нужно освободить порты ввода/вывода, которые мы зарегистрировали на предыдущем этапе. Аналогично поступаем при ошибке захвата IRQ — освобождаем порты и память. Функции
release_mem_region
,
release_region
и
free_irq
используются для освобождения памяти, портов и IRQ соответственно.