Wenn Sie jemals versucht haben, POSIX-basierte Programme zur Verarbeitung von strukturierten VOS-Dateien zu verwenden, sind Sie vielleicht auf einige Einschränkungen gestoßen oder haben ein Verhalten gesehen, das Sie nicht verstanden haben. In diesem Beitrag werde ich versuchen zu erklären, was vor sich geht.
VOS unterstützt 4 Arten von Dateien: sequentielle, relative, feste und Stream-Dateien. Die ersten 3 Formate werden als "strukturierte" Dateien bezeichnet, da das Dateisystem die Grenzen der Datensätze festhält. Die verfügbaren E/A-Operationen lesen und schreiben ganze Datensätze. Das letzte Format wird als "unstrukturiert" bezeichnet, da die Datensatzgrenzen implizit sind; das Newline-Zeichen grenzt die Datensätze ab. Die verfügbaren E/A-Operationen lesen und schreiben Bytesequenzen.
Eine POSIX-konforme Umgebung, wie sie auf einem Unix®- oder Linux©-System zu finden ist, hat nur einen nativen Dateityp, der als "reguläre Datei" bezeichnet wird. Die Organisation der VOS-Streamdateien entspricht einer regulären POSIX-Datei.
Die POSIX-Laufzeitumgebung von VOS klassifiziert alle 4 Dateitypen als reguläre POSIX-Dateien. Zumindest theoretisch kann also jedes POSIX-Programm jeden der 4 Dateitypen lesen oder schreiben. Ganz so einfach ist es jedoch nicht.
Da die POSIX-API alle E/A-Operationen in Form von Bytefolgen definiert, während VOS E/A-Operationen (auf strukturierte Dateien) in Form von Datensatzfolgen definiert, vermittelt die VOS-POSIX-Laufzeit den Unterschied, indem sie den aktuellen Datensatz im Benutzerraum puffert, die POSIX-E/A-Operationen auf dem Puffer durchführt und dann den gepufferten Datensatz an den entsprechenden Stellen zurückschreibt.
Wenn das POSIX-Programm die Größe jedes Datensatzes kennt (z. B. für eine feste Datei) und wenn es die genaue Anzahl von Bytes liest und schreibt, dann hat das Vorhandensein des Puffers keinen Einfluss auf die Operation, und die Zuordnung der beiden Arten von E/A-Operationen ist leicht verständlich und effizient.
Wenn das POSIX-Programm jedoch nur einen Strom von Bytes liest oder schreibt, ohne die zugrunde liegende Datensatzgröße zu berücksichtigen, dann ist die Abbildung der POSIX-Semantik auf die VOS-Semantik zwar wohldefiniert, aber im Allgemeinen nicht sehr nützlich und oft ziemlich ineffizient. Bestimmte Operationen, wie die Suche nach einer Byte-Position oder das Umschreiben einer Byte-Sequenz, die sich über eine Datensatzgrenze erstreckt, sind im besten Fall ineffizient und im schlimmsten Fall unmöglich.
Dann ist da noch die Frage der Behandlung von Zeilenumbruchzeichen.
Sowohl eine reguläre POSIX-Datei als auch eine VOS-Stream-Datei verwenden das Newline-Zeichen, um eine Satzgrenze zu kennzeichnen. VOS-Datensätze in strukturierten Dateien enthalten jedoch in der Regel keine Zeilenumbruchzeichen. Wenn zum Beispiel ein VOS-Editor (z.B. edit, emacs oder line_edit) eine neue sequentielle Datei erstellt, enthält jeder Satz eine Zeile Text. Der Datensatz endet jedoch nicht mit einem Zeilenumbruchzeichen. Die Programme gehen alle davon aus, dass eine sequentielle Datei, die Text enthält, am Ende jedes Satzes einen impliziten Zeilenumbruch hat. Das Gleiche gilt für relative und feste Dateien. Aber hier ist ein wichtiger Punkt: Kein Attribut einer Datei (VOS, Unix, strukturiert oder unstrukturiert) hält fest, ob die Datei Text oder binäre Daten enthält. Die Unterscheidung wird den Programmen überlassen, die auf die Datei zugreifen.
Diese Situation stellt die VOS-POSIX-Laufzeitumgebung vor ein gewisses Dilemma. Sie muß wissen, ob eine strukturierte VOS-Datei Text oder Daten enthält, damit sie weiß, ob sie an jeden Datensatz einen Zeilenumbruch anhängen soll oder nicht. Wenn die Datei Text enthält, sollte sie einen Zeilenumbruch anhängen. Enthält sie Daten, sollte sie keinen Zeilenumbruch anfügen.
Die Antwort ist, dass die VOS-POSIX-Laufzeit vom Aufrufer abhängt, der diese Informationen bereitstellt. Standardmäßig behandelt die POSIX-Laufzeit strukturierte Dateien so, als ob sie Text enthielten, und hängt einen Zeilenumbruch an; ein Aufrufer kann dieses Verhalten explizit anfordern, indem er den Öffnungsmodus O_TEXT angibt. Ein Aufrufer, der eine strukturierte VOS-Datei so behandeln will, als enthalte sie Daten, muss den Öffnungsmodus O_BINARY angeben. Diese beiden Modi schließen sich gegenseitig aus; wenn Sie einen der beiden Modi angeben, dürfen Sie den anderen nicht angeben. Diese Modi sind für Stream-Dateien nicht erforderlich und werden daher in diesem Fall ignoriert.
Für die Sprachjuristen, die diesen Beitrag lesen, möchte ich kurz anmerken, dass sowohl O_TEXT als auch O_BINARY Erweiterungen des POSIX-Standards sind; sie werden nicht von POSIX selbst definiert. Sie sind typischerweise nur auf Betriebssystemen vorhanden, die zwischen Text- und Binärdateien unterscheiden (wie VOS) oder eine spezielle Konvention für das Zeilenende haben (wie Windows; mit CR-LF).
Wenn Stratus POSIX-basierte Software nach OpenVOS portiert, modifizieren wir sie, um die Verwendung von FIXED- und RELATIVE-Dateien auszuschließen, und wir beschränken SEQUENTIAL-Dateien auf den Nur-Lese-Zugriff. Wir nehmen auch an, dass alle sequentiellen Dateien Text enthalten. Unserer Erfahrung nach machen es diese Regeln praktisch, entweder STREAM- oder SEQUENTIAL-Dateien als Eingabe für POSIX-Programme zu verwenden und gleichzeitig die inhärenten Ineffizienzen zu vermeiden, die entstehen, wenn man versucht, byteorientierte Operationen auf SEQUENTIAL-Ausgabedateien durchzuführen.
Zusammenfassend lässt sich sagen, dass es am besten ist, mit POSIX-basierten Programmen nur STREAM-Dateien (für die Ein- oder Ausgabe) und SEQUENTIAL-Dateien (nur für die Eingabe von Text) zu verwenden. Wenn Sie binäre Daten in einer strukturierten Datei haben, schreiben Sie ein kleines Programm, um sie in eine Stream-Datei zu kopieren, und verwenden Sie dann die Stream-Version der Datei mit POSIX-Programmen. Wenn Sie Textdaten in einer FIXED- oder RELATIVE-Datei haben, die Sie mit POSIX-Programmen verarbeiten wollen, kopieren Sie die Datei zunächst in eine STREAM-Datei.