Für den Fall, dass ein Treiber einer Applikation Daten nicht sofort übergeben kann, lassen sich zwei Vorgaben einstellen. Beim blockierenden Lesen wartet die Applikation so lange, bis die Daten zur Verfügung stehen. Unter Linux wird der Rechenprozess dabei entweder in den Zustand TASK_INTERRUPTIBLE (wieder lauffähig, wenn ein Signal unterbricht) oder in den Zustand TASK_UNINTERRUPTIBLE (überhaupt nicht unterbrechbar) versetzt.
Beim nicht blockierenden Lesen gibt der Systemcall read die Kontrolle gleich wieder an die Applikation mit einem Rückgabewert von »-EAGAIN« zurück. In diesem Fall wird die Applikation nicht durch den Treiber in den Wartezustand versetzt.
Für das Schreiben gilt Ähnliches. Kann ein Gerät die Daten zum Zeitpunkt des Aufrufes nicht schreiben, wird beim blockierenden Zugriff die Applikation so lange »schlafen« gelegt, bis die Daten geschrieben werden können oder der Rechenprozess (während er im Systemcall schläft) durch ein Signal unterbrochen wird. Beim nicht blockierenden Schreiben gibt der Treiber die Kontrolle unverzüglich an den Rechenprozess zurück. In diesem Fall hat der Systemcall den Rückgabewert »-EAGAIN«.
Der blockierende Zugriff auf ein Gerät ist der Normalfall. Schließlich kann hierbei die Wartezeit durch den Rechner sinnvoll genutzt werden, indem ein anderer Rechenprozess die zur Verfügung stehende Rechenzeit nutzt.
Die Einstellung des Zugriffsmodus (blockierend oder nicht blockierend) erfolgt entweder beim Öffnen des Gerätes (open) oder ansonsten über die Funktion fcntl.
Beispiel 4-4. Auswahl des Zugriffsmodus in einer Applikation
#include <fcntl.h> |
Neben der Möglichkeit, blockierend oder nicht blockierend zuzugreifen, existiert noch eine Funktion, um festzustellen, ob auf einem oder mehreren Filedeskriptoren der nachfolgende Zugriff blockieren würde oder nicht. Dabei wird sogar noch zwischen lesendem und schreibendem Zugriff differenziert. Diese Funktion heißt select. Die Funktion select selbst wird prinzipiell immer im blockierenden Modus aufgerufen; allerdings kann durch Angabe eines Timeout-Wertes das befristete Blockieren (bzw. überhaupt nicht blockieren) eingestellt werden.
Select wird genutzt, um mehrere Ein- bzw. Ausgabekanäle auf Veränderungen hin zu überwachen. Sobald an einem der angegebenen Kanäle Daten zum Lesen bereit liegen bzw. zum Schreiben übergeben werden können, gibt die Funktion der Applikation den bzw. die zugehörigen Dateideskriptoren zurück.
Beispiel 4-5. Beispielcode mit select
Zurück | Zum Anfang | Weiter |
Die Programmierschnittstelle der Applikation | Nach oben | Einfache Treiber |