Antworten in Bezug auf Linux-Kernel. Sollte für die meisten anderen Betriebssysteme auch funktionieren.
1) Wenn ich einen Gerätetreiber schreibe und ein IRQ X dafür registriere. Woher weiß das System, mit welchem Gerät umzugehen ist? Ich kann zum Beispiel request_irq() mit IRQ Nummer 10 verwenden, aber woher weiß das System, dass der Handler für die Maus oder Tastatur oder für was auch immer ich den Treiber schreibe verwendet werden sollte?
Es gibt keine 1 Antwort darauf. Wenn es sich beispielsweise um ein benutzerdefiniertes eingebettetes System handelt, teilt der Hardware-Designer dem Treiber mit: "Ich werde Gerät x nach irq y routen". Für mehr Flexibilität, zum Beispiel für eine Netzwerkkarte, die in der Regel das PCI-Protokoll verwendet. Es gibt eine Arbitrierung auf Hardware/Firmware-Ebene, um einem neuen Gerät eine IRQ-Nummer zuzuordnen, wenn es erkannt wird. Dies wird dann in eines der PCI-Konfigurationsregister geschrieben. Der Treiber liest zuerst dieses Geräteregister und registriert dann seinen Interrupt-Handler für diesen bestimmten IRQ. Es wird ähnliche Mechanismen für andere Protokolle geben.
Was Sie tun können, ist Aufrufe nach Request_irq im Kernel-Code nachschlagen und wie der Treiber den IRQ-Wert erhalten. Es wird für jede Art von Fahrer anders sein.
Die Antwort auf diese Frage lautet also, das System weiß es nicht. Der Hardware-Designer oder die Hardware-Protokolle stellen diese Informationen dem Treiberschreiber zur Verfügung. Und dann registriert der Treiberschreiber den Handler für diesen bestimmten IRQ und teilt dem System mit, was zu tun ist, falls Sie diesen IRQ sehen.
2) Wie sieht der Interrupt-Vektor dann aus? Ich meine, wenn ich den IRQ 10 für mein Gerät verwende, würde dies einen Standard-Handler überschreiben, der zur Fehlerbehandlung in der Tabelle dient (der erste verwendbare ist 32 gemäß Silberschatz (Betriebssystemkonzepte)).
Gute Frage. Es gibt zwei Teile davon.
a) Wenn Sie request_irq (irq, Handler). Das System programmiert den Eintrag 0 im IVT oder IDT wirklich nicht. Aber Eintrag N + irq. Wobei N die Anzahl der Fehlerbehandler oder Allzweckausnahmen ist, die auf dieser CPU unterstützt werden. Details variieren von System zu System.
b) Was passiert, wenn Sie fälschlicherweise eine irq anfordern, die von einem anderen Treiber verwendet wird? Sie erhalten einen Fehler und IDT ist nicht mit Ihrem Handler programmiert.
Hinweis: IDT ist die Interrupt-Deskriptor-Tabelle.
3) Wer legt zuerst die IRQs fest? Das Bios? Das Betriebssystem?
Bios zuerst und dann OS. Aber es gibt bestimmte Betriebssysteme, zum Beispiel, MS-DOS, die nicht die IVT-Setup von BIOS neu programmieren. Anspruchsvollere moderne Betriebssysteme wie Windows oder Linux wollen sich nicht auf bestimmte Bios-Funktionen verlassen und programmieren den IDT neu. Aber BIOS muss es zunächst tun, dann kommt OS ins Bild.
4) Wer ist verantwortlich für den Abgleich des IRQ und des Offsets im Interrupt Vector?
Ich bin wirklich nicht klar, was du meinst. Der Ablauf ist so. Zuerst wird Ihrem Gerät eine IRQ-Nummer zugewiesen, und Sie registrieren dann einen Handler dafür mit dieser IRQ-Nummer. Wenn Sie eine falsche IRQ-Nummer verwenden und dann den Interrupt auf Ihrem Gerät aktivieren, stürzt das System ab. Weil der Handler für eine falsche IRQ-Nummer registriert ist.
5) Es ist möglich, IRQS zu teilen. Wie ist das möglich? Auf dem Mainboard befinden sich Hardware-Lanes, die Geräte mit dem Interrupt-Controller verbinden. Wie können Fahrspuren für den gleichen Interrupt konfiguriert werden? Es muss eine Tabelle geben, die besagt, dass Spur 2 und 3 IRQ15, z. Wo befindet sich diese Tabelle und wie heißt sie?
Das ist eine sehr gute Frage. Extra Tabelle ist nicht wie es im Kernel gelöst ist. Stattdessen werden die Handler für jede gemeinsam genutzte IRQ in einer verknüpften Liste von Funktionszeigern gehalten. Der Kernel durchläuft alle Handler und ruft sie nacheinander auf, bis einer der Handler den Interrupt für sich beansprucht.
The code looks like this:
driver1:
d1_int_handler:
if (device_interrupted()) <------------- This reads the hardware
{
do_interrupt_handling();
return MY_INTERRUPT;
}else {
return NOT_MY_INTERRUPT;
}
driver2:
Similar to driver 1
kernel:
do_irq(irq n)
{
if (shared_irq(n))
{
irq_chain = get_chain(n);
while(irq_chain)
{
if ((ret = irq_chain->handler()) == MY_INTERRUPT)
break;
irq_chain = irq_chain->next;
}
if (ret != MY_INTERRUPT)
error "None of the drivers accepted the interrupt";
}
}
Eine ausführlichere Erklärung auf Interrupt-Setup, Handhabung und Mapping finden Sie hier: [A Code zu Fuß innerhalb Kernel Interrupt-Rahmen] (http://linuxburps.blogspot.in/2013/10/linux-interrupt- handling.html) –