Die meisten Hardware-Schnittstellen werden mit Hilfe eines Interrupt-Handlers gesteuert. Die Schnittstelle unterbricht den Prozessor, um eines von zwei möglichen Ereignissen mitzuteilen: Entweder ist ein neues Paket angekommen, oder die Übertragung eines ausgehenden Paketes wurde abgeschlossen. Diese Generalisierung ist nicht immer ganz richtig, trifft aber bei allen Problemen der asynchronen Paket-Übertragung zu. Das Parallel Line Internet Protocol (PLIP) und das Point-to-Point Protocol (PPP) sind Beispiele für Schnittstellen, die nicht in diese Generalisierung passen. Sie haben es mit den gleichen Ereignissen zu tun, aber die Interrupt-Verarbeitung auf der unteren Ebene ist geringfügig anders.
Die normale Interrupt-Routine kann den Unterschied zwischen einem Interrupt wegen eines neu eingetroffenen Paketes und einem Interrupt wegen einer vollständig durchgeführten Übertragung anhand eines Status-Registers auf dem physikalischen Gerät selbst feststellen. snull arbeitet ähnlich, wenn auch dieser Zustandswert in der Software implementiert wird und in dev->priv steht. Der Interrupt-Handler für eine Netzwerk-Schnittstelle sieht folgendermaßen aus:
voidsnull_interrupt(intirq,void*dev_id,structpt_regs*regs) { intstatusword; structsnull_priv*priv; /* *Wieueblichden"Geraete"-ZeigeraufgemeinsamgenutzteHandler *ueberpruefen,dann"structnet_device*dev"zuweisen. */ structnet_device*dev=(structnet_device*)dev_id; /*...undbeiderHardwareueberpruefen,obdasunserGeraetist*/ if(!dev/*paranoid*/)return; /*DasGeraetsperren*/ priv=(structsnull_priv*)dev->priv; spin_lock(&priv->lock); /*Statuswertholen:richtigeGeraeteverwendenI/O-Anweisungen*/ statusword=priv->status; if(statusword&SNULL_RX_INTR){ /*ansnull_rxzurBearbeitungsenden*/ snull_rx(dev,priv->rx_packetlen,priv->rx_packetdata); } if(statusword&SNULL_TX_INTR){ /*eineUebertragungisterledigt:denskbfreigeben*/ priv->stats.tx_packets++; priv->stats.tx_bytes+=priv->tx_packetlen; dev_kfree_skb(priv->skb); } /*DasGeraetfreigebenundfertig*/ spin_unlock(&priv->lock); return; } |
Die erste Aufgabe des Handlers ist es, den Zeiger auf die richtige net_device-Struktur zu finden. Dieser Zeiger stammt normalerweise aus dem Zeiger dev_id, der als Argument übergeben wird.
Der interessante Teil des Handlers behandelt abgeschlossene Übertragungen. In diesem Fall wird die Statistik aktualisiert und dev_kfree_skb aufgerufen, um den (nicht mehr benötigten) Socket-Buffer an das System zurückzugeben. Wenn Ihr Treiber die Übertragungswarteschlange vorübergehend angehalten hat, ist dies auch die richtige Stelle, um sie mit netif_wake_queue wieder in Gang zu bringen.
Zum Empfangen der Pakete ist dagegen keine besondere Interrupt-Behandlung notwendig. Es muß lediglich snull_rx aufgerufen werden.