12. SYSTEM PLIKÓW SYSTEMU OPERACYJNEGO UNIX
Logiczny obraz systemu plików z punktu widzenia użytkownika Uniksa jest
jednym grafem
acyklicznym o korzeniu oznaczonym znakiem / . Ten logiczny obraz nie jest
zależny od
umiejscowienia plików na konkretnych urządzeniach fizycznych - dyskach
twardych (ich partycjach),
dyskietkach itp., a nawet na urządzeniach innych komputerów w sieci -
administrator systemu dokonuje
montowania
(mount)
poszczególnych fizycznych systemów plików w jednym
dużym grafie, wspólnym
dla wszystkich użytkowników systemu, który może być widziany jako sieciowy
system plików.
Oznacza to, że interfejs użytkownika nie pozwala mu na stwierdzenie, gdzie (na
którym komputerze
w sieci, na którym jego urządzeniu) przechowywane są jego pliki. Oznacza to
również, że zwykły
użytkownik nie ma uprawnień do posługiwania się dyskietkami i płytkami CD w
systemach uniksowych
i w razie potrzeby musi zwrócić się z taką sprawą do administratora. Typowym
sposobem ominięcia
tego problemu jest przesyłanie plików pomiędzy indywidualnym komputerem
użytkownika a jego
serwerem uniksowym przy użyciu protokołu ftp lub innego równoważnego.
W systemie plików przechowywane są zarówno pliki zawierające dane i
oprogramowanie systemowe,
jak i pliki należące do poszczególnych użytkowników. Katalogi najwyższego
poziomu mają zwykle
standardowe nazwy - poniżej naszkicowany jest fragment typowego grafu:
/
bin dev etc home lib
tmp ..................
bash cat .... tty1 .... passwd .... anna jan ..... libcurses libXt ......
...............
Katalogi domowe poszczególnych użytkowników są umieszczane w katalogu
home (czasem user).
W pozostałych katalogach umieszczone są pliki systemowe, na przykład w bin
programy binarne
(skompilowane), w dev pliki specjalne urządzeń
(device)
, w lib biblioteki funkcji
(library)
itd.
W różnych systemach uniksowych ogólne struktury grafów katalogów są
podobne, ale w szczegółach
mogą się różnić.
Zgodnie z przyjętą filozofią systemu Unix, poza zwykłymi plikami w grafie
katalogów są też
umieszczone pliki specjalne będące logicznymi obrazami urządzeń
zewnętrznych (na przykład
terminali), środków komunikacji międzyprocesowej (kanałów komunikacyjnych) i
innych obiektów.
W interfejsie użytkownika (na przykład w poleceniu ls -l ) wyróżnione są
następujące rodzaje plików
(i przyporządkowane tym rodzajom symbole):
- oznacza plik zwykły
(ordinary file)
d oznacza katalog
(directory)
l oznacza dowiązanie symboliczne (miękkie)
(symbolic link)
c oznacza urządzenie znakowe
(character device)
b oznacza urządzenie blokowe
(block device)
n oznacza urządzenie sieciowe
(network device)
s oznacza gniazdo
(socket)
p oznacza łącze nazwane
(named pipe)
Poza rodzajem plik uniksowy posiada wiele innych atrybutów, które są
uwidocznione w interfejsie
użytkownika. Ważnymi atrybutami są prawa dostępu wyświetlane przez polecenie
ls -l
w następującym formacie:
* * * * * * * * * *
u g o
rodzaj pliku u - prawa właściciela
(user)
(według podanych oznaczeń) g - prawa grupy
(group)
o - prawa innych
użytkowników
(other)
Każdy plik ma swojego właściciela (użytkownika, którego proces utworzył dany
plik). Użytkownik
może należeć do jednej lub więcej grup użytkowników (z których jedna jest
wyróżniona dla każdego
użytkownika jako jego grupa główna). Grupy są z kolei podzbiorami wszystkich
użytkowników
danego systemu uniksowego.
Uwaga
Prawa właściciela, prawa jego grupy i prawa innych użytkowników stanowią
oddzielne, niezależnie
ustalane zbiory atrybutów (na przykład właściciel może odebrać sobie prawa, ale
pozostawić je grupie).
W powyższym 10-znakowym zestawieniu pierwszy znak określa rodzaj pliku,
natomiast ciąg
pozostałych znaków jest traktowany jako trzy trójki, odpowiednio określające
prawa dostępu dla
właściciela pliku, jego grupy i pozostałych użytkowników. W każdej trójce na
każdej pozycji może
wystąpić litera (prawa nadane) lub znak - (prawa odebrane).
Na pierwszej pozycji:
r prawo do czytania
(read)
Na drugiej pozycji:
w prawo do pisania
(write)
Na trzeciej pozycji:
x prawo do wykonywania
(execute)
s
S interpretacja zależna
t od położenia w ciągu
T
Ostatni rodzaj praw związany jest z uruchamianiem procesów na podstawie pliku
wykonywalnego.
Proces może posiadać prawa użytkownika, który go uruchomił, lub właściciela
pliku wykonywalnego
(nie musi to być ten sam użytkownik). Podobnie może posiadać prawa grupy
użytkownika, który go
uruchomił, lub grupy właściciela pliku (mieć nadany identyfikator grupy
właściciela).
Uwaga
Nie wszystkie rodzaje praw odnoszą się do wszystkich rodzajów plików, ponadto w
przypadku
niektórych rodzajów mają odmienną interpretację. W szczególności w przypadku
katalogów:
- prawo do czytania oznacza prawo do przeglądania zawartości katalogu (np.
wyświetlenia jej na
ekranie terminala);
- prawo do pisania oznacza prawo do zmiany zawartości katalogu (tworzenia i
usuwania w nim plików
i podkatalogów);
- prawo do wykonywania oznacza prawo do przeszukiwania („wejścia” do danego
katalogu).
W przypadku programu, który jest przeznaczony do częstego wykonywania, jego
tekst (zawartość pliku)
może być pozostawiony w pamięci operacyjnej, aby zaoszczędzić czasu na
ponownym ładowaniu
programu z pliku. Atrybut pliku, który to ustala, nazywany jest bitem lepkości
(sticky bit)
.
Zestawienie interpretacji atrybutów x, s, S, t, T w zależności od położenia w
ciągu:
* * x * * * * * * prawo właściciela do wykonywania (brak ustanowienia ID
właściciela dla
grupy i dla innych)
* * s * * * * * * prawo właściciela do wykonywania (ustanowienie ID właściciela
dla grupy i dla
innych)
* * S * * * * * * brak prawa właściciela do wykonywania (ustanowienie ID
właściciela dla grupy
i dla innych)
* * * * * x * * * prawo grupy do wykonywania (brak ustanowienia ID grupy dla
innych)
* * * * * s * * * prawo grupy do wykonywania (ustanowienie ID grupy dla
innych)
* * * * * S * * * brak prawa grupy do wykonywania (ustanowienie ID grupy dla
innych)
* * * * * * * * x prawo do wykonywania dla innych (bez ustawienia bitu lepkości)
* * * * * * * * t prawo do wykonywania dla innych (i ustawienie bitu lepkości)
* * * * * * * * T brak prawa do wykonywania dla innych (i ustawienie bitu
lepkości)
Szczególną postacią grafu acyklicznego jest drzewo. W drzewie każdy katalog
(poza korzeniem)
ma dokładnie jeden nadkatalog i każdy plik należy do dokładnie jednego katalogu.
Ogólnie, w grafie
acyklicznym nie musi to zachodzić - można tworzyć dodatkowe dowiązania
zarówno plików, jak
i katalogów do katalogów innych, niż te, w których już są. W interfejsie
użytkownika służy do tego
polecenie ln .
Uwaga
Zwykły użytkownik systemu ma jedynie prawo tworzenia dowiązań do plików.
Prawo tworzenia
dowiązań do katalogów ma jedynie administrator systemu, ze względu na
niebezpieczeństwo
zapętlenia w ten sposób grafu katalogów (co może wiązać się z nieodwracalnym
uszkodzeniem
systemu plików).
Jeśli plik (lub katalog) jest dowiązany w kilku miejscach, to jego usunięcie w
jednym miejscu nie
powoduje jego fizycznego skasowania, a jedynie usunięcie dowiązania do tego
miejsca. Dopiero
usunięcie ostatniego istniejącego dowiązania powoduje fizyczne usunięcie z
systemu plików.
Wyżej omówione dowiązania noszą nazwę dowiązań twardych
(hard link)
. Ich
tworzenie i usuwanie
wiąże się bezpośrednio ze zmianą informacji zapisanej w systemie na temat
danego pliku. Użytkownik
ma prawo tworzenia również dowiązań symbolicznych
(symbolic link)
. W
interfejsie użytkownika są
one uwidocznione w podobny sposób, jak dowiązania twarde, ale w
rzeczywistości są jedynie małymi
plikami zawierającymi informację na temat usytuowania pliku, do którego zostało
stworzone takie
dowiązanie.
Z punktu widzenia użytkownika najbardziej istotną różnicą pomiędzy
dowiązaniami twardymi
a miękkimi (symbolicznymi) jest to, że dowiązanie twarde może być utworzone
tylko do istniejącego
pliku lub katalogu (system musi sprawdzić jego istnienie, modyfikując zapis w
odpowiedniej
strukturze systemowej), zaś dowiązanie miękkie jest tylko plikiem z zapisaną
informacją „na życzenie
użytkownika”, nie weryfikowaną przez system operacyjny. Odpowiednio,
usunięcie wszystkich
twardych dowiązań do danego pliku spowoduje jego fizyczne skasowanie, bez
względu na to, czy
gdzieś istnieją jakieś dowiązania symboliczne do tego pliku.
Łącza nazwane (kolejki FIFO) są specjalnym rodzajem plików przeznaczonych do
umożliwiania
komunikacji międzyprocesowej. Mogą one być traktowane jako „pliki z nietrwałą
zawartością”
w tym sensie, że każdy odczyt porcji informacji z łącza przez pewien proces
jednocześnie usuwa tę
informację z łącza. Pojedyncze łącze umożliwia komunikację jednokierunkową -
jeżeli chcemy
ustanowić komunikację dwukierunkową pomiędzy dwoma procesami, musimy
użyć do tego pary łącz.
Łącza wymuszają synchronizację dwóch komunikujących się procesów - proces,
który otworzył łącze
do zapisu, zostaje zawieszony aż do otwarcia łącza przez inny proces do odczytu
(i na odwrót).
Podobnie proces, który wywołał funkcję zapisu do łącza, zostaje zawieszony aż do
wywołania przez
drugi proces funkcji odczytu z łącza (i na odwrót).
Łącza nazwane są uwidocznione dla użytkownika w systemie plików jako pliki
specjalne
o wielkości 0. Do ich utworzenia służy polecenie systemowe mkfifo. Poza łączami
nazwanymi Unix
dysponuje również łączami nienazwanymi (bezimiennymi), które nie są
uwidocznione dla
użytkownika. Są to tymczasowe pliki nietrwałe (a właściwie ich bufory), które są
tworzone w katalogu
bieżącym na czas przekazywania strumienia danych z jednego procesu do
drugiego wskutek użycia
operatora | .
Gniazda
(socket)
są alternatywnym medium komunikacji międzyprocesowej,
charakterystycznym dla
Uniksów BSD. Zostały zaprojektowane jako obiekty interfejsu do protokołów
komunikacyjnych
(w szczególności do protokołu internetowego IP). Mogą służyć zarówno do
komunikacji wewnętrznej
(między procesami w tym samym systemie uniksowym), jak i do komunikacji
pomiędzy procesami
na różnych komputerach.
W katalogu /dev umieszczone są pliki specjalne będące logicznymi obrazami
urządzeń fizycznych -
terminali użytkowników, urządzeń dyskowych, drukarek i innych. Sposób ich
obsługi zależy od
konkretnych programów obsługi (sterowników) tych urządzeń. Tekstowe terminale
użytkowników
traktowane są jako pliki tekstowe, do których (jeśli prawa dostępu na to pozwalają)
można bezpośrednio
pisać, i z których można bezpośrednio czytać. Związana z tym jest możliwość
przesyłania sobie
wzajemnie komunikatów przez użytkowników systemu uniksowego, jak również
możliwość
„bronienia się” przed otrzymywaniem niepożądanych komunikatów.
Uwaga
Administrator systemu zawsze ma możliwość przesłania komunikatu dowolnym
użytkownikom.
Wewnętrzna organizacja systemu plików
Z każdym plikiem w systemie skojarzona jest systemowa struktura danych
zawierająca informacje na
temat tego pliku, nazywana jego węzłem indeksowym
(index node)
lub, krótko
i-węzłem
(i-node)
.
I-węzeł zawiera następujące informacje:
- identyfikator właściciela pliku;
- typ pliku;
- prawa dostępu;
- czasy: ostatniego dostępu, ostatniej modyfikacji pliku i ostatniej modyfikacji i-
węzła;
- liczba twardych dowiązań;
- tablica adresów bloków dyskowych, w których zapisana jest zawartość pliku;
- rozmiar pliku.
Tablica wszystkich i-węzłów zapisana jest na dysku, a jej kopia - w pamięci
operacyjnej. Kopie
i-węzłów zawierają dodatkowo informacje o założeniu blokady na plik przez
pewien pewien proces,
o modyfikacji i-węzła od czasu skopiowania do pamięci i o tym, czy plik jest
punktem montowania.
Jeśli jakikolwiek proces chce czytać dane z pliku lub zapisywać do niego dane,
musi najpierw ten plik
otworzyć, a po wykonaniu na nim operacji zamknąć go. W systemie
przechowywane są w związku
z tym następujące struktury danych:
- struktura globalna jądra systemu nazywana tablicą plików, w której każda
pozycja odpowiada
jednemu otwarciu pliku (zatem w przypadku, gdy dwa różne procesy otworzą ten
sam plik, w tablicy
będą zapisane dwie pozycje);
- dla każdego procesu w jego indywidualnej strukturze danych przechowywana jest
jego tablica
deskryptorów plików, która zawiera indeksy (numery pozycji) w globalnej
tablicy plików związane
z otwarciami plików dokonanymi przez ten proces.
Tablice deskryptorów Tablica plików
Tablica i-węzłów
plików (po jednej na proces) (globalna)
(globalna)
Uwaga
Z powyższego sposobu zapisu informacji o plikach otwartych wynika, że w każdej
chwili zarówno
liczba plików otwartych przez pojedynczy proces, jak i łączna liczba wszystkich
plików otwartych
w systemie jest ograniczona. Maksymalne wielkości tych liczb są ustalane przez
administratora
w czasie konfiguracji systemu operacyjnego.
Każdy proces w momencie swojego uruchomienia ma automatycznie otwarte trzy
deskryptory plików:
0 - standardowe wejście
(standard input)
;
1 - standardowe wyjście
(standard output)
;
2 - standardowe wyjście błędów
(standard error output)
.
Przez domniemanie te trzy deskryptory są związane z terminalem właściciela
procesu (może to być
zmienione przez przekierowania) i służą odpowiednio do czytania danych,
wyświetlania wyników
i wyświetlania komunikatów o błędach. Użytkownicy mogą rozdzielić mieszające
się na ekranie
terminala strumienie wyjściowe: wyników i błędów, poprzez przekierowanie ich do
dwóch różnych
plików.
Jedną z najważniejszych informacji zapisanych w każdej pozycji tablicy plików
jest aktualne
położenie wskaźnika pliku. Ponieważ różne pozycje w tablicy plików mogą
wskazywać na ten sam
i-węzeł, a ponadto w tablicach deskryptorów procesów mogą występować
jednakowe deskryptory,
stwarza to bogactwo możliwości współpracy wielu procesów za pośrednictwem
współdzielonych
plików. Jest możliwe zarówno niezależne przemieszczanie swoich wskaźników po
jednym pliku przez
dwa procesy (w typowym zastosowaniu jeden z nich zapisuje dane, a drugi
asynchronicznie te dane
odczytuje), jak też korzystanie (zwykle przez grupę spokrewnionych procesów) ze
wspólnego
deskryptora, co umożliwia im na przykład naprzemienne zapisywanie danych do
wspólnego pliku.
W systemach uniksowych procesy potomne dziedziczą po swoich procesach
rodzicielskich między
innymi wszystkie deskryptory otwartych plików. Oznacza to, że strumienie
wejściowe i wyjściowe
tych procesów będą mieszały się (jest zatem możliwe zjawisko wzajemnego
„podkradania sobie”
danych przez proces rodzicielski i potomny) i programista powinien zadbać, aby
w jego programach
nie występowały zjawiska hazardu (niedeterminizmu).