Ошибка: Устройство или ресурс занят

Я пытаюсь написать простой модуль, который должен заменить обработчик irq 1. И все время я получаю следующую ошибку: «-1 Устройство или ресурс занят». Есть ли способ это исправить? Вот мой код:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <asm/io.h>


irqreturn_t myhandler(int irq, void *dev_id, struct pt_regs *regs) 
{
  printk(KERN_ALERT"\n\nMy interrupt handler\n\n");
  return IRQ_HANDLED;
}

int init_module()
{
  int res;
  free_irq(1, NULL);                  
  res = request_irq(1, (void*)myhandler,0, "my_handler", (void*)(myhandler)); 
  return res;
}

void cleanup_module()
{
  free_irq(1, NULL);
}
MODULE_LICENSE("GPL");

Может кто подскажет что не так. PS. Я работаю с ядром 2.6.39.3.


person Roman    schedule 30.11.2011    source источник


Ответы (1)


Какой у вас тип системы (архитектуры)?

На обычном ПК IRQ 1 — это 8042 (контроллер клавиатуры) и уже имеет обработчик прерываний. Вы передаете 0 в request_irq() для flags, поэтому вы просите зарегистрировать обработчик для неразделяемого прерывания. Основной код прерывания ядра проверит и увидит, что для этого IRQ уже зарегистрирован другой обработчик, и вернет -EBUSY из request_irq.

Вы не можете переопределить существующий обработчик, зарегистрировав другой обработчик для того же IRQ. Вам нужно отменить регистрацию первого, прежде чем вы сможете зарегистрировать новый.

Вы можете посмотреть /proc/interrupts, чтобы увидеть, что уже использует IRQ 1 в вашей системе.

person Roland    schedule 30.11.2011
comment
Хорошо, а как насчет 'free_irq(1, NULL);'? Он должен отменить регистрацию обработчика по умолчанию. Но я только что узнал, что проблема (я уверен на 90%) заключается в free_irq (пробовал использовать free_irq 10000 раз на одном и том же irq, и ошибок не обнаружено). - person Roman; 01.12.2011
comment
Второй параметр free_irq — это идентификатор устройства, и если этот указатель не соответствует существующему значению обработчика, free_irq завершится ошибкой. Предполагая, что вы находитесь на ПК, drivers/input/serio/i8042.c - это то, что делает request_irq, и он никогда не передает NULL идентификатор устройства. Таким образом, вы фактически не освобождаете существующий обработчик. - person Roland; 01.12.2011
comment
Я не очень понимаю, почему это происходит. Я имею в виду, что во всех руководствах я читал, что второй параметр free_irq всегда равен NUll. И если второй параметр free_irq не может быть NULL, то как получить id для удаления обработчика по умолчанию? - person Roman; 01.12.2011
comment
Не уверен, какое руководство вы читаете, но если вы посмотрите на реальный исходный код ядра, вы увидите, что второй параметр free_irq почти никогда не равен NULL. Вам нужно передать то же значение, что и исходный request_irq(). Вероятно, проще всего просто зарегистрировать первый IRQ, т.е. на ПК не загружать драйвер i8042. - person Roland; 01.12.2011