nedostup- nymi. Bufernyj pul vse eshche soderzhit bloki s "otlozhennoj zapis'yu", ne perepi- sannye na disk, poetomu yadro "vymyvaet" ih iz bufernogo pula. YAdro udalyaet zapisi s razdelyaemym tekstom, kotorye nahodyatsya v tablice oblastej, no ne yavlyayutsya dejstvuyushchimi (podrobnosti v glave 7), zapisyvaet na disk vse nedav- no skorrektirovannye superbloki i korrektiruet diskovye kopii vseh indeksov, kotorye trebuyut etogo. Kazalos', bylo by dostatochno otkorrektirovat' disko- vye bloki, superblok i indeksy tol'ko dlya demontiruemoj fajlovoj sistemy, odnako v celyah sohraneniya preemstvennosti izmenenij yadro vypolnyaet analogichnye dejstviya dlya vsej sistemy v celom. Zatem yadro os- vobozhdaet kornevoj indeks montirovannoj fajlovoj sistemy, uderzhivaemyj s mo- menta pervogo obrashcheniya k nemu vo vremya vypolneniya funkcii mount, i zapuska- 118 +------------------------------------------------------------+ | algoritm umount | | vhodnaya informaciya: imya special'nogo fajla, sootvetstvuyu- | | shchego demontiruemoj fajlovoj sisteme | | vyhodnaya informaciya: otsutstvuet | | { | | esli (pol'zovatel' ne yavlyaetsya superpol'zovatelem) | | vozvratit' (oshibku); | | poluchit' indeks special'nogo fajla (algoritm namei); | | izvlech' starshij i mladshij nomera demontiruemogo ustroj-| | stva; | | poluchit' v tablice montirovaniya zapis' dlya demontirue- | | moj sistemy, ishodya iz starshego i mladshego nomerov; | | osvobodit' indeks special'nogo fajla (algoritm iput); | | udalit' iz tablicy oblastej zapisi s razdelyaemym teks- | | tom dlya fajlov, prinadlezhashchih fajlovoj | | sisteme; /* glava 7hhh */ | | skorrektirovat' superblok, indeksy, vygruzit' bufery | | na disk; | | esli (kakie-to fajly iz fajlovoj sistemy vse eshche is- | | pol'zuyutsya) | | vozvratit' (oshibku); | | poluchit' iz tablicy montirovaniya kornevoj indeks monti-| | rovannoj fajlovoj sistemy; | | zablokirovat' indeks; | | osvobodit' indeks (algoritm iput); /* iget byl pri | | montirovanii */ | | zapustit' proceduru zakrytiya dlya special'nogo ustroj- | | stva; | | sdelat' nedejstvitel'nymi (otmenit') v pule bufery iz | | demontiruemoj fajlovoj sistemy; | | poluchit' iz tablicy montirovaniya indeks tochki montiro- | | vaniya; | | zablokirovat' indeks; | | ochistit' flag, pomechayushchij indeks kak "tochku montirova- | | niya"; | | osvobodit' indeks (algoritm iput); /* iget byl pri | | montirovanii */ | | osvobodit' bufer, ispol'zuemyj pod superblok; | | osvobodit' v tablice montirovaniya mesto, zanyatoe ranee;| | } | +------------------------------------------------------------+ Risunok 5.27. Algoritm demontirovaniya fajlovoj sistemy et iz drajvera proceduru zakrytiya ustrojstva, soderzhashchego fajlovuyu sistemu. Vposledstvii yadro prosmatrivaet bufery v bufernom keshe i delaet nedejstvi- tel'nymi te iz nih, v kotoryh nahodyatsya bloki demontiruemoj fajlovoj siste- my; v hranenii informacii iz etih blokov v keshe bol'she net neobhodimosti. Delaya bufery nedejstvitel'nymi, yadro vstavlyaet ih v nachalo spiska svobodnyh buferov, v to vremya kak bloki s aktual'noj informaciej ostayutsya v bufernom keshe. YAdro sbrasyvaet v indekse sistemy, gde proizvodilos' montirovanie, flag "tochki montirovaniya", ustanovlennyj funkciej mount, i osvobozhdaet in- deks. Pometiv zapis' v tablice montirovaniya svobodnoj dlya obshchego ispol'zova- niya, funkciya umount zavershaet rabotu. 119 / | usr +------------+-------------+ | | src include | +----+----+ uts sys realfile.h | - - sys -------------------- - +-------+-------+ - inode.h testfile.h ------------------ Risunok 5.28. Fajly v dereve fajlovoj sistemy, svyazannye s pomoshch'yu funkcii link 5.15 LINK Sistemnaya funkciya link svyazyvaet fajl s novym imenem v strukture katalo- gov fajlovoj sistemy, sozdavaya dlya sushchestvuyushchego indeksa novuyu zapis' v ka- taloge. Sintaksis vyzova funkcii link: link(source file name, target file name); gde source file name - sushchestvuyushchee imya fajla, a target file name - novoe (dopolnitel'noe) imya, prisvaivaemoe fajlu posle vypolneniya funkcii link. Fajlovaya sistema hranit imya puti poiska dlya kazhdoj svyazi, imeyushchejsya u fajla, i processy mogut obrashchat'sya k fajlu po lyubomu iz etih imen. YAdro ne znaet, kakoe iz imen fajla yavlyaetsya ego podlinnym imenem, poetomu imya fajla speci- al'no ne obrabatyvaetsya. Naprimer, posle vypolneniya nabora funkcij: link("/usr/src/uts/sys","/usr/include/sys"); link("/usr/include/realfile.h","/usr/src/uts/sys/testfile.h"); na odin i tot zhe fajl budut ukazyvat' tri imeni puti poiska: "/usr/src/uts/sys/testfile.h", "/usr/include/sys/testfile.h" i "/usr/include/realfile" (sm. Risunok 5.28). YAdro pozvolyaet superpol'zovatelyu (i tol'ko emu) svyazyvat' katalogi, up- roshchaya napisanie programm, trebuyushchih peresecheniya dereva fajlovoj sistemy. Es- li by eto bylo razresheno proizvol'nomu pol'zovatelyu, programmam, peresekayu- shchim ierarhicheskuyu strukturu fajlov, prishlos' by zabotit'sya o tom, chtoby ne popast' v beskonechnyj cikl v tom sluchae, esli pol'zovatel' svyazal katalog s vershinoj, stoyashchej nizhe v ierarhii. Predpolagaetsya, chto superpol'zovateli bo- lee ostorozhny v ukazanii takih svyazej. Vozmozhnost' svyazyvat' mezhdu soboj ka- talogi dolzhna byla podderzhivat'sya v rannih versiyah sistemy, tak kak eta voz- mozhnost' trebuetsya dlya realizacii komandy mkdir, kotoraya sozdaet novyj kata- log. Vklyuchenie funkcii mkdir ustranyaet neobhodimost' v svyazyvanii katalogov. Na Risunke 5.29 pokazan algoritm funkcii link. Snachala yadro, ispol'zuya algoritm namei, opredelyaet mestonahozhdenie indeksa ishodnogo fajla, uvelichi- vaet znachenie schetchika svyazej v indekse, korrektiruet diskovuyu kopiyu indeksa (dlya obespecheniya soglasovannosti) i snimaet s indeksa blokirovku. Zatem yadro ishchet fajl s novym imenem; esli on sushchestvuet, funkciya link zavershaetsya neu- dachno i yadro vosstanavlivaet prezhnee znachenie schetchika svyazej, izmenennoe ranee. V protivnom sluchae yadro nahodit v roditel'skom kataloge svobodnuyu za- pis' dlya fajla s novym imenem, zapisyvaet v nee novoe imya i nomer indeksa ishodnogo fajla i osvobozhdaet indeks roditel'skogo kataloga, ispol'zuya algo- 120 +------------------------------------------------------------+ | algoritm link | | vhodnaya informaciya: sushchestvuyushchee imya fajla | | novoe imya fajla | | vyhodnaya informaciya: otsutstvuet | | { | | poluchit' indeks dlya sushchestvuyushchego imeni fajla (algoritm | | namei); | | esli (u fajla slishkom mnogo svyazej ili proizvoditsya | | svyazyvanie kataloga bez razresheniya superpol'zovatelya) | | { | | osvobodit' indeks (algoritm iput); | | vozvratit' (oshibku); | | } | | uvelichit' znachenie schetchika svyazej v indekse; | | otkorrektirovat' diskovuyu kopiyu indeksa; | | snyat' blokirovku s indeksa; | | poluchit' indeks roditel'skogo kataloga dlya vklyucheniya no-| | vogo imeni fajla (algoritm namei); | | esli (fajl s novym imenem uzhe sushchestvuet ili sushchestvuyu- | | shchij fajl i novyj fajl nahodyatsya v raznyh fajlovyh sis- | | temah) | | { | | otmenit' korrektirovku, sdelannuyu vyshe; | | vozvratit' (oshibku); | | } | | sozdat' zapis' v roditel'skom kataloge dlya fajla s no- | | vym imenem: | | vklyuchit' v nee novoe imya i nomer indeksa sushchestvuyu- | | shchego fajla; | | osvobodit' indeks roditel'skogo kataloga (algoritm | | iput); | | osvobodit' indeks sushchestvuyushchego fajla (algoritm iput); | | } | +------------------------------------------------------------+ Risunok 5.29. Algoritm svyazyvaniya fajlov ritm iput. Poskol'ku fajl s novym imenem ranee ne sushchestvoval, osvobozhdat' eshche kakoj-nibud' indeks ne nuzhno. YAdro, osvobozhdaya indeks ishodnogo fajla, delaet zaklyuchenie: schetchik svyazej v indekse imeet znachenie, na 1 bol'shee, chem to znachenie, kotoroe schetchik imel pered vyzovom funkcii, i obrashchenie k fajlu teper' mozhet proizvodit'sya po eshche odnomu imeni v fajlovoj sisteme. Schetchik svyazej hranit kolichestvo zapisej v katalogah, kotorye (zapisi) uka- zyvayut na fajl, i tem samym otlichaetsya ot schetchika ssylok v indekse. Esli po zavershenii vypolneniya funkcii link k fajlu net obrashchenij so storony drugih processov, schetchik ssylok v indekse prinimaet znachenie, ravnoe 0, a schetchik svyazej - znachenie, bol'shee ili ravnoe 2. Naprimer, vypolnyaya funkciyu, vyzvannuyu kak: link("source","/dir/target"); yadro obnaruzhivaet indeks dlya fajla "source", uvelichivaet v nem znachenie schetchika svyazej, zapominaet nomer indeksa, skazhem 74, i snimaet s indeksa blokirovku. YAdro takzhe nahodit indeks kataloga "dir", yavlyayushchegosya roditel'- skim katalogom dlya fajla "target", ishchet svobodnoe mesto v kataloge "dir" i zapisyvaet v nego imya fajla "target" i nomer indeksa 74. Po okonchanii etih dejstvij ono osvobozhdaet indeks fajla "source" po algoritmu iput. Esli zna- chenie schetchika svyazej fajla "source" ran'she bylo ravno 1, to teper' ono rav- 121 no 2. Stoit upomyanut' o dvuh tupikovyh situaciyah, yavivshihsya prichinoj togo, chto process snimaet s indeksa ishodnogo fajla blokirovku posle uvelicheniya znache- niya schetchika svyazej. Esli by yadro ne snimalo s indeksa blokirovku, dva pro- cessa, vypolnyayushchie odnovremenno sleduyushchie funkcii: process A: link("a/b/c/d","e/f/g"); process B: link("e/f","a/b/c/d/ee"); zashli by v tupik (vzaimnaya blokirovka). Predpolozhim, chto process A obnaruzhil indeks fajla "a/b/c/d" v tot samyj moment, kogda process B obnaruzhil indeks fajla "e/f". Fraza "v tot zhe samyj moment" oznachaet, chto sistemoj dostignuto sostoyanie, pri kotorom kazhdyj process poluchil iskomyj indeks. (Risunok 5.30 illyustriruet stadii vypolneniya processov.) Kogda zhe teper' process A popyta- etsya poluchit' indeks fajla "e/f", on priostanovit svoe vypolnenie do teh por, poka indeks fajla "f" ne osvoboditsya. V to zhe vremya process B pytaetsya poluchit' indeks kataloga "a/b/c/d" i priostanavlivaetsya v ozhidanii osvobozh- deniya indeksa fajla "d". Process A budet uderzhivat' zablokirovannym indeks, nuzhnyj processu B, a process B, v svoyu ochered', budet uderzhivat' zablokiro- vannym indeks, nuzhnyj processu A. Na praktike etot klassicheskij primer vza- imnoj blokirovki nevozmozhen blagodarya tomu, chto yadro osvobozhdaet indeks is- hodnogo fajla posle uvelicheniya znacheniya schetchika svyazej. Poskol'ku pervyj iz resursov (indeks) svoboden pri obrashchenii k sleduyushchemu resursu, vzaimnaya blo- kirovka ne proishodit. Sleduyushchij primer pokazyvaet, kak dva processa mogut zajti v tupik, esli s indeksa ne byla snyata blokirovka. Odinochnyj process mozhet takzhe zablokiro- vat' samogo sebya. Esli on vyzyvaet funkciyu: link("a/b/c","a/b/c/d"); to v nachale algoritma on poluchaet indeks dlya fajla "c"; esli by yadro ne sni- malo by s indeksa blokirovku, process zashel by v tupik, zaprosiv indeks "c" pri poiske fajla "d". Esli by dva processa, ili dazhe odin process, ne mogli prodolzhat' svoe vypolnenie iz-za vzaimnoj blokirovki (ili samoblokirovki), chto v rezul'tate proizoshlo by v sisteme ? Poskol'ku indeksy yavlyayutsya temi resursami, kotorye predostavlyayutsya sistemoj za konechnoe vremya, poluchenie signala ne mozhet byt' prichinoj vozobnovleniya processom svoej raboty (glava 7). Sledovatel'no, sistema ne mozhet vyjti iz tupika bez perezagruzki. Esli k fajlam, zablokirovannym processami, net obrashchenij so storony drugih proces- sov, vzaimnaya blokirovka ne zatragivaet ostal'nye processy v sisteme. Odna- ko, lyubye processy, obrativshiesya k etim fajlam (ili obrativshiesya k drugim fajlam cherez zabloki- rovannyj katalog), nepremenno zajdut v tupik. Takim obrazom, esli zablokiro- vany fajly "/bin" ili "/usr/bin" (obychnye hranilishcha komand) ili fajl "/bin/sh" (komandnyj processor shell), posledstviya dlya sistemy budut gibel'- nymi. 5.16 UNLINK Sistemnaya funkciya unlink udalyaet iz kataloga tochku vhoda dlya fajla. Sin- taksis vyzova funkcii unlink: unlink(pathname); gde pathname ukazyvaet imya fajla, udalyaemoe iz ierarhii katalogov. Esli pro- cess razryvaet dannuyu svyaz' fajla s katalogom pri pomoshchi funkcii unlink, po ukazannomu v vyzove funkcii imeni fajl ne budet dostupen, poka v kataloge ne 122 Process A Process B +------------------------------------------------------------- | - Pytaetsya poluchit' indeks | - dlya fajla "e" | - PRIOSTANOV - indeks fajla | - "e" zablokirovan | Poluchaet indeks dlya "a" - | Osvobozhdaet indeks "a" - | Poluchaet indeks dlya "b" - | Osvobozhdaet indeks "b" - | Poluchaet indeks dlya "c" - | Osvobozhdaet indeks "c" - | Poluchaet indeks dlya "d" - | - | Pytaetsya poluchit' indeks - | dlya "e" - | PRIOSTANOV - indeks fajla - | "e" zablokirovan - | - - | +-----------------------------------------------+ | | Vozobnovlenie vypolneniya - indeks fajla "e" | | | razblokirovan | | +-----------------------------------------------+ | - Poluchaet indeks dlya "e" | - Osvobozhdaet indeks "e" | - Poluchaet indeks dlya "f" | - Poluchaet indeks dlya "a" | - Osvobozhdaet indeks "a" | - - | - - | - Pytaetsya poluchit' indeks | - dlya fajla "d" | - PRIOSTANOV - indeks fajla | - "d" zablokirovan | - processom A | - | Poluchaet indeks dlya "e" | Osvobozhdaet indeks "e" | Pytaetsya poluchit' indeks | dlya "f" | PRIOSTANOV - indeks fajla | "f" zablokirovan | processom B | +-------------------------------+ | | Tupik (vzaimnaya blokirovka) | v +-------------------------------+ Vremya Risunok 5.30. Vzaimnaya blokirovka processov pri vypolnenii funkcii link sozdana eshche odna zapis' s etim imenem. Naprimer, pri vypolnenii sleduyushchego fragmenta programmy: unlink("myfile"); fd = open("myfile",O_RDONLY); funkciya open zavershitsya neudachno, poskol'ku k momentu ee vypolneniya v teku- shchem kataloge bol'she ne budet fajla s imenem myfile. Esli udalyaemoe imya yavlya- 123 etsya poslednej svyaz'yu fajla s katalogom, yadro v itoge osvobozhdaet vse infor- macionnye bloki fajla. Odnako, esli u fajla bylo neskol'ko svyazej, on osta- etsya vse eshche dostupnym pod drugimi imenami. Na Risunke 5.31 predstavlen algoritm funkcii unlink. Snachala dlya poiska fajla s udalyaemoj svyaz'yu yadro ispol'zuet modifikaciyu algoritma namei, koto- raya vmesto indeksa fajla vozvrashchaet indeks roditel'skogo kataloga. YAdro ob- rashchaetsya k indeksu fajla v pamyati, ispol'zuya algoritm iget. (Osobyj sluchaj, svyazannyj s udaleniem imeni fajla ".", budet rassmotren v uprazhnenii). Posle proverki otsutstviya oshibok i (dlya ispolnyaemyh fajlov) udaleniya iz tablicy oblastej zapisej s neaktivnym razdelyaemym tekstom (glava 7) yadro stiraet imya fajla iz roditel'skogo kataloga: sdelat' znachenie nomera indeksa ravnym 0 dostatochno dlya ochistki mesta, zanimaemogo imenem fajla v kataloge. Zatem yad- ro proizvodit sinhronnuyu zapis' kataloga na disk, garantiruya tem samym, chto pod svoim prezhnim imenem fajl uzhe ne budet dostupen, umen'shaet znachenie schetchika svyazej i s pomoshch'yu algoritma iput osvobozhdaet v pamyati indeksy ro- ditel'skogo kataloga i fajla s udalyaemoj svyaz'yu. Pri osvobozhdenii v pamyati po algoritmu iput indeksa fajla s udalyaemoj svyaz'yu, esli znacheniya schetchika ssylok i schetchika svyazej stanovyatsya ravnymi 0, yadro zabiraet u fajla obratno diskovye bloki, kotorye on zanimal. Na etot indeks bol'she ne ukazyvaet ni odno iz fajlovyh imen i indeks neaktiven. Dlya +------------------------------------------------------------+ | algoritm unlink | | vhodnaya informaciya: imya fajla | | vyhodnaya informaciya: otsutstvuet | | { | | poluchit' roditel'skij indeks dlya fajla s udalyaemoj | | svyaz'yu (algoritm namei); | | /* esli v kachestve fajla vystupaet tekushchij katalog... */| | esli (poslednej komponentoj imeni fajla yavlyaetsya ".") | | uvelichit' znachenie schetchika ssylok v indekse; | | v protivnom sluchae | | poluchit' indeks dlya fajla s udalyaemoj svyaz'yu (algo-| | ritm iget); | | esli (fajl yavlyaetsya katalogom, no pol'zovatel' ne yavlya- | | etsya superpol'zovatelem) | | { | | osvobodit' indeksy (algoritm iput); | | vozvratit' (oshibku); | | } | | esli (fajl imeet razdelyaemyj tekst i tekushchee znachenie | | schetchika svyazej ravno 1) | | udalit' zapisi iz tablicy oblastej; | | v roditel'skom kataloge: obnulit' nomer indeksa dlya uda-| | lyaemoj svyazi; | | osvobodit' indeks roditel'skogo kataloga (algoritm | | iput); | | umen'shit' chislo svyazej fajla; | | osvobodit' indeks fajla (algoritm iput); | | /* iput proveryaet, ravno li chislo svyazej 0, esli | | * da, | | * osvobozhdaet bloki fajla (algoritm free) i | | * osvobozhdaet indeks (algoritm ifree); | | */ | | } | +------------------------------------------------------------+ Risunok 5.31. Algoritm udaleniya svyazi fajla s katalogom 124 togo, chtoby zabrat' diskovye bloki, yadro v cikle prosmatrivaet tablicu so- derzhimogo indeksa, osvobozhdaya vse bloki pryamoj adresacii nemedlenno (v soot- vetstvii s algoritmom free). CHto kasaetsya blokov kosvennoj adresacii, yadro osvobozhdaet vse bloki, poyavlyayushchiesya na razlichnyh urovnyah kosvennosti, rekur- sivno, prichem v pervuyu ochered' osvobozhdayutsya bloki s men'shim urovnem. Ono obnulyaet nomera blokov v tablice soderzhimogo indeksa i ustanavlivaet razmer fajla v indekse ravnym 0. Zatem yadro ochishchaet v indekse pole tipa fajla, uka- zyvaya tem samym, chto indeks svoboden, i osvobozhdaet indeks po algoritmu ifree. YAdro delaet neobhodimuyu korrekciyu na diske, tak kak diskovaya kopiya indeksa vse eshche ukazyvaet na to, chto indeks ispol'zuetsya; teper' indeks svo- boden dlya naznacheniya drugim fajlam. 5.16.1 Celostnost' fajlovoj sistemy YAdro posylaet svoi zapisi na disk dlya togo, chtoby svesti k minimumu opasnost' iskazheniya fajlovoj sistemy v sluchae sistemnogo sboya. Naprimer, kogda yadro udalyaet imya fajla iz roditel'skogo kataloga, ono sinhronno pere- pisyvaet katalog na disk - pered tem, kak unichtozhit' soderzhimoe fajla i os- vobodit' ego indeks. Esli sistema dala sboj do togo, kak proizoshlo udalenie soderzhimogo fajla, ushcherb fajlovoj sisteme budet nanesen minimal'nyj: odin iz indeksov budet imet' chislo svyazej, na 1 prevyshayushchee chislo zapisej v katalo- ge, kotorye ssylayutsya na etot indeks, no vse ostal'nye imena putej poiska fajla ostanutsya dopustimymi. Esli zapis' na disk ne byla sdelana sinhronno, tochka vhoda v katalog na diske posle sistemnogo sboya mozhet ukazyvat' na svo- bodnyj (ili perenaznachennyj) indeks. Takim obrazom, chislo zapisej v kataloge na diske, kotorye ssylayutsya na indeks, prevysilo by znachenie schetchika ssylok v indekse. V chastnosti, esli imya fajla bylo imenem poslednej svyazi fajla, eto imya ukazyvalo by na nenaznachennyj indeks. Ne vyzyvaet somneniya, chto v pervom sluchae ushcherb, nanosimyj sisteme, menee ser'ezen i legko ustranim (sm. razdel 5.18). Predpolozhim, naprimer, chto u fajla est' dve svyazi s imenami "a" i "b", odna iz kotoryh - "a" - razryvaetsya processom s pomoshch'yu funkcii unlink. Esli yadro zapisyvaet na diske rezul'taty vseh svoih dejstvij, to ono, ochishchaya toch- ku vhoda v katalog dlya fajla "a", delaet to zhe samoe na diske. Esli sistema dala sboj posle zaversheniya zapisi rezul'tatov na disk, chislo svyazej u fajla "b" budet ravno 2, no fajl "a" uzhe ne budet sushchestvovat', poskol'ku prezhnyaya zapis' o nem byla ochishchena pered sboem sistemy. Fajl "b", takim obrazom, bu- det imet' lishnyuyu svyaz', no posle perezagruzki chislo svyazej pereustanovitsya i sistema budet rabotat' nadlezhashchim obrazom. Teper' predpolozhim, chto yadro zapisyvalo na disk rezul'taty svoih dejst- vij v obratnom poryadke i sistema dala sboj: to est', yadro umen'shilo znachenie schetchika svyazej dlya fajla "b", sdelav ego ravnym 1, zapisalo indeks na disk i dalo sboj pered tem, kak ochistit' v kataloge tochku vhoda dlya fajla "a". Posle perezagruzki sistemy zapisi o fajlah "a" i "b" v sootvetstvuyushchih kata- logah budut sushchestvovat', no schetchik svyazej u togo fajla, na kotoryj oni ukazyvayut, budet imet' znachenie 1. Esli zatem process zapustit funkciyu unlink dlya fajla "a", znachenie schetchika svyazej stanet ravnym 0, nesmotrya na to, chto fajl "b" ssylaetsya na tot zhe indeks. Esli pozdnee yadro perenaznachit indeks v rezul'tate vypolneniya funkcii creat, schetchik svyazej dlya novogo faj- la budet imet' znachenie, ravnoe 1, no na fajl budut ssylat'sya dva imeni puti poiska. Sistema ne mozhet vypravit' situaciyu, ne pribegaya k pomoshchi programm soprovozhdeniya (fsck, opisannoj v razdele 5.18), obrashchayushchihsya k fajlovoj sis- teme cherez blochnyj ili strokovyj interfejs. Dlya togo, chtoby svesti k minimumu opasnost' iskazheniya fajlovoj sistemy v sluchae sistemnogo sboya, yadro osvobozhdaet indeksy i diskovye bloki takzhe v osobom poryadke. Pri udalenii soderzhimogo fajla i ochistke ego indeksa mozhno snachala osvobodit' bloki, soderzhashchie dannye fajla, a mozhno osvobodit' indeks 125 i zanovo perepisat' ego. Rezul'tat v oboih sluchayah, kak pravilo, odinakovyj, odnako, esli gde-to v seredine proizojdet sistemnyj sboj, oni budut razli- chat'sya. Predpolozhim, chto yadro snachala osvobodilo diskovye bloki, prinadle- zhavshie fajlu, i dalo sboj. Posle perezagruzki sistemy indeks vse eshche soder- zhit ssylki na diskovye bloki, zanimaemye fajlom prezhde i nyne ne hranyashchie otnosyashchuyusya k fajlu informaciyu. YAdru fajl pokazalsya by vpolne udovletvori- tel'nym, no pol'zovatel' pri obrashchenii k fajlu zametit iskazhenie dannyh. |ti diskovye bloki k tomu zhe mogut byt' perenaznacheny drugim fajlam. CHtoby ochis- tit' fajlovuyu sistemu programmoj fsck, potrebovalis' by bol'shie usiliya. Od- nako, esli sistema snachala perepisala indeks na disk, a potom dala sboj, pol'zovatel' ne zametit kakih-libo iskazhenij v fajlovoj sisteme posle pere- zagruzki. Informacionnye bloki, ranee prinadlezhavshie fajlu, stanut nedostup- ny dlya sistemy, no kakih-nibud' yavnyh izmenenij pri etom pol'zovateli ne uvidyat. Programme fsck tak zhe bylo by proshche zabrat' nazad osvobodivshiesya posle udaleniya svyazi diskovye bloki, nezheli proizvodit' ochistku, neobhodimuyu v pervom iz rassmatrivaemyh sluchaev. 5.16.2 Povody dlya konkurencii Povodov dlya konkurencii pri vypolnenii sistemnoj funkcii unlink ochen' mnogo, osobenno pri udalenii imen katalogov. Komanda rmdir udalyaet katalog, ubedivshis' predvaritel'no v tom, chto v kataloge otsutstvuyut fajly (ona schi- tyvaet katalog i proveryaet znacheniya indeksov vo vseh zapisyah kataloga na ra- venstvo nulyu). No tak kak komanda rmdir zapuskaetsya na pol'zovatel'skom urovne, dejstviya po proverke soderzhimogo kataloga i udaleniya kataloga vypol- nyayutsya ne tak uzh prosto; sistema dolzhna pereklyuchat' kontekst mezhdu vypolne- niem funkcij read i unlink. Odnako, posle togo, kak komanda rmdir obnaruzhi- la, chto katalog pust, drugoj process mozhet predprinyat' popytku sozdat' fajl v kataloge funkciej creat. Izbezhat' etogo pol'zovateli mogut tol'ko putem ispol'zovaniya mehanizma zahvata fajla i zapisi. Tem ne menee, raz process pristupil k vypolneniyu funkcii unlink, nikakoj drugoj process ne mozhet obra- tit'sya k fajlu s udalyaemoj svyaz'yu, poskol'ku indeksy roditel'skogo kataloga i fajla zablokirovany. Obratimsya eshche raz k algoritmu funkcii link i posmotrim, kakim obrazom sistema snimaet s indeksa blokirovku do zaversheniya vypolneniya funkcii. Esli by drugoj process udalil svyaz' fajla poka ego indeks svoboden, on by tem sa- mym tol'ko umen'shil znachenie schetchika svyazej; tak kak znachenie schetchika svya- zej bylo uvelicheno pered udaleniem svyazi, eto znachenie ostanetsya polozhitel'- nym. Sledovatel'no, fajl ne mozhet byt' udalen i sistema rabotaet nadezhno. |ta situaciya analogichna toj, kogda funkciya unlink vyzyvaetsya srazu posle za- versheniya vypolneniya funkcii link. Drugoj povod dlya konkurencii imeet mesto v tom sluchae, kogda odin pro- cess preobrazuet imya puti poiska fajla v indeks fajla po algoritmu namei, a drugoj process udalyaet katalog, imya kotorogo vhodit v put' poiska. Dopustim, process A delaet razbor imeni "a/ b/c/d" i priostanavlivaetsya vo vremya polu- cheniya indeksa dlya fajla "c". On mozhet priostanovit'sya pri popytke zablokiro- vat' indeks ili pri popytke obratit'sya k diskovomu bloku, gde etot indeks hranitsya (sm. algoritmy iget i bread). Esli processu B nuzhno udlit' svyaz' dlya kataloga s imenem "c", on mozhet priostanovit'sya po toj zhe samoj prichine, chto i process A. Pust' yadro vposledstvii reshit vozobnovit' process B ran'she processa A. Prezhde chem process A prodolzhit svoe vypolnenie, process B zaver- shitsya, udaliv svyaz' kataloga "c" i ego soderzhimoe po etoj svyazi. Pozdnee, process A popytaetsya obratit'sya k nesushchestvuyushchemu indeksu, kotoryj uzhe byl udalen. Algoritm namei, proveryayushchij v pervuyu ochered' neravenstvo znacheniya schetchika svyazej nulyu, soobshchit ob oshibke. Takoj proverki, odnako, ne vsegda dostatochno, poskol'ku mozhno predpolo- zhit', chto kakoj-nibud' drugoj process sozdast v lyubom meste fajlovoj sistemy novyj katalog i poluchit tot indeks, kotoryj ranee ispol'zovalsya dlya "c". 126 Process A budet zabluzhdat'sya, dumaya, chto on obratilsya k nuzhnomu indeksu (sm. Risunok 5.32). Kak by to ni bylo, sistema sohranyaet svoyu celostnost'; samoe hudshee, chto mozhet proizojti, eto obrashchenie ne k tomu fajlu - s vozmozhnym na- Process A Process B Process C +------------------------------------------------------------ | - Udalyaetsya svyaz' faj- - | - la s imenem "s" - | - - | - Obnaruzhivaet, chto - | - indeks fajla "c" - | - zablokirovan - | - Priostanavlivaet - | - vypolnenie - | - - - | Prosmatrivaet ka- - - | talog "b" v pois- - - | kah imeni "c" - - | Poluchaet nomer in- - - | deksa dlya "c" - - | Obnaruzhivaet, chto - - | indeks fajla "c" - - | zablokirovan - - | Priostanavlivaet - - | vypolnenie - - | - - - | - Vozobnovlyaet vypol- - | - nenie, indeks "c" - | - svoboden - | - Udalyaet svyaz' s ime- - | - nem "c", prezhnij in- - | - deks osvobozhdaetsya, - | - esli chislo svyazej =0 - | - - - | - - Naznachaet indeks | - - novomu fajlu "n" | - - Sluchajno naznacha- | - - et emu indeks, ra- | - - nee prinadlezhavshij | - - "c" | - - | - - V konechnom itoge | - - snimaet blokirovku | - - s indeksa "n" | - - | Vozobnovlyaet vypol- - | nenie, prezhnij in- - | deks "c" (teper' - | "n") svoboden - | Poluchaet indeks "n" - | Prosmatrivaet ka- - | talog "n" v pois- - | kah imeni "d" - v Vremya Risunok 5.32. Sopernichestvo processov za indeks pri vypolne- nii funkcii unlink 127 +------------------------------------------------------------+ | #include | | #include | | #include | | | | main(argc,argv) | | int argc; | | char *argv[]; | | { | | int fd; | | char buf[1024]; | | struct stat statbuf; | | | | if (argc != 2) /* nuzhen parametr */ | | exit(); | | fd = open(argv[1],O_RDONLY); | | if (fd == -1) /* open zavershilas' | | neudachno */ | | exit(); | | if (unlink(argv[1]) == -1) /* udalit' svyaz' s tol'ko | | chto otkrytym fajlom */ | | exit(); | | if (stat(argv[1],&statbuf) == -1) /* uznat' sostoya- | | nie fajla po imeni */ | | printf("stat %s zavershilas' neudachno\n",argv[1]);| | /* kak i sledovalo by */ | | else | | printf("stat %s zavershilas' uspeshno!\n",argv[1]);| | if (fstat(fd,&statbuf) == -1) /* uznat' sostoyanie | | fajla po identifikatoru */ | | printf("fstat %s srabotala neudachno!\n",argv[1]);| | else | | printf("fstat %s zavershilas' uspeshno\n",argv[1]);| | /* kak i sledovalo by */ | | while (read(fd,buf,sizeof(buf)) > 0) /* chtenie otkry- | | togo fajla s udalennoj svyaz'yu */ | | printf("%1024s",buf); /* vyvod na pechat' polya | | razmerom 1 Kbajt */ | | } | +------------------------------------------------------------+ Risunok 5.33. Udalenie svyazi s otkrytym fajlom rusheniem zashchity - no sopernichestva takogo roda na praktike dovol'no redki. Process mozhet udalit' svyaz' fajla v to vremya, kak drugomu processu nuzh- no, chtoby fajl ostavalsya otkrytym. (Dazhe process, udalyayushchij svyaz', mozhet byt' processom, vypolnivshim eto otkrytie). Poskol'ku yadro snimaet s indeksa blokirovku po okonchanii vypolneniya funkcii open, funkciya unlink zavershitsya uspeshno. YAdro budet vypolnyat' algoritm unlink tochno tak zhe, kak esli by fajl ne byl otkryt, i udalit iz kataloga zapis' o fajle. Teper' po imeni udalen- noj svyazi k fajlu ne smozhet obratit'sya nikakoj drugoj process. Odnako, tak kak sistemnaya funkciya open uvelichila znachenie schetchika ssylok v indekse, yad- ro ne ochishchaet soderzhimoe fajla pri vypolnenii algoritma iput pered zavershe- niem funkcii unlink. Poetomu process, otkryvshij fajl, mozhet proizvodit' nad fajlom vse obychnye dejstviya po ego deskriptoru, vklyuchaya chtenie iz fajla i zapis' v fajl. No kogda process zakryvaet fajl, znachenie schetchika ssylok v algoritme iput stanovitsya ravnym 0, i yadro ochishchaet soderzhimoe fajla. Koroche govorya, process, otkryvshij fajl, prodolzhaet rabotu tak, kak esli by funkciya 128 unlink ne vypolnyalas', a unlink, v svoyu ochered', rabotaet tak, kak esli by fajl ne byl otkryt. Drugie sistemnye funkcii takzhe mogut prodolzhat' vypol- nyat'sya v processe, otkryvshem fajl. V privedennom na Risunke 5.33 primere process otkryvaet fajl, ukazannyj v kachestve parametra, i zatem udalyaet svyaz' tol'ko chto otkrytogo fajla. Fun- kciya stat zavershitsya neudachno, poskol'ku pervonachal'noe imya posle unlink bol'she ne ukazyvaet na fajl (predpo- lagaetsya, chto tem vremenem nikakoj drugoj process ne sozdal fajl s tem zhe imenem), no funkciya fstat zavershitsya uspeshno, tak kak ona vybiraet indeks po deskriptoru fajla. Process vypolnyaet cikl, schityvaya na kazhdom shage po 1024 bajta i peresylaya fajl v standartnyj vyvod. Kogda pri chtenii budet obnaruzhen konec fajla, process zavershaet rabotu: posle zaversheniya processa fajl peres- taet sushchestvovat'. Processy chasto sozdayut vremennye fajly i srazu zhe udalyayut svyaz' s nimi; oni mogut prodolzhat' vvod-vyvod v eti fajly, no imena fajlov bol'she ne poyavlyayutsya v ierarhii katalogov. Esli process po kakoj-libo prichi- ne zavershaetsya avarijno, on ne ostavlyaet ot vremennyh fajlov nikakogo sleda. 5.17 ABSTRAKTNYE OBRASHCHENIYA K FAJLOVYM SISTEMAM Uajnbergerom bylo vvedeno ponyatie "tip fajlovoj sistemy" dlya ob®yasneniya mehanizma raboty prinadlezhavshej emu setevoj fajlovoj sistemy (sm. kratkoe opisanie etogo mehanizma v [Killian 84]) i v pozdnejshej versii sistemy V podderzhivayutsya osnovopolagayushchie principy ego shemy. Nalichie tipa fajlovoj sistemy daet yadru vozmozhnost' podderzhivat' odnovremenno mnozhestvo fajlovyh sistem, takih kak setevye fajlovye sistemy (glava 13) ili dazhe fajlovye sis- temy iz drugih operacionnyh sistem. Processy pol'zuyutsya dlya obrashcheniya k faj- lam obychnymi funkciyami sistemy UNIX, a yadro ustanavlivaet sootvetstvie mezhdu obshchim naborom fajlovyh operacij i operaciyami, specifichnymi dlya kazhdogo tipa fajlovoj sistemy. Operacii fajlovoj Obshchie indeksy Indeks fajlovoj sistemy sistemy versii V +---------------+ +------+ +-------+ Versiya V | open | +-----+- -+-------->| | | close | | +------+ +-------+ | read | | +---+- -+---+ | | | write |<---+ | +------+ | +-------+ | - |<-----|---+- -+---|---->| | | - | | +------+ | +-------+ | - | | | | | | - | | - | | +------+ | | - | +---------------+ | | | | | - | Udalennaya | ropen | | +------+ | +-------+ sistema | rclose | | | - | | | rread | | | - | | Indeks udalen- | rwrite |<-----+ | - | | noj sistemy | - | | - | | +-------+ | - | | - | | | | | - | | - | | +-------+ | - | | - | +---->| | +---------------+ | - | +-------+ | - | | - | | | | - | | - | +-------+ | - | | - | | | | - | | - | +-------+ | - | | - | | - | +---------------+ +------+ +-------+ Risunok 5.34. Indeksy dlya fajlovyh sistem razlichnyh tipov 129 Indeks vystupaet interfejsom mezhdu abstraktnoj fajlovoj sistemoj i ot- del'noj fajlovoj sistemoj. Obshchaya kopiya indeksa v pamyati soderzhit informaciyu, ne zavisyashchuyu ot otdel'noj fajlovoj sistemy, a takzhe ukazatel' na chastnyj in- deks fajlovoj sistemy, kotoryj uzhe soderzhit informaciyu, specifichnuyu dlya nee. CHastnyj indeks fajlovoj sistemy soderzhit takuyu informaciyu, kak p