Грешка: Устройството или ресурсът са заети

Опитвам се да напиша прост модул, който трябва да замени манипулатора на 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 10 000 пъти на едно и също 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, тогава как да получа идентификатор за премахване на манипулатора по подразбиране? - person Roman; 01.12.2011
comment
Не съм сигурен какво ръководство четете, но ако погледнете действителния източник на ядрото, можете да видите, че вторият параметър на free_irq почти никога не е NULL. Трябва да подадете същата стойност като оригиналния request_irq(). Вероятно най-простото нещо, което трябва да направите, е просто да регистрирате първия IRQ -- т.е. на компютър не зареждайте i8042 драйвера. - person Roland; 01.12.2011