Passa al contenuto principale

Se avete mai provato ad usare programmi basati su POSIX per elaborare file strutturati VOS, potreste aver incontrato alcune restrizioni o aver visto qualche comportamento che non avete capito. In questo post cercherò di spiegarvi cosa sta succedendo.

VOS supporta 4 tipi di file: sequenziale, relativo, fisso e stream. I primi 3 formati sono chiamati file "strutturati" perché il file system tiene traccia dei confini dei record. Le operazioni I/O disponibili leggono e scrivono interi record. L'ultimo formato è chiamato "non strutturato" perché i confini dei record sono impliciti; il carattere newline delimita i record. Le operazioni I/O disponibili leggono e scrivono sequenze di byte.

Un ambiente conforme a POSIX, come quello che si trova su un sistema Unix® o Linux©, ha solo un tipo di file nativo, che è chiamato "file normale". L'organizzazione dei file di flusso VOS è equivalente a un file normale POSIX.

L'ambiente di runtime VOS POSIX classifica tutti e 4 i tipi di file come file normali POSIX. Quindi, almeno in teoria, qualsiasi programma POSIX può leggere o scrivere uno qualsiasi dei 4 tipi di file. Tuttavia, non è così semplice.

Poiché l'API POSIX definisce tutte le operazioni di I/O in termini di sequenze di byte, mentre VOS definisce le operazioni di I/O (su file strutturati) in termini di sequenze di record, il runtime di VOS POSIX media la differenza bufferizzando il record corrente nello spazio utente, eseguendo le operazioni di I/O POSIX sul buffer, e poi riscrivendo il record bufferizzato in punti appropriati.

Se il programma POSIX conosce la dimensione di ogni record (ad esempio, per un file fisso), e se legge e scrive il numero esatto di byte, allora la presenza del buffer non influisce sull'operazione, e la mappatura dei due tipi di operazioni di I/O è facile da capire ed efficiente.

Ma se il programma POSIX si limita a leggere o scrivere un flusso di byte senza tener conto della dimensione del record sottostante, allora la mappatura della semantica POSIX con la semantica VOS, anche se ben definita, non è generalmente molto utile, e spesso è piuttosto inefficiente. Alcune operazioni, come la ricerca della posizione di un byte, o la riscrittura di una sequenza di byte che si estende attraverso il confine di un record, sono inefficienti nel migliore dei casi e impossibili nel peggiore dei casi.

Poi c'è la questione della gestione dei caratteri newline.

Sia un file POSIX normale che un file di flusso VOS utilizzano il carattere newline per distinguere il confine di un record. Tuttavia, i record VOS in file strutturati in genere non contengono caratteri di newline. Ad esempio, quando un editor VOS (ad esempio, edit, emacs, o line_edit) crea un nuovo file sequenziale, ogni record contiene una riga di testo. Ma il record non termina con un carattere a nuova riga. Per convenzione, tutti i programmi presuppongono che un file sequenziale che contiene testo abbia una riga di testo implicita alla fine di ogni record. Lo stesso vale per i file relativi e fissi. Ma qui c'è un punto importante: nessun attributo di alcun file (VOS, Unix, strutturato o non strutturato) registra se il file contiene testo o dati binari. La distinzione è lasciata ai programmi che accedono al file.

Questa situazione crea una sorta di dilemma per il runtime di VOS POSIX. Deve sapere se un file strutturato VOS contiene testo o dati per sapere se aggiungere o meno una nuova riga ad ogni record. Se il file contiene testo, dovrebbe aggiungere una nuova riga. Se contiene dati, non dovrebbe aggiungere una nuova riga.

La risposta è che il runtime di VOS POSIX dipende dal chiamante per fornire queste informazioni. Per impostazione predefinita, il runtime POSIX tratta i file strutturati come se contenessero testo e aggiunge una nuova linea; un chiamante può richiedere esplicitamente questo comportamento fornendo la modalità di apertura O_TEXT. Un chiamante che vuole trattare un file strutturato VOS come se contenesse dati deve fornire la modalità di apertura O_BINARY. Queste due modalità si escludono a vicenda; se si specifica una di esse, non si deve specificare l'altra. Queste modalità non sono necessarie per i file di flusso, e quindi sono ignorate in questo caso.

Per i giuristi linguistici che stanno leggendo questo post, permettetemi di notare rapidamente che sia O_TEXT che O_BINARY sono estensioni dello standard POSIX; non sono definite dal POSIX stesso. Sono tipicamente presenti solo su sistemi operativi che distinguono tra file di testo e file binari (come fa VOS), o hanno una speciale convenzione di fine linea (come fa Windows; utilizzando CR-LF).

Per politica, quando Stratus porta il software basato su POSIX su OpenVOS, lo modifichiamo per escludere l'uso di file FISSO e RELATIVO, e limitiamo i file SEQUENZIALI all'accesso in sola lettura. Partiamo anche dal presupposto che tutti i file sequenziali contengano testo. Secondo la nostra esperienza, queste regole rendono pratico l'uso di file STREAM o SEQUENZIALI come input per i programmi POSIX, evitando le inefficienze intrinseche del tentativo di eseguire operazioni byte-oriented sui file di output SEQUENZIALI.

In sintesi, l'approccio migliore è quello di utilizzare solo file STREAM (per l'input o l'output) e file SEQUENZIALI (per il solo input di testo) con programmi basati su POSIX. Se si dispone di dati binari in file strutturati, scrivere un piccolo programma per copiarli in un file stream e poi utilizzare la versione stream del file con i programmi POSIX. Se si dispone di dati di testo in un file FISSO o RELATIVO che si desidera elaborare con i programmi POSIX, copiare prima il file in un file STREAM.

© 2024 Stratus Technologies.