Betriebssystemtheorie/ Datenträger und Dateisysteme

Aus Wikibooks
Zur Navigation springen Zur Suche springen
Zurück zu Geräteverwaltung Zurück zu Geräteverwaltung | Hoch zum Inhaltsverzeichnis Hoch zum Inhaltsverzeichnis | Vor zu Weiterführende Informationen Vor zu Weiterführende Informationen


Nuvola apps bookcase 1.svg Betriebssystemtheorie

Einleitung[Bearbeiten]

Der Zugriff auf Datenträger ist einer der wichtigsten und ältesten Dienste, welcher von Betriebssystemen angeboten wird. Besonders Unix ist hier zu erwähnen, da es den Zugriff auf Geräte und Systeminformationen über das Dateisystem bereitstellt. Alles ist eine Datei. nennt sich das Konzept.

Der Rest des Kapitels beschäftigt sich mit den Schichten der block-orientierten Ein- und Ausgabe, vom Datenträger aufsteigend zur Anwendung.

Block-orientierte Geräte[Bearbeiten]

Festplatten sind block-orientierte Geräte. Alle Daten sind in größeren Blöcken gespeichert. Ein Block umfasst in der Regel 512 Byte und wird als Sektor bezeichnet. Festplatten haben die folgenden Eigenschaften.

Block-orientierter Zugriff auf die Daten
Im Gegensatz zu zeichen-orientierten Geräten, wie Anschlüssen oder Erweiterungskarten, ist es nicht möglich ein einzelnes Zeichen vom Datenträger zu lesen oder auf den Datenträger zu schreiben sondern nur jeweils den Sektor, in dem sich das gesuchte Zeichen befindet. Dieses Verfahren ist ein Zugeständnis an die relativ langsamen Übertragungsgeschwindigkeiten und die riesigen Datenmengen.
Mehrfacher wahlfreier Zugriff
Die gespeicherten Daten können mehrfach in einer beliebigen Reihenfolge abgerufen werden. Im Gegensatz dazu können die Daten an zeichen-orientierten Geräten meist nur einmal in der Reihenfolge der Eingabe gelesen werden und werden anschließend aus dem Gerätespeicher entfernt.
Langzeitspeicherung
Während Arbeitsspeicher nur eine kurzzeitige Speicherung erlaubt, können Festplatten Daten über längere Zeiträume speichern. Eine Stromzufuhr ist dazu nicht erforderlich.

Neben Festplatten gibt es noch weitere block-orienterte Geräte, zum Beispiel USB-Sticks, Disketten oder CD-ROMs. Obwohl diese Datenträger einen anderen physischen Aufbau haben als Festplatten und sich in ihrer Funktionsweise teils deutlich von einander unterscheiden, teilen sie alle die genannten Merkmale.

Für eine detaillierte Diskussion der heute gebräuchlichen Datenträgertechnologien sei hier auf externe Quellen verwiesen. Für den Rest des Kapitels sind vor allen die oben genannten Eigenschaften wichtig. Die physikalische Speicherung ist eher eine Nebensache.

Redundant Array of Independent Drives[Bearbeiten]

Die Schicht oberhalb der block-orientierten Geräte wird als RAID bezeichnet. Unter RAID, ausgeschrieben Redundant Array of Independent Drives, versteht man einen Standard um mehrere Festplatten zu einer einzigen zusammen zu fügen. Dazu sind verschiedene Verfahren, sogenannte RAID-Level, üblich:

RAID 0 (Striping)
Beim Striping werden mehrere Festplatten zu einer einzigen großen zusammengefügt. Die Sektoren werden dabei reihum auf die Festplatten verteilt. Dadurch erhöht sich der Durchsatz beim Lesen und Schreiben von Daten. Aufgrund fehlender Redundanz bietet RAID 0 allerdings keine Vorteile bei der Fehlererkennung, beziehungsweise deren Korrektur, es erhöht sogar die Ausfallwahrscheinlichkeit für Daten, da diese bereits verloren sind, wenn eine Festplatte aus dem Verbund ausfällt.
RAID 1 (Mirroring)
Beim Mirroring wird eine Festplatte auf eine Zweite gespiegelt. Fällt die Platte aus, kann die andere weiterarbeiten, ohne dass Datenverlust droht oder das System abgeschaltet werden muss. Die Lesegeschwindigkeit kann ebenfalls erhöht werden, da das parallele Lesen von beiden Platten möglich ist.
RAID 5
RAID 5 kombiniert mehrere Festplatten und speichert zusätzliche Paritätsinformationen ab. In einem System mit n Platten enthalten jeweils n-1 Platten Daten im Sektor m und die n-te Festplatte ein XOR der Sektoren m. Alle Platten werden für die Speicherung der Paritätsinformationen benutzt und die Pariätssektoren werden gleichmäßig über alle Festplatten verteilt.

Neben diesen 3 gebräuchlichen Leveln gibt es noch ein Dutzend weitere Level, welche die grundlegenden Ideen anders kombinieren. Die meisten dieser Level finden heute allerdings keine Verbreitung mehr.

Aufgrund des Aufwands und der zusätzlichen Kosten wird RAID meist nur in Systemen verwendet, die hohe Anforderungen an die Verfügbarkeit und Integrität der gespeicherten Daten stellen. Darunter fallen Datei-Server oder spezialisierte Workstations.

Für die Implementierung von RAID gibt es spezielle Hardware-Kontroller, welche die angeschlossenen Festplatten verwalten und unabhängig vom Betriebssystem betrieben werden. Eine Alternative ist das sogenannte Software-RAID. Dieses wird durch einen Betriebssystemtreiber bereitgestellt. Durch den entstehenden Aufwand führt Software-RAID zu einer leicht erhöhten Prozessorbelastung. Außerdem führt es zu Problemen mit parallel installierten Betriebssystemen, die Software-RAID nicht unterstüzen. Eine (meist bessere) Alternative zu Software-RAID ist die Verwendung von Logischen Datenträgern.

Partitionen[Bearbeiten]

Um den Platz auf einer Festplatte besser nutzen und verwalten zu können, wird der enthaltene Speicher in logische Untereinheiten aufgeteilt.

Partition
Der Begriff Partition bezeichnet einen logischen Teil des Speichers eines Datenträgers.

Wenn man von logischer Unterteilung spricht, meint man, dass es hierbei (fast) keine Abhängigkeiten zum physischen Aufbau der benutzten Festplatte gibt.

MBR und Partitionstabelle[Bearbeiten]

Den ersten Sektor einer Festplatte nennt man Master Boot Record (MBR). Ihm kommt eine besondere Rolle zu, da er Informationen über die logische Aufteilung des Festplattenspeichers und den Bootloader enthält.

Master Boot Record
Erster Sektor einer Festplatte. Der MBR enthält den Bootloader und die Partitionstabelle.

Der Bootloader ist ein kleines Programm in den ersten 440 Byte des MBRs, welches beim Systemstart nach der Partition sucht, welche das Betriebssystem enthält.

Die Partitionstabelle ist die andere wichtige Komponente im MBR. Sie umfasst 64 Byte im MBR und beschreibt die auf dem Datenträger enthaltenen Partitionen. Ein Eintrag umfasst die folgenden Daten:

  • Bootfähigkeit
  • CHS-Eintrag des ersten Sektors
  • Typ des enthaltenen Dateisystems
  • CHS-Eintrag des letzten Sektors
  • Startsektor
  • Anzahl der Sektoren in der Partition

Jeder Eintrag umfasst 16 Byte. Die Partitionstabelle kann also maximal 4 Einträge enthalten. Um diese Einschränkung zu umgehen, wurden erweiterte Partitionen eingeführt. Erweiterte Partitionen sind Partitionen, die nochmals in logische Partitionen unterteilt sind. Am Beginn einer erweiterten Partition befindet sich der erste Extended Boot Record (EBR), welcher ähnlich einem Eintrag in der Partitiontabelle, die erste logische Partition beschreibt. Nach Ende der ersten logischen Partition folgt der zweite EBR, welcher die zweite logische Partition beschreibt und so weiter. Hierbei gibt es keine Höchstgrenze an logischen Partitionen. Lediglich Grenzen im verwendeten Betriebsystem können die Anzahl limitieren.

Logische Datenträger[Bearbeiten]

Logische Datenträger dienen als weitere Abstraktionsschicht zwischen Partition und Dateisystem. Ihre Nutzung erlaubt eine flexible Verteilung des Speicherplatzes, das Zusammenfassen mehrerer Datenträger und das Ändern der Größe einer Partition im Betrieb. Außerdem kann man in dieser Schicht einige "Spezialeffekte" anwenden, zum Beispiel Kompression oder Verschlüsselung des Dateisystems.

Dateisysteme[Bearbeiten]

Die komplexeste Schicht beim Zugriff auf Datenträger sind die Dateisysteme.

Dateisystem
Ein Dateisystem organisiert die Daten auf einem Datenträger.

Funktionsweise[Bearbeiten]

Der erste Schritt ist die Bildung größerer Informationsblöcke. Deren Größe wird in Abhängigkeit zur Sektorgröße des zugrunde liegenden Datenträgers gewählt, also 512 Byte oder ein Vielfaches davon. Übliche Werte sind auch 1024, 2048 und 4096 Byte. Jeder Block kann entweder zu genau einer Datei gehören oder ungenutzt sein. Beginnend am Anfang der Partition werden alle Blöcke gleichmäßig und ohne Lücken gebildet und durchnummeriert.

Obwohl die Blockgröße für das Funktionieren des Dateisystems irrelevant ist, kann man durch eine geschickte Wahl einen bessere Nutzung des Speicherplatzes erreichen. Befinden sich sehr viele kleine Dateien auf einem Datenträger, ist es sinnvoll eine kleine Blockgröße zu wählen. Da jeder Block nur zu einer Datei gehören kann, würden große Blöcke nie vollständig gefüllt werden. Befinden sich hingegen eher große Dateien auf einem Datenträger ist es sinnvoll eine hohe Blockgröße zu wählen und somit die Gesamtanzahl der Blöcke zu verringern. Bei einer geringeren Blockanzahl benötigt das Dateisystem weniger Verwaltungsdaten. Es wird also mehr Speicher für Nutzdaten frei.

Aufbauend auf die Einteilung der Partition in Blöcke enthält ein Dateisystem eine Liste mit sämtlichen Dateien, sowie deren Attribute und gegebenenfalls deren Lage auf dem Datenträger. Einige typische Attribute sind:

  • Dateityp
  • Dateiname
  • Besitzer und Gruppe der Datei
  • Zugriffsrechte
  • Metadaten, Inhalt, Zusammenfassung, etc.

Den Begriff Dateiliste sollte man in diesem Zusammenhang nicht allzu wörtlich nehmen. Moderne Dateisysteme nutzen baumförmige Datenstrukturen, deren hierarchischer Aufbau sich besser zum Organisieren großer Datenmengen eignet.

Dateitypen[Bearbeiten]

Die meisten Dateisysteme kennen drei verschiedene Dateitypen: Reguläre Dateien, Verzeichnisse und Verknüpfungen.

Bei regulären Dateien handelt es sich um einen Speicherbereich auf einem Datenträger, welcher Informationen enthält. Jeder Datei sind dabei Blöcke im Dateisystem zugeordnet. Die Anzahl der Blöcke muss dabei groß genug sein, um alle in der Datei enthaltenen Zeichen zu speichern. Bei einer Blockgröße von 4096 Byte benötigt eine Datei mit 4096 Byte genau einen Block. Eine Datei mit 4097 Byte benötigt genau zwei Blöcke. In manchen Dateisystemen enthält ein Block noch einen Verweis auf seinen Nachfolger. Der benötigte Speicher steht für Nutzdaten folglich nicht zu Verfügung.

Die meisten Leute überrascht es, aber Verzeichnisse sind gewöhnliche Dateien, welche jedoch einen besonderen Inhalt aufweisen. Statt Nutzdaten enthalten Verzeichnisse Verweise auf die enthaltenen Elemente, beziehungsweise auf deren Einträge in die Dateitabelle.

Eine Verknüpfung stellt eine Verbindung zu einer anderen Datei dar. Sie ist ein Zeiger innerhalb des Dateisystems. Verknüpfungen enthalten also streng genommen keine eigenen Daten, sondern nutzen die Daten anderer Dateien. Man kann zwischen zwei verschiedenen Typen von Verknüpfungen unterscheiden. Harte Verknüpfungen zeigen auf Einträge in der Dateisystemtabelle. Ihr Vorteil besteht darin, dass sie auch gültig bleiben, falls die referenzierte Datei verschoben oder umbenannt wird. Zwar ändert sich bei diesen Operationen der Name oder Pfad einer Datei, ihr Eintrag in der Dateitabelle ändert sich hingegen nicht. Es ist allerdings nicht möglich in die Dateitabelle eines anderen Dateisystems zu zeigen. Harte Verknüpfungen funktionieren daher nicht über Partitionsgrenzen hinweg. In diesen Fällen eignen sich weiche Verknüpfungen. Sie zeigen nicht auf Einträge in eine Dateitabelle, sondern auf Pfade. Da hierbei keine Details der benutzten Dateisysteme benutzt werden, kann eine Verknüpfung auch über Partitionsgrenzen aufgelöst werden. Dies ist allerdings auch der Nachteil weicher Verknüpfungen. Da sie unabhängig vom Dateisystem existieren, kann die referenzierte Datei entfernt werden, ohne dass die Verknüpfung entfernt wird. Sie ist nun ungültig. Erzeugt man eine neue Datei mit dem alten Pfadnamen, wird die Verknüpfung wieder gültig.

Journaling[Bearbeiten]

Viele moderne Dateisysteme beherrschen Journaling. Beim Journaling handelt es sich um eine Technologie, welche die Operationen mitprotokolliert, die auf dem Dateisystem ausgeführt werden.

Der Nutzen des Verfahrens soll an einem Beispiel erläutert werden. Das Kopieren einer Datei lässt sich grob in 3 Schritte zerlegen:

  1. Reservieren von Blöcken für die Zieldatei auf dem Datenträger.
  2. Kopieren der Inhalte aus den Blöcken der Quelldatei in die Blöcke der Zieldatei.
  3. Erstellen eines Eintrages für die Zieldatei in der Dateitabelle.

Während dieses Vorgangs befindet sich das Dateisystem in einem inkonsistenten Zustand. Wird er unterbrochen, sind zwar Blöcke auf dem Datenträger belegt, aber keiner Datei zugeordnet. Der Speicher geht vorerst verloren. Zur Behebung eines solchen Fehlers muss in einem Dateisystem ohne Journaling der gesamte Datenträger auf Blöcke ohne zugehörige Datei untersucht werden.

Dateisysteme mit Journaling protokollieren alle Teilschritte in einem reservierten Teil des Datenträgers, dem Journal, mit. Folglich muss zur Reparatur nur das Journal durchgesehen werden und die dort eingetragenen Operationen vervollständigt werden. Die Teile des Dateisystems, die von den Operationen nicht betroffen sind, können nicht korrupt sein und müssen nicht überprüft werden.

Die Vorgehensweise beim Journaling ist dabei, dass das Dateisystem im Journal alle Operationen vermerkt, die ausgeführt werden sollen, sowie jeweils die Änderungen, die dazu notwendig sind. Anschließend werden die Änderungen Schritt für Schritt ausgeführt. Um die Konsistenz des Dateisystems sicherzustellen, gelten für Operationen die folgenden Nebenbedingungen:

  • Eine Operation ist genau dann gültig, wenn alle Teilschritte korrekt ausgeführt wurden.
  • Ungültige Operationen werden komplett verworfen und haben keine Auswirkungen auf den Zustand des Dateisystems.

Da bei vollem Journaling alle Daten doppelt geschrieben werden müssen, hat es zum Teil einen deutlich negativen Einfluss auf die Geschwindigkeit der Operationen. Möchte man beispielsweise Daten in eine Datei schreiben, müssen diese zuerst im Journal gespeichert werden und anschließend nochmals in der Datei. Eine einfache Lösung besteht im Metadaten-Journaling, bei dem die Konsistenzbedingungen gelockert werden. Der Zustand des Dateisystems wird weiterhin konsistent gehalten, aber nicht die Dateiinhalte, da die Nutzdaten nicht im Journal vermerkt werden. Tritt ein Fehler während einer Schreiboperation auf, wird zwar die Datei mit den korrekten Attributen erzeugt, der Dateiinhalt kann allerdings korrupt sein.

Bekannte Dateisysteme[Bearbeiten]

File Allocation Table[Bearbeiten]

Extended File System 2[Bearbeiten]

Extended File System 3[Bearbeiten]

Virtuelles Dateisystem[Bearbeiten]

Für Anwendungen sichtbar ist das VFS. Das virtuelle Dateisystem (VFS) bietet Darstellung und Zugriff auf Dateien, unabhängig von den zugrunde liegenden Dateisystemen. Die grundlegende Datenstruktur des VFS ist der Index Node (Inode). Inodes enthalten die Attribute genau eines Objekts im VFS und verweisen auf die jeweilige Datei des darunter liegenden Dateisystems. Jeder Datei ist mindestens ein Inode zugeordnet.

Abstraktion[Bearbeiten]

Das VFS ist so eng mit den darunter liegenden Dateisystemen verbunden, dass eine vollständige Abstraktion unmöglich ist. Die gute Nachricht ist allerdings, dass man sich meistens mit einigen Tricks behelfen kann.

Dateisysteme, die für ein konkretes Betriebssystem entwickelt werden, implementieren auch die üblichen Eigenschaften des dazu gehörenden VFS. Ein Dateisystem für Unix bietet immer die typische Zugriffskontrolle, Verknüpfungen, sowie die Unterscheidung von Groß- und Kleinschreibung. Die Integrierung dieser Dateisysteme in ein kompatibles VFS ist meist recht einfach.

Andere Dateisysteme, für Systeme mit inkompatiblen Konzepten, sind hingegen schwerer einzubinden. Kann ein Dateisystem die Eigenschaften des VFS nicht bieten, muss der Treiber sinnvolle Einstellungen anbieten. Beispielsweise kann das Dateisystem FAT weder Zugriffskontrolle, noch Verknüpfungen. Der FAT-Treiber in Unix-Systemen bietet daher immer alle Zugriffsattribute für alle Dateien und meldet einen Fehler, wenn der Benutzer eine Verknüpfung erzeugen will.

Komplizierter ist es, falls das Dateisystem mehr Funktionen bietet als das VFS. Das Dateisystem NTFS, welches unter Windows NT, 2000 und XP üblich ist, bietet zum Beispiel eine sehr umfangreiche Unterstützung von Zugriffsrechten, welche inkompatibel zum einfachen VFS von Unix ist. Die eine Lösung für dieses Problem besteht im kompletten Weglassen solcher Funktionen. Im gegebenen Beispiel wäre NTFS unter Unix nur noch zum Lesen und Schreiben von unkritischen Daten verwendbar, da alle Sicherheitselemente fehlen. Als alternative Lösung kann man versuchen, sinnvolle Abbildungen zwischen den Funktionen des Dateisystems und des VFS zu finden. Das geht manchmal besser und manchmal schlechter.

Benutzer und Zugriffsrechte[Bearbeiten]

Das zugrunde liegende Dateisystem speichert für jede Datei Informationen für die Zugriffskontrolle. Im VFS werden die Informationen in den Inodes gehalten und die Zugriffsrechte durchgesetzt.

Nutzer und Gruppen[Bearbeiten]

Ein einfaches Modell bietet das VFS in Unix. Jeder Datei sind lediglich einige wenige Attribute zugeordnet:

  • Jede Datei hat einen Besitzer.
  • Jede Datei befindet sich in einer Gruppe.
  • Beim Zugriff auf eine Datei unterscheidet das VFS zwischen:
    • Dem Besitzer,
    • Den Mitgliedern der Gruppe, in der sich die Datei befindet und
    • Allen anderen.
  • Es gibt jeweils die drei boolschen Attribute
    • Lesbar,
    • Schreibbar und
    • Ausführbar.

Öffnet ein Benutzer eine Datei, überprüft das VFS, welche Rechte er besitzt.

  • Ist der Benutzer der Besitzer der Datei, gelten die Attribute für den Besitzer.
  • Ist der Benutzer nicht der Besitzer, aber Mitglied der assoziierten Gruppe, gelten die Attribute für Gruppenmitglieder
  • Ist der Benutzer weder Besitzer der Datei, noch Gruppenmitglied, gelten die Attribute für alle anderen

Nachdem die Attribute bestimmt wurden, überprüft das VFS, ob die gewünschte Operation erlaubt ist. Möchte der Benutzer aus der Datei lesen, muss das Lesbar-Attribut gesetzt sein. Will der Benutzer in die Datei schreiben, muss das Schreibbar-Attribut gesetzt sein. Beide Modi können als Parameter des Systemaufrufs angegeben werden. Bei Verzeichnissen zeigen diese Attribute an, ob der Benutzer den Verzeichnisinhalt auslesen darf, beziehungsweise, ob er Dateien im Verzeichnis erzeugen darf. Das Attribut Ausführbar zeigt an, ob der Benutzer eine Datei ausführen darf. Bei Verzeichnissen gibt es an, ob der Benutzer in das Verzeichnis wechseln darf.

Obwohl dieses Modell sehr einfach ist, leistet es schon eine ganze Menge. Besonders interessant ist es für Privatanwender und halbprofessionelle Anwender, da ohne hohen Aufwand ein großer Nutzen erreicht werden kann. Durch die Trennung von System- und Benutzerdaten wird vielen Schadprogrammen bereits eine beträchtliche Hürde gesetzt.

Access Control Lists und Capabilities[Bearbeiten]

In vielen professionellen Systemen hat man mehrere Benutzer, die mit verschiedenen, differenzierten Rechten ausgestattet sind. Das Modell aus Benutzern und Gruppen ist meistens zu schwach, um solche Zusammenhänge auszudrücken.

In einem System gibt es zum beispielsweise eine Datei D. Auf D können genau drei Benutzer zugreifen. Benutzer L kann nur lesen, Benutzer S nur schreiben und Benutzer A nur ausführen. Egal wie man das Problem dreht und wendet, es kann im beschriebenen Modell nicht dargestellt werden.

Die verbreitete Lösung liegt in Access Control Lists (ACL) und Capabilities.

Access Control Lists speichern für jedes Objekt im Dateisystem die Nutzer, die darauf zugreifen dürfen, sowie die jeweiligen Zugriffsrechte. Für die Datei D werden also drei Einträge gespeichert, jeweils einer für L, S und A.

Capabilities gehen den umgekehrten Weg. Sie stellen Zugriffsrechte auf Dateien dar, die jedem Benutzer zugeteilt werden können. Hierbei bekommt der Benutzer L eine Capability zum Lesen der Datei D, der Benutzer S eine Capability zum Schreiben von D und der Benutzer A eine Capability zum Ausführen.

ACLs und Capabilities können gemeinsam dargestellt werden. Man schreibt in eine Matrix in jede Zeile einen Benutzer und in jede Spalte ein Objekt im Dateisystem. Die Zellen der Matrix werden mit Zugriffsrechten des jeweiligen Benutzers auf die jeweilige Datei gefüllt. Zeilenweise können nun die Capabilities ausgelesen werden und spaltenweise die ACLs.

Anwendung[Bearbeiten]

Damit eine Anwendung auf das Dateisystem zugreifen kann, werden vom Betriebssystem die nötigen Funktionen bereit gestellt. Der minimale Umfang auf einem Unix-System besteht aus vier Aufrufen.

int open(char *filename, int mode)
Öffnet eine Datei. Wenn die Datei nicht existiert, wird sie automatisch angelegt, falls der Benutzer die nötigen Schreibrechte besitzt. Der Parameter filename bezeichnet den Dateinamen und mode die Zugriffsart. Der Rückgabewert ist ein Dateideskriptor, mit dem die geöffnete Datei benutzt werden kann.
void close(int fd)
Schließt eine geöffnete Datei. Der Parameter fd ist ein Dateideskriptor.
int read(int fd, char *buf, int siz)
Liest Zeichen aus der Datei. Dabei zeigt buf auf die Zieladresse im Arbeitsspeicher und siz gibt die Anzahl der zu lesenden Zeichen an.
int write(int fd, char *buf, int siz)
Schreibt Zeichen in eine Datei.

Mit diesen Funktionen kann ein Programm bereits die wichtigsten Operationen im Dateisystem durchführen und weitere Aktionen, wie Datei kopieren oder Datei verschieben, selbst implementieren. Solche mehrstufigen Aktionen sind meist in einem zusätzlichen Interface für das Dateisystem bereitgestellt.

Weitere typische Funktionen sind

int lseek(int fd, int pos)
Setzt die Lese-, beziehungsweise Schreibposition des Dateideskriptors.
int flush(int fd)
Schreibt alle Änderungen an einem Dateideskriptor zurück auf die Festplatte.
int fcntl(int fd, int cmd, ...)
Ändert ein Dateiattribut. Damit lasen sich zum Beispiel die Zugriffsrechte einer Datei oder eines Dateideskriptors auslesen.

Die Dateideskriptoren, welche von open zurückgegeben werden, sind nicht identisch mit den Dateien, auf die sie zeigen. Das bedeutet, dass ein Programm mehrere Male die selbe Datei öffnen kann und jeweils einen anderen Dateideskriptor erhält. Daher ergibt sich eine Besonderheit in Unix-Systemen: die Möglichkeit, eine Datei zu manipulieren, während ein anderes Programm diese benutzt. Folgendes Beispiel soll das Konzept erläutern.

Versucht ein Programm A eine Datei zu schreiben, die gleichzeitig von einem anderen Programm B geöffnet ist, wird der betroffene Inode kopiert und ins Dateisystem hinzugefügt. Der Dateideskriptor in Programm A zeigt nun auf die offizielle neue Version der Datei. Der Dateideskriptor in B zeigt noch auf die alte Version. Schließt B seinen Dateideskriptor, wird der alte Inode automatisch gelöscht. Alle weiteren Versuche, die Datei zu öffnen benutzen immer die neueste Version.

Dieses Prinzip verwirrt häufig Programmierer, die zum ersten Mal mit Unix arbeiten. Es bietet allerdings einige Vorteile. Zum Einen können mehrere Programme die gleiche Datei manipulieren, ohne dass das Betriebssystem die Änderungen bekannt geben muss. Möchte eine Anwendung die Änderungen am Dateisystem beobachten, kann sie sich auf den meisten Systemen über ein unabhängiges Interface darüber informieren lassen, zum Beispiel Inotify in Linux. Zum Anderen ist es möglich, neue Versionen von Programmen oder Dokumenten zu installieren, ohne das Betriebssystem neu starten zu müssen. Nach erfolgreicher Installation der Dateien müssen nur die betroffenen Anwendungen neu gestartet werden.