GNU/Linux >> Znalost Linux >  >> Linux

Jak Unix sleduje pracovní adresář uživatele při navigaci v systému souborů?

Řekněme, že se přihlásím do shellu na unixovém systému a začnu odklepávat příkazy. Nejprve začínám v domovském adresáři mého uživatele ~ . Mohl bych odtud cd dolů do adresáře Documents .

Příkaz ke změně pracovního adresáře je intuitivně velmi jednoduchý na pochopení:nadřazený uzel má seznam podřízených uzlů, ke kterým má přístup, a pravděpodobně používá (optimalizovanou) variantu vyhledávání k nalezení existence podřízeného uzlu s jméno zadaného uživatele a pracovní adresář se pak „změní“ tak, aby tomu odpovídal – opravte mě, pokud se tam mýlím. Dokonce může být jednodušší, že se shell jednoduše „naivně“ pokusí o přístup k adresáři přesně podle přání uživatele, a když souborový systém vrátí nějaký typ chyby, shell zobrazí odpovídající odpověď.

Co mě však zajímá, je, jak stejný proces funguje, když přejdu do adresáře, tj. k rodiči nebo rodiči rodiče.

Vzhledem k mému neznámému, pravděpodobně „slepému“ umístění Documents , jeden z možných mnoha adresářů v celém stromu souborového systému s tímto názvem, jak Unix určí, kde bych měl být umístěn jako další? Odkazuje na pwd a prozkoumat to? Pokud ano, jak funguje pwd sledovat aktuální stav navigace?

Přijatá odpověď:

Dalšími odpověďmi jsou přílišná zjednodušení, z nichž každá představuje pouze části příběhu a v několika bodech jsou chybné.

Jsou dva způsoby, kterými je pracovní adresář sledován:

  • Pro každý proces v datové struktuře kernel-space, která tento proces představuje, jádro ukládá dva odkazy na vnode na vnody pracovního adresáře a kořenový adresář daného procesu. Předchozí odkaz je nastaven pomocí chdir() a fchdir() systémová volání, druhé pomocí chroot() . Lze je vidět nepřímo v /proc v operačních systémech Linux nebo prostřednictvím fstat příkaz na FreeBSD a podobně:

    % fstat -p $$|head -n 5
    USER     CMD          PID   FD MOUNT      INUM MODE         SZ|DV R/W
    JdeBP    zsh        92648 text /         24958 -r-xr-xr-x  702360  r
    JdeBP    zsh        92648 ctty /dev        148 crw--w----   pts/4 rw
    JdeBP    zsh        92648   wd /usr/home/JdeBP      4 drwxr-xr-x     124  r
    JdeBP    zsh        92648 root /             4 drwxr-xr-x      35  r
    % 

    Když funguje překlad názvů cest, začíná na jednom nebo druhém z těchto odkazovaných uzlů podle toho, zda je cesta relativní nebo absolutní. (Existuje rodina …at() systémová volání, která umožňují, aby překlad názvu cesty začínal v uzlu, na který odkazuje otevřený (adresář) deskriptor souboru jako třetí možnost.)

    V mikrokernelu Unices je datová struktura v aplikačním prostoru, ale princip udržování otevřených odkazů na tyto adresáře zůstává stejný.

  • Interně, v rámci shellů, jako je Z, Korn, Bourne Again, C a Almquist shell, shell dodatečně sleduje pracovní adresář pomocí manipulace s vnitřní řetězcovou proměnnou. Dělá to vždy, když má důvod k volání chdir() .

    Pokud se změníte na relativní název cesty, manipuluje s řetězcem tak, aby toto jméno připojil. Pokud se změní na absolutní název cesty, nahradí řetězec novým názvem. V obou případech upraví řetězec tak, aby odstranil . a .. komponenty a pronásledovat symbolické odkazy, které je nahrazují jejich souvisejícími názvy. (Zde je například kód Z shellu.)

    Název v interní řetězcové proměnné je sledován proměnnou shellu s názvem PWD (nebo cwd ve skořápkách C). To se běžně exportuje jako proměnná prostředí (pojmenovaná PWD ) na programy vytvořené shellem.

Tyto dva způsoby sledování věcí odhaluje -P a -L možnosti na cd a pwd vestavěné příkazy shellu a podle rozdílů mezi vestavěnými příkazy pwd v shellu příkazy a oba /bin/pwd a vestavěný pwd příkazy věcí jako (mimo jiné) VIM a NeoVIM.

% mkdir a ; ln -s a b
% (cd b; pwd; /bin/pwd; printenv PWD)
/usr/home/JdeBP/b
/usr/home/JdeBP/a
/usr/home/JdeBP/b
% (cd b; pwd -P; /bin/pwd -P)
/usr/home/JdeBP/a
/usr/home/JdeBP/a
% (cd b; pwd -L; /bin/pwd -L)
/usr/home/JdeBP/b
/usr/home/JdeBP/b
% (cd -P b; pwd; /bin/pwd; printenv PWD)
/usr/home/JdeBP/a
/usr/home/JdeBP/a
/usr/home/JdeBP/a
% (cd b; PWD=/hello/there /bin/pwd -L)
/usr/home/JdeBP/a
% 

Související:Hledáte alternativní editor souborů GUI s podporou velkých souborů?

Jak můžete vidět:získání „logického“ pracovního adresáře je věcí pohledu na PWD proměnná shellu (nebo proměnná prostředí, pokud jedna není programem shellu); zatímco získání „fyzického“ pracovního adresáře je záležitostí volání getcwd() funkce knihovny.

Operace /bin/pwd program, když -L použitá možnost je poněkud subtilní. Nemůže věřit hodnotu PWD proměnná prostředí, kterou zdědila. Koneckonců to nemuselo být vyvoláno shellem a zasahující programy nemusely implementovat mechanismus shellu pro vytváření PWD proměnná prostředí vždy sleduje název pracovního adresáře. Nebo někdo může udělat to, co jsem tam udělal já.

Takže to udělá (jak říká standard POSIX) zkontroluje, že jméno uvedené v PWD dává totéž co jméno . , jak je vidět na trasování systémového volání:

% ln -s a c
% (cd b;  truss /bin/pwd -L 3>&1 1>&2 2>&3 | grep -E '^stat|__getcwd')
stat("/usr/home/JdeBP/b",{ mode=drwxr-xr-x ,inode=120932,size=2,blksize=131072 }) = 0 (0x0)
stat(".",{ mode=drwxr-xr-x ,inode=120932,size=2,blksize=131072 }) = 0 (0x0)
/usr/home/JdeBP/b
% (cd b; PWD=/usr/local/etc truss /bin/pwd -L 3>&1 1>&2 2>&3 | grep -E '^stat|__getcwd')
stat("/usr/local/etc",{ mode=drwxr-xr-x ,inode=14835,size=158,blksize=10240 }) = 0 (0x0)
stat(".",{ mode=drwxr-xr-x ,inode=120932,size=2,blksize=131072 }) = 0 (0x0)
__getcwd("/usr/home/JdeBP/a",1024)       = 0 (0x0)
/usr/home/JdeBP/a
% (cd b; PWD=/hello/there truss /bin/pwd -L 3>&1 1>&2 2>&3 | grep -E '^stat|__getcwd')
stat("/hello/there",0x7fffffffe730)      ERR#2 'No such file or directory'
__getcwd("/usr/home/JdeBP/a",1024)       = 0 (0x0)
/usr/home/JdeBP/a
% (cd b; PWD=/usr/home/JdeBP/c truss /bin/pwd -L 3>&1 1>&2 2>&3 | grep -E '^stat|__getcwd')
stat("/usr/home/JdeBP/c",{ mode=drwxr-xr-x ,inode=120932,size=2,blksize=131072 }) = 0 (0x0)
stat(".",{ mode=drwxr-xr-x ,inode=120932,size=2,blksize=131072 }) = 0 (0x0)
/usr/home/JdeBP/c
%

Jak můžete vidět:volá pouze getcwd() pokud zjistí nesoulad; a lze to oklamat nastavením PWD na řetězec, který skutečně pojmenovává stejný adresář, ale jinou cestou.

getcwd() knihovní funkce je samostatný předmět. Ale pro upřesnění:

  • Původně to byla čistě funkce knihovny, která vytvořila cestu z pracovního adresáře zpět do kořenového adresáře opakovaným pokusem vyhledat pracovní adresář v .. adresář. Zastavil se, když dosáhl smyčky, kde .. byl stejný jako jeho pracovní adresář nebo když došlo k chybě při pokusu o otevření dalšího .. nahoru. To by bylo mnoho systémových volání pod pokličkou.
  • V současné době je situace o něco složitější. Například na FreeBSD (to platí i pro jiné operační systémy) je skutečné systémové volání, jak můžete vidět na trasování systémového volání, které bylo uvedeno dříve. Veškeré procházení z pracovního adresáře vnode až do kořenového adresáře se provádí v jediném systémovém volání, které využívá věcí, jako je přímý přístup kódu režimu jádra do mezipaměti záznamů adresáře, aby bylo možné mnohem efektivněji vyhledávat komponenty názvu cesty.

    Uvědomte si však, že i na FreeBSD a dalších operačních systémech jádro není sledujte pracovní adresář pomocí řetězce.

Navigace na .. je opět samostatným subjektem. Další upřesnění:Ačkoli jsou adresáře konvenčně (i když, jak již bylo zmíněno, to není povinné) obsahovat skutečný .. v adresářové datové struktuře na disku jádro sleduje nadřazený adresář každého adresářového vnode a může tak přejít do .. vnode libovolného pracovního adresáře. To je poněkud komplikované přípojným bodem a změněnými kořenovými mechanismy, které jsou nad rámec této odpovědi.

Na stranu

Windows NT ve skutečnosti dělá podobnou věc. Každý proces má jeden pracovní adresář nastavený pomocí SetCurrentDirectory() volání API a sledováno podle procesu jádrem prostřednictvím (interního) otevřeného popisovače souboru do tohoto adresáře; a existuje sada proměnných prostředí, které Win32 programuje (nejen příkazové interprety, ale všechny Programy Win32) používají ke sledování názvů více pracovních adresářů (jeden na jednotku), připojují je nebo přepisují při každé změně adresáře.

Související:Jak používat $? a test pro kontrolu funkce?

Běžně, na rozdíl od případu operačních systémů Unix a Linux, programy Win32 tyto proměnné prostředí uživatelům nezobrazují. Někdy je lze vidět v podsystémech podobných Unixu běžícími na Windows NT, stejně jako pomocí příkazu SET. příkazy určitým způsobem.

Další čtení

  • pwd “. Základní specifikace otevřené skupiny Vydání 7. IEEE 1003.1:2008. Otevřená skupina. 2016.
  • „Rozlišení názvu cesty“. Základní specifikace otevřené skupiny Vydání 7. IEEE 1003.1:2008. Otevřená skupina. 2016.
  • https://askubuntu.com/a/636001/43344
  • Jak se v unixu otevírají soubory?
  • k čemu je inode ve FreeBSD nebo Solaris
  • Podivná proměnná prostředí !::=::v Cygwin
  • Proč CDPATH nefunguje tak, jak je zdokumentováno v příručkách?
  • Jak mohu nastavit zsh, aby používal fyzické cesty?
  • Přechod do adresáře propojeného odkazem

Linux
  1. Linux – jak často je systém souborů Proc aktualizován v systému Linux?

  2. Linux – Jak lze zkontrolovat informace o struktuře adresářů souboru Unix/linux?

  3. Jak povolím indexování souborů a adresářů Apache v systému Linux nebo UNIX?

  1. UNIX / Linux:Jak používat Sticky Bit na adresář a soubor

  2. Jak najít domovský adresář uživatele na linuxu nebo unixu?

  3. Jak nastavím pracovní adresář nadřazeného procesu?

  1. Jak získám absolutní adresář souboru v bash?

  2. Jak zazipujete soubor a uchováte soubor .gz?

  3. Jak ukončit průzkumníka souborů Ranger zpět do příkazového řádku, ale zachovat aktuální adresář?