2017-12-23 5 views
-1

Ich werde einige Code gründlich, die in etwa die folgenden tut:Interrupthandling in Gerätetreiber & Umfrage

  • Kernel-Treiber verarbeitet eine Unterbrechung.
  • Es gibt 1 Interrupt-Leitung. Wenn ein Interrupt auftritt, lesen die Handles ein 32-Bit-Register, das den Grund für diesen Interrupt angibt.
  • Für jedes Bit, das festgelegt ist, ruft es ack_irq() auf, um den Interrupt zu löschen, und schreibt die Interruptursache in einen Puffer im Treiber für weiteres read().
  • Als nächstes ruft es wake_up_interruptible() auf, um einen User-Space-Prozess zu aktivieren, der auf select() schläft.
  • Die entsprechende poll() - Funktion führt poll_wait() durch.
  • Sobald Auswahl zurückgibt, liest der User-Space() aus dem Treiber.

Während ich die grundlegende Bedienung von nur 1 Bit zu verstehen, was im folgenden Fall geschehen:

  • Interrupt geschieht, und 1 Bit gesetzt ist.
  • Handler ruft wake_up_interruptible() auf. poll() gibt zurück.
  • Benutzerraum wacht auf, beginnen zu lesen().
  • JETZT, ein weiterer Interrupt passiert -> Kernel behandelt den Interrupt und ruft wake_up_interruptible() auf, aber jetzt wartet niemand auf dieses Ereignis.

Bedeutet dies, dass der zweite Interrupt verpasst wird? Wenn ja, wie kann man das überwinden?

+0

Angenommen, es ist ein Ringpuffer, und der Benutzerprozess liest, bis es nicht mehr zu lesen gibt (und eine ordnungsgemäße Sperre des Puffers vorausgesetzt), der Benutzerprozess wird nur die nächste Ursache aus dem Puffer lesen. –

+0

Danke, es ist ein Ringspeicher, aber wir nehmen an, dass der Benutzerprozess die read() des ersten Interrupts beendet und kurz bevor er bei select() wieder in den Ruhezustand geht, ist der neue Interrupt angekommen. Der neue Interrupt wird wake_up_interruptible() aufrufen, aber der Benutzerprozess wartet noch nicht auf dieses Ereignis. – JZ500

+0

"kurz bevor es wieder einschläft" wurde die neue "Ursache" in den Puffer gelegt, so dass select() den nächsten Wert zurückgibt. Der Aufruf wake_up_interruptible() tut einfach nichts (es gibt nichts aufzuwachen, weil nichts schläft). Rember es ist das Betriebssystem, das alles tut. Es greift die CPU bei dem Interrupt vom Benutzerprozess ab, so dass der Benutzerprozess nichts unternimmt, und gibt die CPU an den Benutzerprozess zurück, nachdem jede Reinigung durchgeführt wurde. Aus diesem Grund wird der Benutzerprozess nicht in den Ruhezustand versetzt. –

Antwort

0

Die Aufgabe des Interrupt-Handlers ist es, den Interrupt so schnell wie möglich zu behandeln.

mit dem Rest des Systems zu kommunizieren, verwendet die ISR einen (circular) Puffer, in dem es Ihre cause platziert. Dies geschieht während eines deaktivierten Interrupt-Status.

Sobald der Interrupt bearbeitet wurde, wird das System fortgesetzt. Wenn der Benutzerprozess nun den Ringpuffer auf neue Ereignisse überprüfen möchte, benötigt er einen exklusiven Zugriff auf den Puffer. Dazu muss es Interrupts deaktivieren (mit einer höheren Priorität als der ISR). Es deaktiviert Interrupts, ruft das nächste Element des Puffers ab, aktualisiert Pufferzeiger oder -indizes und aktiviert Interrupts erneut.

Wäre ein neuer Interrupt eingegangen, dann wurde dieser nicht verarbeitet, bis der Benutzerprozess die Interrupts wieder aktiviert hat (die IRQ-Leitung bleibt hoch, die Chipregister wurden nicht gelesen). Natürlich muss dieser Pufferzugriff auch so schnell wie möglich sein (so wenig Befehle wie möglich). Nach dem erneuten Aktivieren von Interrupts wird der neue ausstehende Interrupt bedient.

Nachdem dieser nächste Eintrag den Puffer erhalten hat, übergibt er ihn an den funktionalen Benutzerprozess. Wären keine Objekte im Puffer vorhanden, würde es schlafen. Wenn ein Element angekommen ist, wird es aufgeweckt, unterbricht Interrupts, ruft das Element auf, aktiviert Interrupts erneut und kehrt zum Benutzerprozess zurück.

Auf diese Weise können keine Interrupts verpasst werden.