Bardzo często początkujący słyszą zwrot „Wszystko w systemie Linux / Unix”. Jakie są zatem katalogi? Czym różnią się od plików?
Bardzo często początkujący słyszą zwrot „Wszystko w systemie Linux / Unix”. Jakie są zatem katalogi? Czym różnią się od plików?
Odpowiedzi:
Uwaga: pierwotnie zostało to napisane na poparcie mojej odpowiedzi na pytanie: Dlaczego bieżący katalog w ls
poleceniu jest zidentyfikowany jako powiązany z samym sobą? ale czułem, że jest to temat, który zasługuje na samodzielne podejście, i stąd te pytania i odpowiedzi .
Zasadniczo katalog to tylko specjalny plik, który zawiera listę wpisów i ich identyfikatory.
Przed rozpoczęciem dyskusji ważne jest, aby wprowadzić rozróżnienie między kilkoma terminami i zrozumieć, co tak naprawdę reprezentują katalogi i pliki. Być może słyszałeś wyrażenie „Wszystko jest plikiem” dla Unix / Linux. Cóż, użytkownicy często rozumieją jako plik: /etc/passwd
- Obiekt ze ścieżką i nazwą. W rzeczywistości nazwa (czy to katalog, plik, czy cokolwiek innego) to tylko ciąg tekstowy - właściwość rzeczywistego obiektu. Ten obiekt nazywa się i- węzłem lub numerem I i jest przechowywany na dysku w tabeli i-węzłów. Otwarte programy również mają tabele i-węzłów, ale na razie nie jest to naszym celem.
Uniksowe pojęcie katalogu jest takie, jak ujął to Ken Thompson w wywiadzie z 1989 roku :
... A potem niektóre z tych plików były katalogami, które właśnie zawierały nazwę i numer I.
Interesująca obserwacja może być wykonana z talk Dennisa Ritchiego w 1972 roku , że
„... katalog jest w rzeczywistości niczym więcej niż plikiem, ale jego zawartość jest kontrolowana przez system, a zawartość to nazwy innych plików. (W innych systemach katalog jest czasem nazywany katalogiem).”
... ale w rozmowie nie ma wzmianki o i-węzłach. Jednak instrukcja 1971 o format of directories
stanach:
O tym, że plik jest katalogiem, wskazuje nieco słowo flagowe wpisu i-węzła.
Wpisy w katalogu mają długość 10 bajtów. Pierwsze słowo to i-węzeł pliku reprezentowany przez wpis, jeśli niezerowy; jeśli zero, wpis jest pusty.
Tak było od początku.
Parowanie katalogów i i-węzłów wyjaśniono również w rozdziale Jak przechowywane są struktury katalogów w systemie plików UNIX? . sam katalog jest strukturą danych, a dokładniej: listą obiektów (plików i numerów i-węzłów) wskazujących na listy o tych obiektach (uprawnienia, typ, właściciel, rozmiar itp.). Tak więc każdy katalog zawiera swój własny numer i-węzła, a następnie nazwy plików i ich numery i-węzłów. Najbardziej znana jest i- węzeł nr 2, który jest /
katalogiem . (Uwaga, chociaż /dev
i /run
to wirtualne systemy plików, ponieważ są one tak korzeń ich foldery plików, mają też 2-węzeł; tzn. i-węzeł jest unikalny w swoim własnym systemie plików, ale z dołączonymi wieloma systemami plików masz nie-unikalne i-węzły). schemat zapożyczony z połączonego pytania prawdopodobnie wyjaśnia go bardziej zwięźle:
Wszystkie te informacje przechowywane w i-węźle są dostępne za pośrednictwem stat()
wywołań systemowych, zgodnie z Linuksem man 7 inode
:
Każdy plik ma i-węzeł zawierający metadane dotyczące pliku. Aplikacja może odzyskać te metadane przy użyciu stat (2) (lub powiązanych wywołań), które zwraca strukturę stat, lub statx (2), która zwraca strukturę statx.
Czy to możliwe, aby uzyskać dostęp do pliku tylko znając jego numer i-węzła ( REF1 , REF2 )? W niektórych implementacjach Uniksa jest to możliwe, ale omija sprawdzanie uprawnień i dostępu, więc w Linuksie nie jest zaimplementowane i musisz przejść przez drzewo systemu plików ( find <DIR> -inum 1234
na przykład), aby uzyskać nazwę pliku i odpowiadający mu i-węzeł.
Na poziomie kodu źródłowego jest on zdefiniowany w źródle jądra Linux i jest również adoptowany przez wiele systemów plików, które działają w systemach operacyjnych Unix / Linux, w tym systemy plików ext3 i ext4 (domyślnie Ubuntu). Ciekawe: ponieważ dane są tylko blokami informacji, Linux faktycznie ma funkcję inode_init_always, która może określić, czy i-węzeł jest potokiem ( inode->i_pipe
). Tak, gniazda i potoki są technicznie także plikami - plikami anonimowymi, które mogą nie mieć nazwy pliku na dysku. FIFO i gniazda domeny Unix mają nazwy plików w systemie plików.
Same dane mogą być unikalne, ale numery i-węzłów nie są unikalne. Jeśli mamy twardy link do foo o nazwie foobar, będzie to wskazywać również na i-węzeł 123. Sam ten i-węzeł zawiera informacje o tym, jakie rzeczywiste bloki miejsca na dysku są zajęte przez ten i-węzeł. I technicznie jest to sposób na .
połączenie z nazwą pliku katalogu. Cóż, prawie: nie można samodzielnie tworzyć twardych dowiązań do katalogów w systemie Linux , ale systemy plików mogą zezwalać na dowiązania twarde do katalogów w bardzo zdyscyplinowany sposób, co stanowi ograniczenie posiadania tylko .
i ..
jako twardych dowiązań.
Systemy plików implementują drzewo katalogów jako jedną z drzewiastych struktur danych. W szczególności,
Kluczową kwestią jest to, że same katalogi są węzłami w drzewie, a podkatalogi są węzłami potomnymi, przy czym każde dziecko ma łącze z powrotem do węzła nadrzędnego. Zatem dla łącza do katalogu liczba i-węzłów wynosi co najmniej 2 dla /home/example/
samego katalogu (link do nazwy katalogu i link do siebie /home/example/.
), a każdy dodatkowy podkatalog jest dodatkowym łączem / węzłem:
# new directory has link count of 2
$ stat --format=%h .
2
# Adding subdirectories increases link count
$ mkdir subdir1
$ stat --format=%h .
3
$ mkdir subdir2
$ stat --format=%h .
4
# Count of links for root
$ stat --format=%h /
25
# Count of subdirectories, minus .
$ find / -maxdepth 1 -type d | wc -l
24
Schemat znajdujący się na stronie kursu Iana D. Allena pokazuje uproszczony bardzo jasny schemat:
WRONG - names on things RIGHT - names above things
======================= ==========================
R O O T ---> [etc,bin,home] <-- ROOT directory
/ | \ / | \
etc bin home ---> [passwd] [ls,rm] [abcd0001]
| / \ \ | / \ |
| ls rm abcd0001 ---> | <data> <data> [.bashrc]
| | | |
passwd .bashrc ---> <data> <data>
Jedyne, co na diagramie PRAWY jest niepoprawne, to fakt, że technicznie nie uważa się, że pliki znajdują się w samym drzewie katalogów: dodanie pliku nie ma wpływu na liczbę łączy:
$ mkdir subdir2
$ stat --format=%h .
4
# Adding files doesn't make difference
$ cp /etc/passwd passwd.copy
$ stat --format=%h .
4
Cytując Linusa Torvaldsa :
Chodzi o to, że „wszystko jest plikiem” nie polega na tym, że masz jakąś losową nazwę pliku (w rzeczywistości gniazda i potoki pokazują, że „plik” i „nazwa pliku” nie mają ze sobą nic wspólnego), ale fakt, że możesz używać wspólnego narzędzia do obsługi różnych rzeczy.
Biorąc pod uwagę, że katalog jest tylko specjalnym przypadkiem pliku, oczywiście muszą istnieć interfejsy API, które pozwalają nam otwierać / odczytywać / zapisywać / zamykać je w podobny sposób jak zwykłe pliki.
Tam właśnie dirent.h
pojawia się biblioteka C, która określa dirent
strukturę, którą można znaleźć w readdir man 3 :
struct dirent {
ino_t d_ino; /* Inode number */
off_t d_off; /* Not an offset; see below */
unsigned short d_reclen; /* Length of this record */
unsigned char d_type; /* Type of file; not supported
by all filesystem types */
char d_name[256]; /* Null-terminated filename */
};
Dlatego w kodzie C musisz zdefiniować struct dirent *entry_p
, a kiedy otworzymy katalog opendir()
i zaczniemy go czytać readdir()
, będziemy przechowywać każdy element w tej entry_p
strukturze. Oczywiście każdy element będzie zawierał pola zdefiniowane w szablonie dla dirent
pokazanego powyżej.
Praktyczny przykład tego, jak to działa, można znaleźć w mojej odpowiedzi na temat wyświetlania plików i ich numerów i-węzłów w bieżącym katalogu roboczym .
Zauważ, że instrukcja POSIX na fdopen stwierdza, że „wpisy katalogu dla kropki i kropki są opcjonalne”, a stany instrukcji readdir struct dirent
są wymagane tylko d_name
i d_ino
pola.
Uwaga na temat „zapisywania” do katalogów: zapisywanie do katalogu modyfikuje jego „listę” wpisów. Dlatego tworzenie lub usuwanie pliku jest bezpośrednio związane z uprawnieniami do zapisu w katalogu , a dodawanie / usuwanie plików jest operacją zapisu w tym katalogu.
open()
i read()
gniazda mają connect()
i read()
też. Bardziej dokładne byłoby to, że „plik” to tak naprawdę zorganizowane „dane” przechowywane na dysku lub w pamięci, a niektóre pliki są anonimowe - nie mają nazwy pliku. Zwykle użytkownicy myślą o plikach w kategoriach tej ikony na pulpicie, ale to nie jedyna rzecz, która istnieje. Zobacz także unix.stackexchange.com/a/116616/85039