Mogę cat /dev
, mogę ls /dev
, nie mogę less /dev
. Dlaczego cat
pozwala mi cat
ten katalog, ale nie ma innych katalogów?
Mogę cat /dev
, mogę ls /dev
, nie mogę less /dev
. Dlaczego cat
pozwala mi cat
ten katalog, ale nie ma innych katalogów?
Odpowiedzi:
Historycznie (do V7 UNIX lub około 1979 r.) read
Wywołanie systemowe działało zarówno na plikach, jak i katalogach. read
w katalogu zwróci prostą strukturę danych, którą program użytkownika przeanalizuje w celu uzyskania pozycji katalogu. Rzeczywiście, ls
narzędzie V7 właśnie to zrobiło - read
w katalogu parsuje wynikową strukturę danych, wyprowadza w uporządkowanym formacie listy.
Ponieważ systemy plików stały się bardziej złożone, ta „prosta” struktura danych stała się bardziej skomplikowana, do tego stopnia, że dodano readdir
funkcję biblioteki, aby pomóc programom w analizie danych wyjściowych read(directory)
. Różne systemy i systemy plików mogą mieć różne formaty na dysku, co się komplikuje.
Kiedy Sun wprowadził system plików NFS, chciał całkowicie wyodrębnić strukturę katalogów na dysku. Zamiast jednak read(directory)
zwracać niezależną od platformy reprezentację katalogu, dodali nowe wywołanie systemowe getdirents
- i zbanowali read
w katalogach podłączonych do sieci. To wywołanie systemowe zostało szybko przystosowane do pracy we wszystkich katalogach w różnych wersjach UNIX, dzięki czemu jest to domyślny sposób uzyskiwania zawartości katalogów. (Historia pobrana z https://utcc.utoronto.ca/~cks/space/blog/unix/ReaddirHistory )
Ponieważ readdir
jest to teraz domyślny sposób odczytywania katalogów, read(directory)
zwykle nie jest implementowany (zwraca -EISDIR) w większości nowoczesnych systemów operacyjnych (na przykład QNX jest godnym uwagi wyjątkiem, który implementuje readdir
jako read(directory)
). Jednak dzięki projektowi „wirtualnego systemu plików” w większości współczesnych jąder, to od systemu plików zależy, czy czytanie katalogu działa, czy nie.
I rzeczywiście, w systemie macOS, devfs
system plików leżący u podstaw /dev
mountpoint naprawdę obsługuje czytanie ( https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/bsd/miscfs/devfs/devfs_vnops.c#L629 ) :
static int
devfs_read(struct vnop_read_args *ap)
{
devnode_t * dn_p = VTODN(ap->a_vp);
switch (ap->a_vp->v_type) {
case VDIR: {
dn_p->dn_access = 1;
return VNOP_READDIR(ap->a_vp, ap->a_uio, 0, NULL, NULL, ap->a_context);
Wywołuje to jawnie, READDIR
jeśli próbujesz czytać /dev
(odczytywanie plików /dev
jest obsługiwane przez osobną funkcję - devfsspec_read
). Tak więc, jeśli program wywoła read
wywołanie systemowe /dev
, powiedzie się i uzyska listę katalogów!
Jest to w rzeczywistości funkcja, która jest zapamiętywaniem od bardzo wczesnych dni UNIX-a i nie była dotykana od bardzo dawna. Część mnie podejrzewa, że jest to utrzymywane z jakiegoś powodu wstecznej kompatybilności, ale równie dobrze może to być fakt, że nikomu nie zależy na usunięciu tej funkcji, ponieważ tak naprawdę nic nie rani.
Less to przeglądarka plików tekstowych, cat to narzędzie do kopiowania dowolnych danych. Więc mniej wykonuje własne sprawdzanie, aby upewnić się, że nie otwierasz czegoś, co będzie zawierało ogromne ilości danych lub zachowa się bardzo dziwnie. Z drugiej strony, kot w ogóle nie ma takiego sprawdzania - jeśli jądro pozwala ci coś otworzyć (nawet jeśli jest to potok, urządzenie lub coś gorszego), kot to przeczyta.
Dlaczego system operacyjny pozwala cat otwierać katalogi? Tradycyjnie w systemach typu BSD wszystkie katalogi mogły być odczytywane jako pliki, i w ten sposób programy umieszczałyby katalog na pierwszym miejscu: po prostu interpretując bezpośrednie struktury przechowywane na dysku.
Później te struktury na dysku zaczęły odbiegać od direntu używanego przez jądro: gdzie wcześniej katalog był listą liniową, później systemy plików zaczęły używać tabel hashtable, B-drzewek i tak dalej. Czytanie katalogów bezpośrednio nie było już tak proste - jądro ma do tego dedykowane funkcje. (Nie jestem pewien, czy to był główny powód, czy też zostały dodane głównie z innych powodów, takich jak buforowanie).
Niektóre systemy BSD pozwalają nadal otwierać wszystkie katalogi do czytania; Nie wiem, czy dają ci surowe dane z dysku, czy zamiast tego zwracają emulowaną listę bezpośrednio, czy też decydują sterownik systemu plików.
Być może macOS jest jednym z tych systemów operacyjnych, w których jądro na to pozwala, o ile system plików dostarcza dane. Różnica polega /dev
na tym, devfs
że system plików został napisany, aby umożliwić to na początku, podczas gdy /
system plików APFS pomija tę funkcję jako niepotrzebną we współczesnych czasach.
Oświadczenie: Właściwie nie przeprowadziłem żadnych badań dotyczących BSD ani macOS. Po prostu to latam.
/etc
że tak, więc wykorzystałem to jako mój punkt odniesienia.
mount
lub /sbin/mount
zobaczyć, co się aktualnie zamontowany gdzie.
/dev
jest to wirtualny system plików korzystający ze devfs
sterownika, podczas gdy /etc
jest on częścią /
systemu plików używającego apfs
sterownika. Powodem, dla którego cat
czytać będzie jeden, a nie drugi, jest różnica między sterownikami apfs
a devfs
.
neofetch
dla twojej informacji :) i.imgur.com/3azpnDt.png