Operační systém UNIX a jazyk C

Jan Brodský
Luděk Skočovský

SNTL Nakladatelství technické literatury Praha 1989, ISBN 80-03-00049-1

10. Implementace


10.5 Proces a soubory

Dosud popsané tabulky jsou vnitřní záležitostí jádra. Proces se soubory pracuje voláním jádra open, creat atd. a tak tyto tabulky nepřímo využívá. Je proto důležité, aby programátor věděl, jak.

10.5.1 Evidence otevřených souborů

Soubory v Unixu jsou považovány za posloupnost slabik. S každým otevřeným souborem je spjato ukazovátko na příští čtenou, resp. zapisovanou slabiku. Ukazovátko se posouvá voláním read, resp. write. Dá se rovněž přestavit voláním lseek. Jeden soubor přitom může být otevřen pro více procesů současně. Vznikne tak problém, kam vlastně ukazovátko patří.

Kdyby ukazovátko patřilo k i-uzlu souboru, procesy by neměly možnost nezávislé práce s týmž souborem. Kdyby ukazovátko patřilo k procesu, nemohly by procesy spolupracovat - sdílet soubor s totožným ukazovátkem. Unix tento problém řeší zavedením dvoustupňového zobrazení.

Ve struktuře user (odst. 10.2.3) je uložena tabulka otevřených souborů procesu. Technicky jde o pole ofile ukazatelů na strukturu file. Deskriptor souboru, vrácený voláním open nebo creat, je indexem do této tabulky ofile.

Ukazatele vedou do systémové tabulky otevřených souborů file, která je tvořena polem struktur

extern struct file {
	char flag;		/* stav */
	char count;		/* kolikrát je otevřen - sdíleně */
	struct inode *ino;	/* odkaz do tabulky aktivních i-uzlů */
	off_t offset;		/* ukazovátko */
} file[];

V této struktuře je právě uloženo ukazovátko offset na příště čtenou, resp. zapisovanou slabiku souboru. Povšimněte si obr. 10.14, kde jsou znázorněny některé používané příznakové bity (čl. 10.6).

[OBR. 10.14]

Vzájemné vztahy všech zúčastněných tabulek jsou uvedeny na obr. 10.15.

10.5.2 Práce se soubory

Na obr. 10.15 můžeme rovněž ukázat implementaci jednotlivých volání. Volání offset převede úplné jméno souboru (cestu) na číslo i-uzlu a popř. vytvoří záznam v tabulce aktivnách i-uzlů s odkazem (1). Odkaz (2) na tento záznam se uloží do systémové tabulky otevřených souborů. Odkaz (3) do této tabulky se uloží do prvního volného ukazatele v poli ofile a index do ofile se vrátí jako deskriptor souboru.

[OBR. 10.15]

Každé volání open (i na týž soubor) vytvoří nový záznam v systémové tabulce otevřených souborů a tím i nové ukazovátko. To je cesta pro nezávislou činnost několika procesů s jedním souborem. Naopak procesy vzniklé voláním fork jádra od svého rodičovského procesu zdědí tabulku otevřených souborů procesu, a tím i odkazy do systémové tabulky otevřených souborů. Oba procesy pak sdílí totéž ukazovátko do souboru.

Při vytváření souboru voláním creat jádro nejprve vytvoří i-uzel na disku, jeho číslo spolu se jménem vytvářeného souboru uloží do adresáře a dále postupuje stejně jako v případě volání open. Vytváří-li se již existující soubor, použije se jeho stávající i-uzel.

Volání close uvolní ty záznamy, které volání open nebo creat vytvořily. Součástí všech struktur je složka count. Každé otevření k ní přičte jedničku, každé uzavření jedničku odečte. Klesne-li count na nulovou hodnotu, žádný proces už strukturu nepotřebuje a jádro ji uvolní.

V i-uzlu se dále ve složce nlink udržuje počet odkazů na soubor z adresářů. Při vytvoření souboru se nastaví hodnotou 1, každé volání link zvýší počet o 1. Voláním unlink se počet sníží o 1. Klesne-li počet odkazů na nulu, není soubor dále evidován v žádném adresáři, může být zrušen a i-uzel na disku uvolněn. Může přitom dojít k zajímavé situaci, kdy je zrušen aktivní soubor, tj. soubor otevřený a dosud evidovaný v tabulce aktivních i-uzlů; existuje pak do nejbližšího volání close jako bezejmenný.

10.5.3 Implementace datových operací

Požádá-li proces o datovou operaci voláním read, resp. write, naplní se složky base a count struktury user podle argumentů volání a složka offset ze systémové tabulky otevřených souborů (ukazovátkem).

Z tabulky aktivních i-uzlů se zjistí, o jaký soubor jde. Je-li to znakový speciální soubor, jádro vyvolá příslušné funkce ovládače. V tabulce i-uzlů zjistí identifikaci zařízení (major, minor) a adresy funkcí jsou umístěny v tabulce cdevsw.

U blokových zařízení se spočte číslo bloku (podělí se offset délkou bloku). Odkazuje-li i-uzel na obyčejný soubor, zjistí se mechanismem popsaným v odst. 10.4.4 disková adresa bloku. Odkazuje-li i-uzel přímo na speciální soubor blokového zařízení, udává offset přímo diskovou adresu bloku.

V obou případech jádro požádá svou správu vyrovnávacích pamětí o čtení, resp. zápis bloku. To je však situace popsaná v odst. 10.3.3. Buď je požadovaný blok v systémové vyrovnávací paměti, pak se operace provede mezi ní a adresovým prostorem procesu, nebo v ní není. Pak se nejprve do vyrovnávací paměti musí blok načíst a operace se dokončí stejným způsobem.

Po provedení datové operace se posune ukazovátko za čtené, resp. zapisované slabiky. Pohyb ukazovátka lze vyžádat rovněž voláním lseek jádra. Neprovádí se žádná disková operace, pouze se změní složka offsetv systémové tabulce otevřených souborů.