To jest naprawdę dość proste, przynajmniej jeśli nie potrzebujesz szczegółów implementacji.
Po pierwsze, w systemie Linux wszystkie systemy plików (ext2, ext3, btrfs, reiserfs, tmpfs, zfs, ...) są zaimplementowane w jądrze. Niektórzy mogą odciążyć pracę do kodu użytkownika przez FUSE, a niektórzy przychodzą tylko w formie modułu jądra ( natywny ZFS jest godnym uwagi przykładem tego ostatniego z powodu ograniczeń licencyjnych), ale tak czy inaczej pozostaje komponent jądra. To ważna podstawa.
Gdy program chce czytać z pliku, wyda różne połączenia bibliotecznych system, który ostatecznie kończy się w jądrze w postaci emulsji open()
, read()
, close()
sekwencja (ewentualnie z seek()
rzucony w środek na dobre). Jądro pobiera podaną ścieżkę i nazwę pliku, a poprzez system plików i warstwę we / wy urządzenia przekłada je na żądania odczytu fizycznego (w wielu przypadkach także żądania zapisu - pomyśl na przykład aktualizacje atime) do niektórych bazowych pamięci.
Jednak nie musi tłumaczyć tych żądań konkretnie na fizyczne, trwałe przechowywanie . Umowa jądra polega na tym, że wydanie tego konkretnego zestawu wywołań systemowych zapewni zawartość danego pliku . Gdzie dokładnie w naszym fizycznym królestwie istnieje „plik”, ma on drugorzędne znaczenie.
Na /proc
zwykle montowane jest tak zwane procfs
. Jest to specjalny typ systemu plików, ale ponieważ jest to system plików, tak naprawdę nie różni się od np. ext3
Zamontowanego gdzieś systemu plików. Tak więc żądanie jest przekazywane do kodu sterownika systemu plików procfs, który zna wszystkie te pliki i katalogi i zwraca określone informacje ze struktur danych jądra .
„Warstwa pamięci” w tym przypadku to struktury danych jądra i procfs
zapewnia czysty, wygodny interfejs dostępu do nich. Pamiętaj, że montowanie procfs w /proc
to po prostu konwencja; równie łatwo możesz zamontować go gdzie indziej. W rzeczywistości czasami tak się dzieje, na przykład w więzieniach chroot, gdy działający tam proces z jakiegoś powodu potrzebuje dostępu do / proc.
Działa tak samo, jeśli zapisujesz wartość do jakiegoś pliku; na poziomie jądra, które przekłada się na serię open()
, seek()
, write()
, close()
zaproszeń, które ponownie przejdzie do sterownika systemu plików; ponownie, w tym konkretnym przypadku, kod procfs.
Szczególnym powodem file
powrotu empty
jest to, że wiele plików ujawnionych przez procfs ma rozmiar 0 bajtów. Rozmiar 0 bajtów jest prawdopodobnie optymalizacją po stronie jądra (wiele plików w / proc jest dynamicznych i może łatwo różnić się długością, być może nawet od jednego odczytu do następnego, a obliczenie długości każdego pliku w każdym czytanym katalogu potencjalnie być bardzo drogie). Przechodząc od komentarzy do tej odpowiedzi, które można zweryfikować we własnym systemie, uruchamiając strace lub podobne narzędzie, file
najpierw wydaje stat()
wywołanie w celu wykrycia specjalnych plików, a następnie korzysta z okazji, jeśli rozmiar pliku jest zgłaszany jako 0 , przerwij i zgłoś plik jako pusty.
Takie zachowanie jest właściwie udokumentowane i mogą być zastąpione przez podanie -s
lub --special-files
na file
pw, choć jak wynika z ręcznym strony, które mogą mieć skutki uboczne. Cytat poniżej pochodzi ze strony podręcznika użytkownika BSD 5.11 z dnia 17 października 2011 r.
Zwykle plik próbuje jedynie odczytać i określić typ plików argumentów, które raporty stat (2) są zwykłymi plikami. Zapobiega to problemom, ponieważ odczytywanie plików specjalnych może mieć szczególne konsekwencje. Podanie -s
opcji powoduje, że plik odczytuje również pliki argumentów, które są plikami specjalnymi blokowymi lub znakowymi. Jest to przydatne do określania typów systemów plików danych na surowych partycjach dysku, które są blokowymi plikami specjalnymi. Ta opcja powoduje również, że plik ignoruje rozmiar pliku zgłoszony przez stat (2), ponieważ w niektórych systemach zgłasza zerowy rozmiar partycji dysku surowego.
strace file /proc/version
lubltrace -S /proc/version
, optymalizacja jest raczej niewielka.stat()
Najpierw wykonuje wywołanie i stwierdza, że rozmiar wynosi 0, pomijając w ten sposóbopen()
- ale wcześniej ładuje kilka magicznych plików.