2012-06-03 10 views
14

Auf der mainbord wir einen Interrupt-Controller (IRC) haben, die zwischen den Geräten als Multiplexer wirkt, die einen Interrupt und die CPU erhöhen kann: mitInterrupt-Handling (Linux/General)

       |--------| 
      |-----------|  |  | 
-(0)------| IRC _____|______| CPU | 
-(...)----| ____/  |  |  | 
-(15)-----|/   |  |--------| 
      |-----------| 

Jedes Gerät zugeordnet ist, ein IRQ (die Nummer auf der linken Seite). Nach jeder Ausführung erkennt die CPU die Interrupt-Request-Leitung. Wenn ein Signal erkannt wird, wird eine Zustandsspeicherung durchgeführt, und die CPU lädt eine Interrupt-Handler-Routine, die im Interrupt-Vektor zu finden ist, der sich an einer festen Adresse im Speicher befindet. Soweit ich das sehe sind die Nummer des IRQ und die Vector Nummer im Interrupt Vector nicht gleich, da ich zB meine Netzwerkkarte nach IRQ 8 registriert habe. Auf einem Intel Pentium Prozessor würde dies auf eine Routine verweisen, die benutzt wird um eine Fehlerbedingung zu signalisieren, so dass irgendwo eine Zuordnung erfolgen muss, die auf den richtigen Handler zeigt.

Fragen:

1) Wenn ich einen Gerätetreiber schreiben und einen IRQ X für sie registrieren. 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?

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)).

3) Wer legt zuerst die IRQs fest? Das Bios? Das Betriebssystem?

4) Wer ist verantwortlich für den Abgleich des IRQ und des Offsets im Interrupt Vector?

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?

+0

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) –

Antwort

18

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"; 
      } 
     } 
+2

Ausgezeichnete Antwort, thx! – fliX

+0

Sie haben eine Beschreibung zu IDT hinzugefügt, können Sie eine für IVT hinzufügen? – einstein