Immer wenn ein Datentransfer zur oder von der verwalteten Hardware aus irgendwelchen Gründen verzögert werden könnte, sollte der Treiberprogrammierer ein Zwischenspeichern implementieren. Datenpuffer helfen dabei, die Datenübertragung und -entgegennahme von den Systemaufrufen read und write zu entkoppeln, und verbessern so die Gesamt-Performance des Systems.
Ein guter Puffer-Mechanismus verwendet “Interrupt-gesteuerte I/O”, bei der ein Eingabe-Puffer zur Interrupt-Zeit gefüllt und von Prozessen, die von dem Gerät lesen, geleert wird. Entsprechend wird ein Ausgabe-Puffer von den auf das Gerät schreibenden Prozessen gefüllt und zur Interrupt-Zeit geleert. Ein Beispiel für die Interrupt-gesteuerte Ausgabe ist die Implementation von /dev/shortint.
Damit die Interrupt-gesteuerte Datenübertragung funktioniert, muß die Hardware in der Lage sein, Interrupts mit der folgenden Semantik zu generieren:
Bei Eingaben unterbricht das Gerät den Prozessor, wenn neue Daten eingetroffen sind und vom Systemprozessor abgeholt werden können. Wie das passiert, hängt davon ab, ob das Gerät I/O-Ports, das Abbilden in den Speicher (Memory Mapping) oder DMA verwendet.
Bei Ausgaben meldet das Gerät einen Interrupt, wenn es entweder in der Lage ist, neue Daten entgegenzunehmen, oder wenn es eine erfolgreiche Übertragung bestätigen will. Geräte, die in den Speicher abgebildet werden können oder DMA-fähig sind, erzeugen meistens Interrupts, um dem System mitzuteilen, daß sie mit dem Puffer fertig sind.
Die Zusammenhänge im Timing zwischen read oder write einerseits und dem tatsächlichen Eintreffen der Daten andererseits wurden in “the Section called Blockierende und nicht-blockierende Operationen in Kapitel 5” in Kapitel 5 eingeführt. Interrupt-gesteuerte I/O bringt noch das zusätzliche Problem mit sich, daß beim nebenläufigen Zugriff auf gemeinsam genutzte Datenelemente Race Conditions auftreten können und deswegen Synchronisationsmechanismen vorgesehen werden müssen. Im nächsten Abschnitt wird dieses verwandte Thema detaillierter besprochen.