Ocenite etot tekst:




    V poslednej glave rassmatrivalis' vnutrennie struktury dannyh dlya fajlo-
voj  sistemy i algoritmy raboty s nimi. V etoj glave rech' pojdet o sistemnyh
funkciyah dlya raboty s fajlovoj sistemoj s ispol'zovaniem ponyatij,  vvedennyh
v  predydushchej glave. Rassmatrivayutsya sistemnye funkcii, obespechivayushchie obra-
shchenie k sushchestvuyushchim fajlam, takie kak open, read, write, lseek i close, za-
tem funkcii sozdaniya novyh fajlov, a imenno, creat i mknod, i, nakonec, fun-
kcii dlya raboty s indeksom ili dlya peredvizheniya po fajlovoj sisteme:  chdir,
chroot,  chown,  stat  i fstat. Issleduyutsya bolee slozhnye sistemnye funkcii:
pipe i dup imeyut vazhnoe znachenie dlya realizacii kanalov v shell'e;  mount  i
umount  rasshiryayut  vidimoe  dlya  pol'zovatelya derevo fajlovyh sistem; link i
unlink izmenyayut ierarhicheskuyu strukturu fajlovoj sistemy. Zatem daetsya pred-
stavlenie ob abstrakciyah, svyazannyh s fajlovoj sistemoj, v otnoshenii podder-
zhki razlichnyh fajlovyh sistem, podchinyayushchihsya standartnym interfejsam. V pos-
lednem razdele glavy rech' pojdet o  soprovozhdenii  fajlovoj  sistemy.  Glava
znakomit  s tremya strukturami dannyh yadra: tablicej fajlov, v kotoroj kazhdaya
zapis' svyazana s odnim iz otkrytyh v sisteme fajlov, tablicej  pol'zovatel'-
skih  deskriptorov  fajlov, v kotoroj kazhdaya zapis' svyazana s fajlovym desk-
riptorom, izvestnym processu, i tablicej montirovaniya, v kotoroj  soderzhitsya
informaciya po kazhdoj aktivnoj fajlovoj sisteme.

             Funkcii dlya raboty s fajlovoj sistemoj
+----------------------------------------------------------------+
+------+--------------+--------+-------+-------+---------+-------+
| Voz- | Ispol'zuyut   | Nazna- | Rabo- | Vvod- | Rabota- | Uprav-|
| vra- | algoritm     | chayut   | tayut  | vyvod | yut so   | lenie |
| shchayut | namei        | indek- | s at- | iz    | struktu-| de-   |
| desk-|              | sy     | ribu- | fajla | roj faj-| rev'- |
| rip- |              |        | tami  |       | lovyh   | yami   |
| tory |              |        | fajla |       | sistem  |       |
| fajla|              |        |       |       |         |       |
+------+--------------+--------+-------+-------+---------+-------+
| open | open   stat  |        |       |       |         |       |
| creat| creat  link  | creat  | chown | read  |         |       |
| dup  | chdir  unlink| mknod  | chmod | write | mount   | chdir |
| pipe | chroot mknod | link   | stat  | lseek | umount  | chown |
| close| chown  mount | unlink |       |       |         |       |
|      | chmod  umount|        |       |       |         |       |
+------+--------------+--------+-------+-------+---------+-------+
+---+--+--------------+--------+-------+-------+---------+----+--+
    |  Algoritmy raboty s fajlovoj sistemoj na nizhnem urovne  |
    +-------------+------------------+------------------------+
    |    namei    |                  |                        |
    +-------------+ ialloc    ifree  |   alloc   free   bmap  |
    | iget   iput |                  |                        |
    +-------------+------------------+------------------------+
    +---------------------------------------------------------+
    |             algoritmy raboty s buferami                 |
    +---------------------------------------------------------+
    |    getblk     brelse     bread     breada     bwrite    |
    +---------------------------------------------------------+

    Risunok 5.1.  Funkcii dlya raboty s  fajlovoj  sistemoj  i  ih
                  svyaz' s drugimi algoritmami

                                     85

    Na  Risunke  5.1 pokazana vzaimosvyaz' mezhdu sistemnymi funkciyami i algo-
ritmami, opisannymi ranee. Sistemnye funkcii klassificiruyutsya  na  neskol'ko
kategorij, hotya nekotorye iz funkcij prisutstvuyut bolee, chem v odnoj katego-
rii:

  *  Sistemnye  funkcii,  vozvrashchayushchie  deskriptory fajlov dlya ispol'zovaniya
    drugimi sistemnymi funkciyami;
  * Sistemnye funkcii, ispol'zuyushchie algoritm namei dlya  analiza  imeni  puti
    poiska;
  *  Sistemnye  funkcii, naznachayushchie i osvobozhdayushchie indeks s ispol'zovaniem
    algoritmov ialloc i ifree;
  * Sistemnye funkcii, ustanavlivayushchie ili izmenyayushchie atributy fajla;
  * Sistemnye funkcii, pozvolyayushchie processu proizvodit' vvod-vyvod dannyh  s
    ispol'zovaniem algoritmov alloc, free i algoritmov vydeleniya bufera;
  * Sistemnye funkcii, izmenyayushchie strukturu fajlovoj sistemy;
  * Sistemnye funkcii, pozvolyayushchie processu izmenyat' sobstvennoe predstavle-
    nie o strukture dereva fajlovoj sistemy.




    Vyzov  sistemnoj  funkcii  open (otkryt' fajl) - eto pervyj shag, kotoryj
dolzhen sdelat' process, chtoby obratit'sya k dannym v fajle. Sintaksis  vyzova
funkcii open:

    fd = open(pathname,flags,modes);

gde pathname - imya fajla, flags ukazyvaet rezhim otkrytiya (naprimer, dlya chte-
niya  ili zapisi), a modes soderzhit prava dostupa k fajlu v sluchae, esli fajl
sozdaetsya. Sistemnaya funkciya open  vozvrashchaet  celoe  chislo  (*),  imenuemoe
pol'zovatel'skim  deskriptorom fajla. Drugie operacii nad fajlami, takie kak
chtenie, zapis', po-
zicionirovanie golovok chteniya-zapisi, vosproizvedenie deskriptora fajla, us-
tanovka parametrov vvoda-vyvoda, opredelenie statusa fajla i zakrytie fajla,
ispol'zuyut znachenie deskriptora fajla, vozvrashchaemoe sistemnoj funkciej open.
    YAdro prosmatrivaet fajlovuyu sistemu v poiskah fajla po  ego  imeni,  is-
pol'zuya  algoritm  namei  (sm. Risunok 5.2). Ono proveryaet prava na otkrytie
fajla posle togo, kak obnaruzhit kopiyu indeksa fajla v pamyati, i vydelyaet ot-
kryvaemomu fajlu zapis' v tablice fajlov.  Zapis'  tablicy  fajlov  soderzhit
ukazatel'  na  indeks  otkrytogo fajla i pole, v kotorom hranitsya smeshchenie v
bajtah ot nachala fajla do mesta, otkuda predpolagaetsya  nachinat'  vypolnenie
posleduyushchih  operacij chteniya ili zapisi. YAdro sbrasyvaet eto smeshchenie v 0 vo
vremya otkrytiya fajla, imeya v vidu, chto ishodnaya operaciya chteniya  ili  zapisi
po  umolchaniyu  budet proizvodit'sya s nachala fajla. S drugoj storony, process
mozhet otkryt' fajl v rezhime zapisi v konec, v etom sluchae yadro ustanavlivaet
znachenie smeshcheniya, ravnoe razmeru fajla. YAdro vydelyaet zapis' v lichnoj (zak-
rytoj) tablice v adresnom prostranstve zadachi, vydelennom processu  (tablica
eta  nazyvaetsya tablicej pol'zovatel'skih deskriptorov fajlov), i zapominaet
ukazatel' na etu zapis'. Ukazatelem vystupaet deskriptor fajla, vozvrashchaemyj
pol'zovatelyu. Zapis' v tablice pol'zovatel'skih fajlov ukazyvaet na zapis' v
global'noj tablice fajlov.


---------------------------------------
(*) Vse sistemnye funkcii vozvrashchayut v sluchae neudachnogo zaversheniya kod  -1.
    Kod  vozvrata,  ravnyj  -1, bol'she ne budet upominat'sya pri rassmotrenii
    sintaksisa vyzova sistemnyh funkcij.



                                     86

    +------------------------------------------------------------+
    | algoritm open                                              |
    | vhodnaya informaciya:  imya fajla                             |
    |                      rezhim otkrytiya                        |
    |                      prava dostupa (pri sozdanii fajla)    |
    | vyhodnaya informaciya: deskriptor fajla                      |
    | {                                                          |
    |    prevratit' imya fajla v identifikator indeksa (algoritm  |
    |     namei);                                                |
    |    esli (fajl ne sushchestvuet ili k nemu ne razreshen dostup) |
    |         vozvratit' (kod oshibki);                           |
    |    vydelit' dlya indeksa zapis' v tablice fajlov, iniciali- |
    |     zirovat' schetchik, smeshchenie;                            |
    |    vydelit' zapis' v tablice pol'zovatel'skih deskriptorov |
    |     fajla, ustanovit' ukazatel' na zapis' v tablice fajlov;|
    |    esli (rezhim otkrytiya podrazumevaet usechenie fajla)      |
    |         osvobodit' vse bloki fajla (algoritm free);        |
    |    snyat' blokirovku (s indeksa);  /* indeks zablokirovan   |
    |                                      vyshe, v algoritme     |
    |                                      namei */              |
    |    vozvratit' (pol'zovatel'skij deskriptor fajla);         |
    | }                                                          |
    +------------------------------------------------------------+

               Risunok 5.2. Algoritm otkrytiya fajla


    Predpolozhim, chto process, otkryvaya fajl "/etc/passwd" dvazhdy,  odin  raz
tol'ko  dlya  chteniya i odin raz tol'ko dlya zapisi, i odnazhdy fajl "local" dlya
chteniya i dlya zapisi (**), vypolnyaet sleduyushchij nabor operatorov:

    fd1 = open("/etc/passwd",O_RDONLY);
    fd2 = open("local",O_RDWR);
    fd3 = open("/etc/passwd",O_WRONLY);

    Na Risunke 5.3 pokazana vzaimosvyaz' mezhdu  tablicej  indeksov,  tablicej
fajlov  i tablicej pol'zovatel'skih deskriptorov fajla. Kazhdyj vyzov funkcii
open vozvrashchaet processu deskriptor fajla, a sootvetstvuyushchaya zapis' v tabli-
ce pol'zovatel'skih deskriptorov fajla ukazyvaet na unikal'nuyu zapis' v tab-
lice fajlov yadra, pust' dazhe odin i tot zhe fajl ("/etc/passwd")  otkryvaetsya
dvazhdy.
   Zapisi v tablice fajlov dlya vseh ekzemplyarov odnogo i togo  zhe  otkrytogo
fajla ukazyvayut na odnu zapis' v tablice indeksov, hranyashchihsya v pamyati. Pro-
cess mozhet obrashchat'sya k fajlu "/etc/passwd" s chteniem ili zapis'yu, no tol'ko
cherez deskriptory fajla, imeyushchie znacheniya 3 i 5 (sm. risunok).YAdro zapomina-
et razreshenie na chtenie ili zapis' v fajl v stroke tablicy fajlov,vydelennoj
vo  vremya vypolneniya funkcii open. Predpolozhim, chto vtoroj process vypolnyaet
sleduyushchij nabor operatorov:


---------------------------------------
(**) V opisanii vyzova sistemnoj funkcii open soderzhatsya tri parametra (tre-
     tij ispol'zuetsya pri otkrytii v rezhime sozdaniya), no programmisty obych-
     no ispol'zuyut tol'ko pervye dva iz nih. Kompilyator s yazyka Si ne prove-
     ryaet pravil'nost' kolichestva parametrov. V sisteme pervye dva parametra
     i tretij (s lyubym "musorom", chto by ni proizoshlo  v  steke)  peredayutsya
     obychno  yadru. YAdro ne proveryaet nalichie tret'ego parametra, esli tol'ko
     neobhodimost' v nem ne vytekaet iz znacheniya vtorogo parametra, chto poz-
     volyaet programmistam ukazat' tol'ko dva parametra.

                                     87

    tablica pol'zova-
    tel'skih deskrip-
       torov fajla        tablica fajlov        tablica indeksov
       +---------+        +------------+        +--------------+
      0|         |        |            |        |       -      |
       +---------+        |            |        |       -      |
      1|         |        |            |        |       -      |
       +---------+        +------------+        |       -      |
      2|         |        |      -     |        |       -      |
       +---------+        |      -     |        |       -      |
      3|     ----+----+   |      -     |        |       -      |
       +---------+    |   |      -     |        +--------------+
      4|     ----+---+|   |      -     |  +---->| schet-        |
       +---------+   ||   |      -     |  |+--->| chik  (/etc/  |
      5|     ----+--+||   +------------+  ||    |  2    passwd)|
       +---------+  |||   | schet-      |  ||    +--------------+
      6|         |  ||+-->| chik  CHtenie+--+|    |       -      |
       +---------+  ||    |  1         |   |    |       -      |
      7|         |  ||    +------------+   |    |       -      |
       +---------+  ||    |      -     |   |    |       -      |
       |    -    |  ||    |      -     |   |    |       -      |
       +---------+  ||    +------------+   |    |       -      |
                    ||    | schet-  CHte-|   |    |       -      |
                    |+--->| chik    nie-+---|-+  |       -      |
                    |     |  1   Zapis'|   | |  |       -      |
                    |     +------------+   | |  |       -      |
                    |     |      -     |   | |  +--------------+
                    |     |      -     |   | |  | schet-        |
                    |     |      -     |   | +->| chik   (local)|
                    |     |      -     |   |    |  1           |
                    |     |      -     |   |    +--------------+
                    |     +------------+   |    |       -      |
                    |     | schet-      |   |    |       -      |
                    +---->| chik  Zapis'+---+    |       -      |
                          |  1         |        |       -      |
                          +------------+        |       -      |
                          |      -     |        |       -      |
                          |      -     |        |       -      |
                          +------------+        +--------------+


            Risunok 5.3. Struktury dannyh posle otkrytiya


    fd1 = open("/etc/passwd",O_RDONLY);
    fd2 = open("private",O_RDONLY);

Na Risunke 5.4 pokazana vzaimosvyaz' mezhdu sootvetstvuyushchimi strukturami  dan-
nyh, kogda oba processa (i bol'she nikto) imeyut otkrytye fajly. Snova rezul'-
tatom  kazhdogo vyzova funkcii open yavlyaetsya vydelenie unikal'noj tochki vhoda
v tablice pol'zovatel'skih deskriptorov fajla i v tablice fajlov yadra, i yad-
ro hranit ne bolee odnoj zapisi na kazhdyj fajl v tablice indeksov, razmeshchen-
nyh v pamyati.
    Zapis' v tablice pol'zovatel'skih deskriptorov fajla po umolchaniyu hranit
smeshchenie v fajle do adresa sleduyushchej operacii vvodavyvoda i ukazyvaet nepos-
redstvenno na tochku vhoda v tablice indeksov dlya fajla,  ustranyaya  neobhodi-
most'  v  otdel'noj  tablice fajlov yadra. Vysheprivedennye primery pokazyvayut
vzaimosvyaz' mezhdu zapisyami tablicy pol'zovatel'skih deskriptorov fajla i za-


                                     88

    tablicy pol'zova-
    tel'skih deskrip-
       torov fajla
       (process A)        tablica fajlov        tablica indeksov
       +---------+        +------------+        +--------------+
      0|         |        |            |        |       -      |
       +---------+        |            |        |       -      |
      1|         |        |            |        |       -      |
       +---------+        +------------+        |       -      |
      2|         |        |      -     |        |       -      |
       +---------+        |      -     |        |       -      |
      3|     ----+----+   |      -     |        |       -      |
       +---------+    |   |      -     |        +--------------+
      4|     ----+---+|   |      -     |  +---->| schet-        |
       +---------+   ||   |      -     |  |+--->| chik  (/etc/  |
      5|     ----+--+||   +------------+  ||+-->|  3    passwd)|
       +---------+  |||   | schet-      |  |||   +--------------+
       |    -    |  ||+-->| chik  CHtenie+--+||   |       -      |
       |    -    |  ||    |  1         |   ||   |       -      |
       |    -    |  ||    +------------+   ||   |       -      |
       +---------+  ||    |      -     |   ||   |       -      |
                    ||    |      -     |   ||   |       -      |
       (process B)  ||    |      -     |   ||   |       -      |
       +---------+  ||    |      -     |   ||   |       -      |
      0|         |  ||    +------------+   ||   |       -      |
       +---------+  ||    | schet-  CHte-|   ||   |       -      |
      1|         |  |+--->| chik    nie-+---||+  |       -      |
       +---------+  |     |  1   Zapis'|   |||  |       -      |
      2|         |  |     +------------+   |||  |       -      |
       +---------+  |     |      -     |   |||  +--------------+
      3|     ----+--|--+  |      -     |   |||  | schet-        |
       +---------+  |  |  |      -     |   ||+->| chik   (local)|
      4|     ----+-+|  |  |      -     |   ||   |  1           |
       +---------+ ||  |  |      -     |   ||   +--------------+
      5|         | ||  |  |      -     |   ||   |       -      |
       +---------+ ||  |  +------------+   ||   |       -      |
       |    -    | ||  |  | schet-      |   ||   |       -      |
       |    -    | ||  +->| chik  CHtenie+---+|   |       -      |
       |    -    | ||     |  1         |    |   |       -      |
       +---------+ ||     +------------+    |   |       -      |
                   ||     |      -     |    |   |       -      |
                   ||     |      -     |    |   +--------------+
                   ||     |      -     |    |   | schet-        |
                   ||     +------------+    |+->| chik (private)|
                   ||     | schet-      |    ||  |  1           |
                   |+---->| chik  Zapis'+----+|  +--------------+
                   |      |  1         |     |  |       -      |
                   |      +------------+     |  |       -      |
                   |      |      -     |     |  +--------------+
                   |      |      -     |     |
                   |      +------------+     |
                   |      | schet-      |     |
                   +----->| chik  CHtenie+-----+
                          |  1         |
                          +------------+

    Risunok 5.4.  Struktury dannyh posle togo,  kak dva  processa
                  proizveli otkrytie fajlov


                                     89



pisyami v tablice fajlov yadra tipa "odin k odnomu". Tompson, odnako,  otmecha-
et, chto im byla realizovana tablica fajlov kak otdel'naya struktura, pozvolya-
yushchaya  sovmestno  ispol'zovat'  odin  i  tot zhe ukazatel' smeshcheniya neskol'kim
pol'zovatel'skim deskriptoram fajla (sm. [Thompson 78], str.1943). V sistem-
nyh funkciyah dup i fork, rassmatrivaemyh v razdelah 5.13 i 7.1,  pri  rabote
so strukturami dannyh dopuskaetsya takoe sovmestnoe ispol'zovanie.

    Pervye  tri pol'zovatel'skih deskriptora (0, 1 i 2) imenuyutsya deskripto-
rami fajlov: standartnogo vvoda, standartnogo vyvoda  i  standartnogo  fajla
oshibok. Processy v sisteme UNIX po dogovorennosti ispol'zuyut deskriptor faj-
la standartnogo vvoda pri chtenii vvodimoj informacii, deskriptor fajla stan-
dartnogo  vyvoda  pri  zapisi vyvodimoj informacii i deskriptor standartnogo
fajla oshibok dlya zapisi soobshchenij ob oshibkah. V operacionnoj sisteme net ni-
kakogo ukazaniya na to, chto eti  deskriptory  fajlov  yavlyayutsya  special'nymi.
Gruppa pol'zovatelej mozhet uslovit'sya o tom, chto fajlovye deskriptory, imeyu-
shchie znacheniya 4, 6 i 11, yavlyayutsya special'nymi, no bolee estestvenno nachinat'
otschet  s  0 (kak v yazyke Si). Prinyatie soglasheniya srazu vsemi pol'zovatel'-
skimi programmami oblegchit svyaz' mezhdu nimi pri ispol'zovanii kanalov, v chem
my ubedimsya v dal'nejshem, izuchaya glavu 7. Obychno operatorskij terminal  (sm.
glavu  10) sluzhit i v kachestve standartnogo vvoda, i v kachestve standartnogo
vyvoda i v kachestve standartnogo ustrojstva vyvoda soobshchenij ob oshibkah.




    Sintaksis vyzova sistemnoj funkcii read (chitat'):
    number = read(fd,buffer,count)

gde fd - deskriptor fajla, vozvrashchaemyj funkciej open, buffer - adres struk-
tury dannyh v pol'zovatel'skom processe,  gde  budut  razmeshchat'sya  schitannye
dannye  v sluchae uspeshnogo zaversheniya vypolneniya funkcii read, count - koli-
chestvo bajt, kotorye pol'zovatelyu nuzhno prochitat', number - kolichestvo  fak-
ticheski prochitannyh bajt. Na Risunke 5.5 priveden algoritm read, vypolnyayushchij
chtenie  obychnogo  fajla.  YAdro obrashchaetsya v tablice fajlov k zapisi, kotoraya
sootvetstvuet znacheniyu pol'zovatel'skogo deskriptora fajla, sleduya
za ukazatelem (sm. Risunok 5.3). Zatem ono ustanavlivaet znacheniya neskol'kih
parametrov vvoda-vyvoda v adresnom prostranstve processa (Risunok 5.6),  tem
samym  ustranyaya neobhodimost' v ih peredache v kachestve parametrov funkcii. V
chastnosti, yadro ukazyvaet v kachestve rezhima vvoda-vyvoda "chtenie",  ustanav-
livaet flag, svidetel'stvuyushchij o tom, chto vvod-vyvod napravlyaetsya v adresnoe
prostranstvo  pol'zovatelya, znachenie polya schetchika bajtov priravnivaet koli-
chestvu bajt, kotorye budut prochitany, ustanavlivaet adres  pol'zovatel'skogo
bufera dannyh i, nakonec, znachenie smeshcheniya (iz tablicy fajlov), ravnoe sme-
shcheniyu  v  bajtah  vnutri fajla do mesta, otkuda nachinaetsya vvod-vyvod. Posle
togo, kak yadro ustanovit znacheniya parametrov vvoda-vyvoda v adresnom  prost-
ranstve  processa,  ono obrashchaetsya k indeksu, ispol'zuya ukazatel' iz tablicy
fajlov, i blokiruet ego prezhde, chem nachat' chtenie iz fajla.

    Zatem v algoritme nachinaetsya cikl, vypolnyayushchijsya do teh por, poka opera-
ciya chteniya ne budet proizvedena do konca. YAdro preobrazuet smeshchenie v bajtah
vnutri fajla v nomer bloka, ispol'zuya al-







                                     90
    +------------------------------------------------------------+
    | algoritm read                                              |
    | vhodnaya informaciya:  pol'zovatel'skij deskriptor fajla     |
    |                      adres bufera v pol'zovatel'skom pro-  |
    |                      cesse                                 |
    |                      kolichestvo bajt, kotorye nuzhno prochi- |
    |                      tat'                                  |
    | vyhodnaya informaciya: kolichestvo bajt, skopirovannyh v pol'-|
    |                      zovatel'skoe prostranstvo             |
    | {                                                          |
    |    obratit'sya k zapisi v tablice fajlov po znacheniyu pol'zo-|
    |     vatel'skogo deskriptora fajla;                         |
    |    proverit' dostupnost' fajla;                            |
    |    ustanovit' parametry v adresnom prostranstve processa,  |
    |     ukazav adres pol'zovatelya, schetchik bajtov, parametry   |
    |     vvoda-vyvoda dlya pol'zovatelya;                         |
    |    poluchit' indeks po zapisi v tablice fajlov;             |
    |    zablokirovat' indeks;                                   |
    |    ustanovit' znachenie smeshcheniya v bajtah dlya adresnogo     |
    |     prostranstva processa po znacheniyu smeshcheniya v tablice   |
    |     fajlov;                                                |
    |    vypolnit' (poka znachenie schetchika bajtov ne stanet udov-|
    |     letvoritel'nym)                                        |
    |    {                                                       |
    |       prevratit' smeshchenie v fajle v nomer diskovogo bloka  |
    |        (algoritm bmap);                                    |
    |       vychislit' smeshchenie vnutri bloka i kolichestvo bajt,   |
    |        kotorye budut prochitany;                            |
    |       esli (kolichestvo bajt dlya chteniya ravno 0)            |
    |          /* popytka chteniya konca fajla */                  |
    |          prervat'sya;      /* vyhod iz cikla */             |
    |       prochitat' blok (algoritm breada, esli proizvoditsya   |
    |        chtenie s prodvizheniem, i algoritm bread - v protiv- |
    |        nom sluchae);                                        |
    |       skopirovat' dannye iz sistemnogo bufera po adresu    |
    |        pol'zovatelya;                                       |
    |       skorrektirovat' znacheniya polej v adresnom prostran-  |
    |        stve processa, ukazyvayushchie smeshchenie v bajtah vnutri |
    |        fajla, kolichestvo prochitannyh bajt i adres dlya pe-  |
    |        redachi v prostranstvo pol'zovatelya;                 |
    |       osvobodit' bufer;     /* zablokirovannyj v algoritme |
    |                                bread */                    |
    |    }                                                       |
    |    razblokirovat' indeks;                                  |
    |    skorrektirovat' znachenie smeshcheniya v tablice fajlov dlya  |
    |     sleduyushchej operacii chteniya;                             |
    |    vozvratit' (obshchee chislo prochitannyh bajt);              |
    | }                                                          |
    +------------------------------------------------------------+
                Risunok 5.5. Algoritm chteniya iz fajla

    +------------------------------------------------------+
    | mode     chtenie ili zapis'                           |
    | count    kolichestvo bajt dlya chteniya ili zapisi       |
    | offset   smeshchenie v bajtah vnutri fajla              |
    | address  adres mesta, kuda budut kopirovat'sya dannye,|
    |          v pamyati pol'zovatelya ili yadra              |
    | flag     otnoshenie adresa k pamyati pol'zovatelya ili  |
    |          k pamyati yadra                               |
    +------------------------------------------------------+
  Risunok 5.6.  Parametry vvoda-vyvoda, hranyashchiesya v prostranstve processa
                                     91

goritm bmap, i vychislyaet smeshchenie vnutri bloka do mesta, otkuda sleduet  na-
chat'  vvod-vyvod, a takzhe kolichestvo bajt, kotorye budut prochitany iz bloka.
Posle schityvaniya bloka v bufer, vozmozhno, s prodvizheniem (algoritmy bread  i
breada) yadro kopiruet dannye iz bloka po naznachennomu adresu v pol'zovatel'-
skom processe. Ono korrektiruet parametry vvoda-vyvoda v adresnom prostrans-
tve  processa v sootvetstvii s kolichestvom prochitannyh bajt, uvelichivaya zna-
chenie smeshcheniya v bajtah vnutri fajla i adres mesta v  pol'zovatel'skom  pro-
cesse, kuda budet dostavlena sleduyushchaya porciya dannyh, i umen'shaya chislo bajt,
kotorye neobhodimo prochitat', chtoby vypolnit' zapros pol'zovatelya. Esli zap-
ros  pol'zovatelya ne udovletvoren, yadro povtoryaet ves' cikl, preobrazuya sme-
shchenie v bajtah vnutri fajla v nomer bloka, schityvaya blok s diska v sistemnyj
bufer, kopiruya dannye iz bufera v pol'zovatel'skij process, osvobozhdaya bufer
i korrektiruya znacheniya parametrov vvoda-vyvoda v adresnom prostranstve  pro-
cessa.  Cikl  zavershaetsya, libo kogda yadro vypolnit zapros pol'zovatelya pol-
nost'yu, libo kogda v fajle bol'she ne budet dannyh, libo esli yadro  obnaruzhit
oshibku  pri  chtenii dannyh s diska ili pri kopirovanii dannyh v prostranstvo
pol'zovatelya. YAdro korrektiruet znachenie smeshcheniya v tablice fajlov  v  soot-
vetstvii  s kolichestvom fakticheski prochitannyh bajt; poetomu uspeshnoe vypol-
nenie operacij chteniya vyglyadit kak  posledovatel'noe  schityvanie  dannyh  iz
fajla. Sistemnaya operaciya lseek (razdel 5.6) ustanavlivaet znachenie smeshcheniya
v tablice fajlov i izmenyaet poryadok, v kotorom process chitaet ili zapisyvaet
dannye v fajle.

    +------------------------------------------------------+
    | #include                                    |
    | main()                                               |
    | {                                                    |
    |     int fd;                                          |
    |     char lilbuf[20],bigbuf[1024];                    |
    |                                                      |
    |     fd = open("/etc/passwd",O_RDONLY);               |
    |     read(fd,lilbuf,20);                              |
    |     read(fd,bigbuf,1024);                            |
    |     read(fd,lilbuf,20);                              |
    | }                                                    |
    +------------------------------------------------------+

         Risunok 5.7. Primer programmy chteniya iz fajla


    Rassmotrim programmu, privedennuyu na Risunke 5.7. Funkciya open vozvrashcha-
et deskriptor fajla, kotoryj pol'zovatel' zasylaet v peremennuyu fd i ispol'-
zuet  v posleduyushchih vyzovah funkcii read. Vypolnyaya funkciyu read, yadro prove-
ryaet, pravil'no li zadan parametr "deskriptor fajla", a takzhe  byl  li  fajl
predvaritel'no  otkryt  processom  dlya chteniya. Ono sohranyaet znachenie adresa
pol'zovatel'skogo bufera, kolichestvo schityvaemyh bajt i nachal'noe smeshchenie v
bajtah vnutri fajla (sootvetstvenno: lilbuf, 20 i 0), v prostranstve proces-
sa. V rezul'tate vychislenij okazyvaetsya, chto nulevoe znachenie smeshcheniya soot-
vetstvuet nulevomu bloku fajla, i yadro vozvrashchaet tochku vhoda v indeks,  so-
otvetstvuyushchuyu  nulevomu  bloku. Predpolagaya, chto takoj blok sushchestvuet, yadro
schityvaet polnyj blok razmerom 1024 bajta v bufer, no po adresu lilbuf kopi-
ruet tol'ko 20 bajt. Ono uvelichivaet smeshchenie vnutri  prostranstva  processa
na 20 bajt i sbrasyvaet schetchik dannyh v 0. Poskol'ku operaciya read vypolni-
las',  yadro  pereustanavlivaet znachenie smeshcheniya v tablice fajlov na 20, tak
chto posleduyushchie operacii chteniya iz fajla s dannym  deskriptorom  nachnutsya  s
mesta, raspolozhennogo so smeshcheniem 20 bajt ot nachala fajla, a sistemnaya fun-
kciya vozvrashchaet chislo bajt, fakticheski prochitannyh, t.e. 20.
    Pri povtornom vyzove funkcii read yadro vnov' proveryaet korrektnost' uka-
zaniya  deskriptora i nalichie sootvetstvuyushchego fajla, otkrytogo processom dlya

                                     92

chteniya, poskol'ku ono nikak ne mozhet uznat', chto zapros pol'zovatelya na chte-
nie kasaetsya togo zhe samogo fajla, sushchestvovanie kotorogo  bylo  ustanovleno
vo  vremya  poslednego vyzova funkcii. YAdro sohranyaet v prostranstve processa
pol'zovatel'skij adres bigbuf, kolichestvo bajt, kotorye nuzhno prochitat' pro-
cessu (1024), i nachal'noe smeshchenie v fajle (20), vzyatoe iz  tablicy  fajlov.
YAdro  preobrazuet smeshchenie vnutri fajla v nomer diskovogo bloka, kak ran'she,
i schityvaet blok. Esli mezhdu vyzovami funkcii read proshlo  neprodolzhitel'noe
vremya, est' shansy, chto blok nahoditsya v bufernom keshe. Odnako, yadro ne mozhet
polnost'yu  udovletvorit'  zapros  pol'zovatelya na chtenie za schet soderzhimogo
bufera, poskol'ku tol'ko 1004 bajta iz 1024 dlya dannogo zaprosa nahodyatsya  v
bufere. Poetomu ono kopiruet ostavshiesya 1004 bajta iz bufera v pol'zovatel'-
skuyu strukturu dannyh bigbuf i korrektiruet parametry v prostranstve proces-
sa takim obrazom, chtoby sleduyushchij shag cikla chteniya nachinalsya v fajle s bajta
1024, pri etom dannye sleduet kopirovat' po adresu bajta 1004 v bigbuf v ob-
®eme 20 bajt, chtoby udovletvorit' zapros na chtenie.
    Teper'  yadro  perehodit  k nachalu cikla, soderzhashchegosya v algoritme read.
Ono preobrazuet smeshchenie v bajtah (1024) v nomer logicheskogo bloka (1),  ob-
rashchaetsya ko vtoromu bloku pryamoj adresacii, nomer kotorogo hranitsya v indek-
se,  i otyskivaet tochnyj diskovyj blok, iz kotorogo budet proizvodit'sya chte-
nie. YAdro schityvaet blok iz bufernogo kesha ili s diska, esli v  keshe  dannyj
blok otsutstvuet. Nakonec, ono kopiruet 20 bajt iz bufera po utochnennomu ad-
resu v pol'zovatel'skij process. Prezhde chem vyjti iz sistemnoj funkcii, yadro
ustanavlivaet  znachenie  polya smeshcheniya v tablice fajlov ravnym 1044, to est'
ravnym znacheniyu smeshcheniya v bajtah do mesta, kuda budet proizvodit'sya sleduyu-
shchee obrashchenie. V poslednem vyzove funkcii read iz primera yadro  vedet  sebya,
kak i v pervom obrashchenii k funkcii, za isklyucheniem togo, chto chtenie iz fajla
v  dannom  sluchae nachinaetsya s bajta 1044, tak kak imenno eto znachenie budet
obnaruzheno v pole smeshcheniya toj zapisi tablicy fajlov, kotoraya  sootvetstvuet
ukazannomu deskriptoru.
    Primer  pokazyvaet, naskol'ko vygodno dlya zaprosov vvoda-vyvoda rabotat'
s dannymi, nachinayushchimisya na granicah blokov fajlovoj sistemy i imeyushchimi raz-
mer, kratnyj razmeru bloka. |to pozvolyaet yadru izbegat' dopolnitel'nyh  ite-
racij  pri  vypolnenii cikla v algoritme read i vseh vytekayushchih posledstvij,
svyazannyh s dopolnitel'nymi obrashcheniyami k indeksu v  poiskah  nomera  bloka,
kotoryj  soderzhit  dannye, i s konkurenciej za ispol'zovanie bufernogo pula.
Biblioteka standartnyh modulej vvoda-vyvoda  sozdana  takim  obrazom,  chtoby
skryt' ot pol'zovatelej razmery buferov yadra; ee ispol'zovanie pozvolyaet iz-
bezhat' poter' proizvoditel'nosti, prisushchih processam, rabotayushchim s nebol'shi-
mi porciyami dannyh, iz-za chego ih funkcionirovanie na urovne fajlovoj siste-
my neeffektivno (sm. uprazhnenie 5.4).
    Vypolnyaya  cikl chteniya, yadro opredelyaet, yavlyaetsya li fajl ob®ektom chteniya
s prodvizheniem: esli process schityvaet posledovatel'no dva bloka, yadro pred-
polagaet, chto vse ocherednye operacii budut proizvodit' posledovatel'noe chte-
nie, do teh por, poka ne budet utverzhdeno obratnoe. Na kazhdom shage cikla yad-
ro zapominaet nomer sleduyushchego logicheskogo bloka v kopii indeksa, hranyashchejsya
v pamyati, i na sleduyushchem shage sravnivaet nomer tekushchego logicheskogo bloka so
znacheniem, zapomnennym ranee. Esli eti nomera ravny,  yadro  vychislyaet  nomer
fizicheskogo bloka dlya chteniya s prodvizheniem i sohranyaet eto znachenie v pros-
transtve  processa  dlya  ispol'zovaniya  v algoritme breada. Konechno zhe, poka
process ne schital konec bloka, yadro ne zapustit algoritm chteniya s  prodvizhe-
niem dlya sleduyushchego bloka.
    Obrativshis'  k  Risunku 4.9, vspomnim, chto nomera nekotoryh blokov v in-
dekse ili v blokah kosvennoj adresacii mogut imet' nulevoe  znachenie,  pust'
dazhe  nomera  posleduyushchih blokov i nenulevye. Esli process popytaetsya prochi-
tat' dannye iz takogo bloka, yadro vypolnit zapros, vydelyaya proizvol'nyj  bu-
fer  v  cikle read, ochishchaya ego soderzhimoe i kopiruya dannye iz nego po adresu
pol'zovatelya. |tot sluchaj ne imeet nichego obshchego s tem sluchaem,  kogda  pro-
cess obnaruzhivaet konec fajla, govoryashchij o tom, chto posle etogo mesta zapis'
informacii  nikogda ne proizvodilas'. Obnaruzhiv konec fajla, yadro ne vozvra-

                                     93

shchaet processu nikakoj informacii (sm. uprazhnenie 5.1).
    Kogda process vyzyvaet sistemnuyu funkciyu read, yadro blokiruet indeks  na
vremya vypolneniya vyzova. Vposledstvii, etot process mozhet priostanovit'sya vo
vremya  chteniya  iz bufera, associirovannogo s dannymi ili s blokami kosvennoj
adresacii v indekse. Esli eshche odnomu processu dat' vozmozhnost' vnosit' izme-
neniya v fajl v to vremya, kogda pervyj process  priostanovlen,  funkciya  read
mozhet  vozvratit' nesoglasovannye dannye. Naprimer, process mozhet schitat' iz
fajla neskol'ko blokov; esli on priostanovilsya vo vremya chteniya pervogo  blo-
ka,  a  vtoroj  process  sobiralsya vesti zapis' v drugie bloki, vozvrashchaemye
dannye budut soderzhat' starye dannye vperemeshku s novymi. Takim obrazom, in-
deks ostaetsya zablokirovannym na vse vremya vypolneniya  vyzova  funkcii  read
dlya  togo, chtoby processy mogli imet' celostnoe videnie fajla, to est' vide-
nie togo obraza, kotoryj byl u fajla pered vyzovom funkcii.
    YAdro mozhet vygruzhat' process, vedushchij chtenie, v rezhim  zadachi  na  vremya
mezhdu  dvumya vyzovami funkcij i planirovat' zapusk drugih processov. Tak kak
po okonchanii vypolneniya sistemnoj funkcii s  indeksa  snimaetsya  blokirovka,
nichto  ne meshaet drugim processam obrashchat'sya k fajlu i izmenyat' ego soderzhi-
moe. So storony sistemy bylo by nespravedlivo derzhat' indeks zablokirovannym
vse vremya ot momenta, kogda process otkryl fajl, i do  togo  momenta,  kogda
fajl budet zakryt etim processom, poskol'ku togda odin process budet derzhat'
vse vremya fajl otkrytym, tem samym ne davaya drugim processam vozmozhnosti ob-
ratit'sya  k fajlu. Esli fajl imeet imya "/etc/ passwd", to est' yavlyaetsya faj-
lom, ispol'zuemym v processe registracii dlya proverki pol'zovatel'skogo  pa-
rolya, odin pol'zovatel' mozhet umyshlenno (ili, vozmozhno, neumyshlenno) vospre-
pyatstvovat'  registracii  v sisteme vseh ostal'nyh pol'zovatelej. CHtoby pre-
dotvratit' vozniknovenie podobnyh problem, yadro snimaet s indeksa blokirovku
po okonchanii vypolneniya kazhdogo vyzova sistemnoj funkcii,  ispol'zuyushchej  in-
deks. Esli vtoroj process vneset izmeneniya v fajl mezhdu dvumya vyzovami funk-
cii  read,  proizvodimymi  pervym  processom, pervyj process mozhet prochitat'
nepredvidennye dannye, odnako struktury dannyh yadra sohranyat  svoyu  soglaso-
vannost'.
    Predpolozhim,  k  primeru, chto yadro vypolnyaet dva processa, konkuriruyushchie

    +------------------------------------------------------------+
    | #include                                          |
    | /* process A */                                            |
    | main()                                                     |
    | {                                                          |
    |     int fd;                                                |
    |     char buf[512];                                         |
    |     fd = open("/etc/passwd",O_RDONLY);                     |
    |     read(fd,buf,sizeof(buf));          /* chtenie1 */       |
    |     read(fd,buf,sizeof(buf));          /* chtenie2 */       |
    | }                                                          |
    |                                                            |
    | /* process B */                                            |
    | main()                                                     |
    | {                                                          |
    |     int fd,i;                                              |
    |     char buf[512];                                         |
    |     for (i = 0; i < sizeof(buf); i++)                      |
    |         buf[i] = 'a';                                      |
    |     fd = open("/etc/passwd",O_WRONLY);                     |
    |     write(fd,buf,sizeof(buf));         /* zapis'1 */       |
    |     write(fd,buf,sizeof(buf));         /* zapis'2 */       |
    | }                                                          |
    +------------------------------------------------------------+

            Risunok 5.8. Processy, vedushchie chtenie i zapis'

                                     94



mezhdu soboj (Risunok 5.8). Esli dopustit', chto oba processa vypolnyayut opera-
ciyu open do togo, kak lyuboj iz  nih  vyzyvaet  sistemnuyu  funkciyu  read  ili
write,  yadro mozhet vypolnyat' funkcii chteniya i zapisi v lyuboj iz shesti posle-
dovatel'nostej: chtenie1, chtenie2, zapis'1, zapis'2,  ili  chtenie1,  zapis'1,
chtenie2,  zapis'2,  ili chtenie1, zapis'1, zapis'2, chtenie2 i t.d. Sostav in-
formacii, schityvaemoj processom A, zavisit ot posledovatel'nosti, v  kotoroj
sistema  vypolnyaet funkcii, vyzyvaemye dvumya processami; sistema ne garanti-
ruet, chto dannye v fajle ostanutsya takimi zhe, kakimi oni byli posle otkrytiya
fajla. Ispol'zovanie vozmozhnosti zahvata fajla i zapisej (razdel 5.4) pozvo-
lyaet processu garantirovat' sohranenie celostnosti fajla posle ego otkrytiya.

    Nakonec, programma na Risunke 5.9 pokazyvaet, kak process  mozhet  otkry-
vat' fajl bolee odnogo raza i chitat' iz nego, ispol'zuya raznye fajlovye des-
kriptory.  YAdro rabotaet so znacheniyami smeshchenij v tablice fajlov, associiro-
vannymi s dvumya fajlovymi deskriptorami, nezavisimo, i poetomu massivy  buf1
i  buf2 budut po zavershenii vypolneniya processa identichny drug drugu pri us-
lovii, chto ni  odin  process  v  eto  vremya  ne  proizvodil  zapis'  v  fajl
"/etc/passwd".


    5.3 WRITE

Sintaksis vyzova sistemnoj funkcii write (pisat'): number = write(fd,buffer,count); gde peremennye fd, buffer, count i number imeyut tot zhe smysl, chto i dlya vy- zova sistemnoj funkcii read. Algoritm zapisi v obychnyj fajl pohozh na algo- ritm chteniya iz obychnogo fajla. Odnako, esli v fajle otsutstvuet blok, soot- vetstvuyushchij smeshcheniyu v bajtah do mesta, kuda dolzhna proizvodit'sya zapis', yadro vydelyaet blok, ispol'zuya algoritm alloc, i prisvaivaet emu nomer v so- otvetstvii s tochnym ukazaniem mesta v tablice soderzhimogo indeksa. Esli sme- shchenie v bajtah sovpadaet so smeshcheniem dlya bloka kosvennoj adresacii, yadru, vozmozhno, pridetsya vydelit' neskol'ko blokov dlya ispol'zovaniya ih v kachestve blokov kosvennoj adresacii i informaci- +------------------------------------------------------------+ | #include | | main() | | { | | int fd1,fd2; | | char buf1[512],buf2[512]; | | | | fd1 = open("/etc/passwd",O_RDONLY); | | fd2 = open("/etc/passwd",O_RDONLY); | | read(fd1,buf1,sizeof(buf1)); | | read(fd2,buf2,sizeof(buf2)); | | } | +------------------------------------------------------------+ Risunok 5.9. CHtenie iz fajla s ispol'zovaniem dvuh deskriptorov onnyh blokov. Indeks blokiruetsya na vse vremya vypolneniya funkcii write, tak kak yadro mozhet izmenit' indeks, vydelyaya novye bloki; razreshenie drugim pro- cessam obrashchat'sya k fajlu mozhet razrushit' indeks, esli neskol'ko processov vydelyayut bloki odnovremenno, ispol'zuya odni i te zhe znacheniya smeshchenij. Kogda zapis' zavershaetsya, yadro korrektiruet razmer fajla v indekse, esli fajl uve- 95 lichilsya v razmere. Predpolozhim, k primeru, chto process zapisyvaet v fajl bajt s nomerom 10240, naibol'shim nomerom sredi uzhe zapisannyh v fajle. Obrativshis' k bajtu v fajle po algoritmu bmap, yadro obnaruzhit, chto v fajle otsutstvuet ne tol'ko sootvetstvuyushchij etomu bajtu blok, no takzhe i nuzhnyj blok kosvennoj adresa- cii. YAdro naznachaet diskovyj blok v kachestve bloka kosvennoj adresacii i za- pisyvaet nomer bloka v kopii indeksa, hranyashchejsya v pamyati. Zatem ono vydelya- et diskovyj blok pod dannye i zapisyvaet ego nomer v pervuyu poziciyu vnov' sozdannogo bloka kosvennoj adresacii. Tak zhe, kak v algoritme read, yadro vhodit v cikl, zapisyvaya na disk po odnomu bloku na kazhdoj iteracii. Pri etom na kazhdoj iteracii yadro opredelya- et, budet li proizvodit'sya zapis' celogo bloka ili tol'ko ego chasti. Esli zapisyvaetsya tol'ko chast' bloka, yadro v pervuyu ochered' schityvaet blok s dis- ka dlya togo, chtoby ne zateret' te chasti, kotorye ostalis' bez izmenenij, a esli zapisyvaetsya celyj blok, yadru ne nuzhno chitat' ves' blok, tak kak v lyu- bom sluchae ono zatret predydushchee soderzhimoe bloka. Zapis' osushchestvlyaetsya poblochno, odnako yadro ispol'zuet otlozhennuyu zapis' (razdel 3.4) dannyh na disk, zapominaya ih v keshe na sluchaj, esli oni ponadobyatsya vskore drugomu processu dlya chteniya ili zapisi, a takzhe dlya togo, chtoby izbezhat' lishnih ob- rashchenij k disku. Otlozhennaya zapis', veroyatno, naibolee effektivna dlya kana- lov, tak kak drugoj process chitaet kanal i udalyaet iz nego dannye (razdel 5.12). No dazhe dlya obychnyh fajlov otlozhennaya zapis' effektivna, esli fajl sozdaetsya vremenno i vskore budet prochitan. Naprimer, mnogie programmy, ta- kie kak redaktory i elektronnaya pochta, sozdayut vremennye fajly v kataloge "/tmp" i bystro udalyayut ih. Ispol'zovanie otlozhennoj zapisi mozhet sokratit' kolichestvo obrashchenij k disku dlya zapisi vo vremennye fajly.

    5.4 ZAHVAT FAJLA I ZAPISI

V pervoj versii sistemy UNIX, razrabotannoj Tompsonom i Richi, otsutstvo- val vnutrennij mehanizm, s pomoshch'yu kotorogo processu mog by byt' obespechen isklyuchitel'nyj dostup k fajlu. Mehanizm zahvata byl priznan izlishnim, pos- kol'ku, kak otmechaet Richi, "my ne imeem dela s bol'shimi bazami dannyh, sos- toyashchimi iz odnogo fajla, kotorye podderzhivayutsya nezavisimymi processami" (sm. [Ritchie 81]). Dlya togo, chtoby povysit' privlekatel'nost' sistemy UNIX dlya kommercheskih pol'zovatelej, rabotayushchih s bazami dannyh, v versiyu V sis- temy nyne vklyucheny mehanizmy zahvata fajla i zapisi. Zahvat fajla - eto sredstvo, pozvolyayushchee zapretit' drugim processam proizvodit' chtenie ili za- pis' lyuboj chasti fajla, a zahvat zapisi - eto sredstvo, pozvolyayushchee zapre- tit' drugim processam proizvodit' vvod-vyvod ukazannyh zapisej (chastej fajla mezhdu ukazannymi smeshcheniyami). V uprazhnenii 5.9 rassmatrivaetsya realizaciya mehanizma zahvata fajla i zapisi.

    5.5 UKAZANIE MESTA V FAJLE, GDE BUDET VYPOLNYATXSYA VVOD-VYVOD - LSEEK

Obychnoe ispol'zovanie sistemnyh funkcij read i write obespechivaet posle- dovatel'nyj dostup k fajlu, odnako processy mogut ispol'zovat' vyzov sistem- noj funkcii lseek dlya ukazaniya mesta v fajle, gde budet proizvodit'sya vvod-vyvod, i osushchestvleniya proizvol'nogo dostupa k fajlu. Sintaksis vyzova sistemnoj funkcii: position = lseek(fd,offset,reference); gde fd - deskriptor fajla, identificiruyushchij fajl, offset - smeshchenie v baj- tah, a reference ukazyvaet, yavlyaetsya li znachenie offset smeshcheniem ot nachala fajla, smeshcheniem ot tekushchej pozicii vvoda-vyvoda ili smeshcheniem ot konca faj- la. Vozvrashchaemoe znachenie, position, yavlyaetsya smeshcheniem v bajtah do mesta, 96 gde budet nachinat'sya sleduyushchaya operaciya chteniya ili zapisi. Naprimer, v prog- ramme, privedennoj na Risunke 5.10, process otkryvaet fajl, schityvaet bajt, a zatem vyzyvaet funkciyu lseek, chtoby zamenit' znachenie polya smeshcheniya v tab- lice fajlov velichinoj, ravnoj 1023 (s peremennoj reference, imeyushchej znachenie 1), i vypolnyaet cikl. Takim obrazom, programma schityvaet kazhdyj 1024-j bajt fajla. Esli reference imeet znachenie 0, yadro osushchestvlyaet poisk ot nachala fajla, a esli 2, yadro vedet poisk ot konca fajla. Funkciya lseek nichego ne dolzhna delat', krome operacii poiska, kotoraya pozicioniruet golovku chte- niya-zapisi na ukazannyj diskovyj sektor. Dlya togo, chtoby vypolnit' funkciyu lseek, yadro prosto vybiraet znachenie smeshcheniya iz tablicy fajlov; v posleduyu- shchih vyzovah funkcij read i write smeshchenie iz tablicy fajlov ispol'zuetsya v kachestve nachal'nogo smeshcheniya.

    5.6 CLOSE

Process zakryvaet otkrytyj fajl, kogda processu bol'she ne nuzhno obra- shchat'sya k nemu. Sintaksis vyzova sistemnoj funkcii close (zakryt'): +--------------------------------------------------------+ | #include | | main(argc,argv) | | int argc; | | char *argv[]; | | { | | int fd,skval; | | char c; | | | | if(argc != 2) | | exit(); | | fd = open(argv[1],O_RDONLY); | | if (fd == -1) | | exit(); | | while ((skval = read(fd,&c,1)) == 1) | | { | | printf("char %c\n",c); | | skval = lseek(fd,1023L,1); | | printf("new seek val %d\n",skval); | | } | | } | +--------------------------------------------------------+ Risunok 5.10. Programma, soderzhashchaya vyzov sistemnoj funkcii lseek close(fd); gde fd - deskriptor otkrytogo fajla. YAdro vypolnyaet operaciyu zakrytiya, is- pol'zuya deskriptor fajla i informaciyu iz sootvetstvuyushchih zapisej v tablice fajlov i tablice indeksov. Esli schetchik ssylok v zapisi tablicy fajlov imeet znachenie, bol'shee, chem 1, v svyazi s tem, chto byli obrashcheniya k funkciyam dup ili fork, to eto oznachaet, chto na zapis' v tablice fajlov delayut ssylku dru- gie pol'zovatel'skie deskriptory, chto my uvidim dalee; yadro umen'shaet znache- nie schetchika i operaciya zakrytiya zavershaetsya. Esli schetchik ssylok v tablice fajlov imeet znachenie, ravnoe 1, yadro osvobozhdaet zapis' v tablice i indeks v pamyati, ranee vydelennyj sistemnoj funkciej open (algoritm iput). Esli drugie processy vse eshche ssylayutsya na indeks, yadro umen'shaet znachenie schetchi- ka ssylok na indeks, no ostavlyaet indeks processam; v protivnom sluchae in- deks osvobozhdaetsya dlya perenaznacheniya, tak kak ego schetchik ssylok soderzhit 0. Kogda vypolnenie sistemnoj funkcii close zavershaetsya, zapis' v tablice 97 pol'zovatel'skih deskriptorov fajla stanovitsya pustoj. Popytki processa is- pol'zovat' dannyj deskriptor zakanchivayutsya oshibkoj do teh por, poka deskrip- tor ne budet perenaznachen drugomu fajlu v rezul'tate vypolneniya drugoj sis- temnoj funkcii. Kogda process zavershaetsya, yadro proveryaet nalichie aktivnyh pol'zovatel'skih deskriptorov fajla, prinadlezhavshih processu, i zakryvaet kazhdyj iz nih. Takim obrazom, ni odin process ne mozhet ostavit' fajl otkry- tym posle svoego zaversheniya. Na Risunke 5.11, naprimer, pokazany zapisi iz tablic, privedennyh na Ri- sunke 5.4, posle togo, kak vtoroj process zakryvaet sootvetstvuyushchie im faj- ly. Zapisi, sootvetstvuyushchie deskriptoram 3 i 4 v tablice pol'zovatel'skih pol'zovatel'skie deskrip- tory fajla tablica fajlov tablica indeksov +---------+ +------------+ +--------------+ 0| | | | | - | +---------+ | | | - | 1| | | | | - | +---------+ +------------+ | - | 2| | | - | | - | +---------+ | - | | - | 3| ----+----+ | - | | - | +---------+ | | - | +--------------+ 4| ----+---+| | - | +---->| schet- | +---------+ || | - | | | chik (/etc/ | 5| ----+--+|| +------------+ | +-->| 2 passwd)| +---------+ ||| | schet- | | | +--------------+ | - | ||+-->| chik +--+ | | - | | - | || | 1 | | | - | | - | || +------------+ | | - | +---------+ || | - | | | - | || | - | | | - | +---------+ || | - | | | - | 0| | || +------------+ | | - | +---------+ || | schet- | | | - | 1| | |+--->| chik +----|+ | - | +---------+ | | 1 | || | - | 2| | | +------------+ || | - | +---------+ | | - | || +--------------+ 3| NULL | | | - | || | schet- | +---------+ | | - | |+->| chik (local)| 4| NULL | | | - | | | 1 | +---------+ | | - | | +--------------+ 5| | | | - | | | - | +---------+ | +------------+ | | - | | - | | | schetchik 0 | | | - | +---------+ | +------------+ | | - | | | - | | +--------------+ | | - | | | schet- | | +------------+ | | chik (private)| | | schetchik 1 | | | 0 | +---->| +----+ +--------------+ +------------+ | - | | - | +--------------+ | - | +------------+ | schetchik 0 | +------------+ Risunok 5.11. Tablicy posle zakrytiya fajla 98 deskriptorov fajlov, pusty. Schetchiki v zapisyah tablicy fajlov teper' imeyut znachenie 0, a sami zapisi pusty. Schetchiki ssylok na fajly "/etc/passwd" i "private" v indeksah takzhe umen'shilis'. Indeks dlya fajla "private" nahoditsya v spiske svobodnyh indeksov, poskol'ku schetchik ssylok na nego raven 0, no zapis' o nem ne pusta. Esli eshche kakoj-nibud' process obratitsya k fajlu "private", poka indeks eshche nahoditsya v spiske svobodnyh indeksov, yadro vostrebuet indeks obratno, kak pokazano v razdele 4.1.2.

    5.7 SOZDANIE FAJLA

Sistemnaya funkciya open daet processu dostup k sushchestvuyushchemu fajlu, a sistemnaya funkciya creat sozdaet v sisteme novyj fajl. Sintaksis vyzova sis- temnoj funkcii creat: fd = creat(pathname,modes); gde peremennye pathname, modes i fd imeyut tot zhe smysl, chto i v sistemnoj funkcii open. Esli prezhde takogo fajla ne sushchestvovalo, yadro sozdaet novyj fajl s ukazannym imenem i ukazannymi pravami dostupa k nemu; esli zhe takoj fajl uzhe sushchestvoval, yadro usekaet fajl (osvobozhdaet vse sushchestvuyushchie bloki +------------------------------------------------------------+ | algoritm creat | | vhodnaya informaciya: imya fajla | | ustanovki prav dostupa k fajlu | | vyhodnaya informaciya: deskriptor fajla | | { | | poluchit' indeks dlya dannogo imeni fajla (algoritm namei);| | esli (fajl uzhe sushchestvuet) | | { | | esli (dostup ne razreshen) | | { | | osvobodit' indeks (algoritm iput); | | vozvratit' (oshibku); | | } | | } | | v protivnom sluchae /* fajl eshche ne sushchestvuet */ | | { | | naznachit' svobodnyj indeks iz fajlovoj sistemy (algo- | | ritm ialloc); | | sozdat' novuyu tochku vhoda v roditel'skom kataloge: | | vklyuchit' imya novogo fajla i nomer vnov' naznachennogo | | indeksa; | | } | | vydelit' dlya indeksa zapis' v tablice fajlov, inicializi-| | rovat' schetchik; | | esli (fajl sushchestvoval k momentu sozdaniya) | | osvobodit' vse bloki fajla (algoritm free); | | snyat' blokirovku (s indeksa); | | vozvratit' (pol'zovatel'skij deskriptor fajla); | | } | +------------------------------------------------------------+ Risunok 5.12. Algoritm sozdaniya fajla 99 dannyh i ustanavlivaet razmer fajla ravnym 0) pri nalichii sootvetstvuyushchih prav dostupa k nemu (***). Na Risunke 5.12 priveden algoritm sozdaniya fajla. YAdro provodit sintaksicheskij analiz imeni puti poiska, ispol'zuya algo- ritm namei i sleduya etomu algoritmu bukval'no, kogda rech' idet o razbore imen katalogov. Odnako, kogda delo kasaetsya poslednej komponenty imeni puti poiska, a imenno identifikatora sozdavaemogo fajla, namei otmechaet smeshchenie v bajtah do pervoj pustoj pozicii v kataloge i zapominaet eto smeshchenie v prostranstve processa. Esli yadro ne obnaruzhilo v kataloge komponentu imeni puti poiska, ono v ko- nechnom schete vpishet imya komponenty v tol'ko chto najdennuyu pustuyu poziciyu. Esli v kataloge net pustyh pozicij, yadro zapominaet smeshchenie do konca kata- loga i sozdaet novuyu poziciyu tam. Ono takzhe zapominaet v prostranstve pro- cessa indeks prosmatrivaemogo kataloga i derzhit indeks zablokirovannym; ka- talog stanovitsya po otnosheniyu k novomu fajlu roditel'skim katalogom. YAdro ne zapisyvaet poka imya novogo fajla v katalog, tak chto v sluchae vozniknoveniya oshibok yadru prihoditsya men'she peredelyvat'. Ono proveryaet nalichie u processa razresheniya na zapis' v katalog. Poskol'ku process budet proizvodit' zapis' v katalog v rezul'tate vypolneniya funkcii creat, nalichie razresheniya na zapis' v katalog oznachaet, chto processam dozvolyaetsya sozdavat' fajly v kataloge. Predpolozhiv, chto pod dannym imenem ranee ne sushchestvovalo fajla, yadro naznachaet novomu fajlu indeks, ispol'zuya algoritm ialloc (razdel 4.6). Zatem ono zapisyvaet imya novogo fajla i nomer vnov' vydelennogo indeksa v rodi- tel'skij katalog, a smeshchenie v bajtah sohranyaet v prostranstve processa. Vposledstvii yadro osvobozhdaet indeks roditel'skogo kataloga, uderzhivaemyj s togo vremeni, kogda v kataloge proizvodilsya poisk imeni fajla. Roditel'skij katalog teper' soderzhit imya novogo fajla i ego indeks. YAdro zapisyvaet vnov' vydelennyj indeks na disk (algoritm bwrite), prezhde chem zapisat' na disk ka- talog s novym imenem. Esli mezhdu operaciyami zapisi indeksa i kataloga proi- zojdet sboj sistemy, v itoge okazhetsya, chto vydelen indeks, na kotoryj ne ssylaetsya ni odno iz imen putej poiska v sisteme, odnako sistema budet funk- cionirovat' normal'no. Esli, s drugoj storony, katalog byl zapisan ran'she vnov' vydelennogo indeksa i sboj sistemy proizoshel mezhdu nimi, fajlovaya sis- tema budet soderzhat' imya puti poiska, ssylayushcheesya na nevernyj indeks (bolee podrobno ob etom sm. v razdele 5.16.1). Esli dannyj fajl uzhe sushchestvoval do vyzova funkcii creat, yadro obnaruzhi- vaet ego indeks vo vremya poiska imeni fajla. Staryj fajl dolzhen pozvolyat' processu proizvodit' zapis' v nego, chtoby mozhno bylo sozdat' "novyj" fajl s tem zhe samym imenem, tak kak yadro izmenyaet soderzhimoe fajla pri vypolnenii funkcii creat: ono usekaet fajl, osvobozhdaya vse informacionnye bloki po al- goritmu free, tak chto fajl budet vyglyadet' kak vnov' sozdannyj. Tem ne me- nee, vladelec i prava dostupa k fajlu ostayutsya prezhnimi: yadro ne peredaet pravo sobstvennosti na fajl vladel'cu processa i ignoriruet prava dostupa, ukazannye processom v vyzove funkcii. Nakonec, yadro ne proveryaet nalichie razresheniya na zapis' v katalog, yavlyayushchijsya roditel'skim dlya sushchestvuyushchego fajla, poskol'ku ono ne menyaet soderzhimogo kataloga. Funkciya creat prodolzhaet rabotu, vypolnyaya tot zhe algoritm, chto i funkciya open. YAdro vydelyaet sozdannomu fajlu zapis' v tablice fajlov, chtoby process mog chitat' iz fajla, a takzhe zapis' v tablice pol'zovatel'skih deskriptorov fajla, i v konce koncov vozvrashchaet ukazatel' na poslednyuyu zapis' v vide pol'zovatel'skogo deskriptora fajla. --------------------------------------- (***) Sistemnaya funkciya open imeet dva flaga, O_CREAT (sozdanie) i O_TRUNC (usechenie). Esli process ustanavlivaet v vyzove funkcii flag O_CREAT i fajl ne sushchestvuet, yadro sozdast fajl. Esli fajl uzhe sushchestvuet, on ne budet usechen, esli tol'ko ne ustanovlen flag O_TRUNC. 100

    5.8 SOZDANIE SPECIALXNYH FAJLOV

Sistemnaya funkciya mknod sozdaet v sisteme special'nye fajly, v chislo ko- toryh vklyuchayutsya poimenovannye kanaly, fajly ustrojstv i katalogi. Ona poho- zha na funkciyu creat v tom, chto yadro vydelyaet dlya fajla indeks. Sintaksis vy- zova sistemnoj funkcii mknod: mknod(pathname,type and permissions,dev) gde pathname - imya sozdavaemoj vershiny v ierarhicheskoj strukture fajlovoj sistemy, type and permissions - tip vershiny (naprimer, katalog) i prava dos- tupa k sozdavaemomu fajlu, a dev ukazyvaet starshij i mladshij nomera ustrojs- tva dlya blochnyh i simvol'nyh special'nyh fajlov (glava 10). Na Risunke 5.13 priveden algoritm, realizuemyj funkciej mknod pri sozdanii novoj vershiny. +------------------------------------------------------------+ | algoritm sozdaniya novoj vershiny | | vhodnaya informaciya: vershina (imya fajla) | | tip fajla | | prava dostupa | | starshij, mladshij nomera ustrojstva | | (dlya blochnyh i simvol'nyh special'nyh | | fajlov) | | vyhodnaya informaciya: otsutstvuet | | { | | esli (novaya vershina ne yavlyaetsya poimenovannym kanalom | | i pol'zovatel' ne yavlyaetsya superpol'zovatelem) | | vozvratit' (oshibku); | | poluchit' indeks vershiny, yavlyayushchejsya roditel'skoj dlya | | novoj vershiny (algoritm namei); | | esli (novaya vershina uzhe sushchestvuet) | | { | | osvobodit' roditel'skij indeks (algoritm iput); | | vozvratit' (oshibku); | | } | | naznachit' dlya novoj vershiny svobodnyj indeks iz fajlovoj| | sistemy (algoritm ialloc); | | sozdat' novuyu zapis' v roditel'skom kataloge: vklyuchit' | | imya novoj vershiny i nomer vnov' naznachennogo indeksa; | | osvobodit' indeks roditel'skogo kataloga (algoritm | | iput); | | esli (novaya vershina yavlyaetsya blochnym ili simvol'nym spe-| | cial'nym fajlom) | | zapisat' starshij i mladshij nomera v strukturu indek-| | sa; | | osvobodit' indeks novoj vershiny (algoritm iput); | | } | +------------------------------------------------------------+ Risunok 5.13. Algoritm sozdaniya novoj vershiny YAdro prosmatrivaet fajlovuyu sistemu v poiskah imeni fajla, kotoryj ono sobiraetsya sozdat'. Esli fajl eshche poka ne sushchestvuet, yadro naznachaet emu no- vyj indeks na diske i zapisyvaet imya novogo fajla i nomer indeksa v rodi- tel'skij katalog. Ono ustanavlivaet znachenie polya tipa fajla v indekse, uka- zyvaya, chto fajl yavlyaetsya kanalom, katalogom ili special'nym fajlom. Nakonec, esli fajl yavlyaetsya special'nym fajlom ustrojstva blochnogo ili simvol'nogo tipa, yadro zapisyvaet v indeks starshij i mladshij nomera ustrojstva. Esli funkciya mknod sozdaet katalog, on budet sushchestvovat' po zavershenii vypolne- niya funkcii, no ego soderzhimoe budet imet' nevernyj format (v kataloge budut 101 otsutstvovat' zapisi s imenami "." i ".."). V uprazhnenii 5.33 rassmatrivayut- sya shagi, neobhodimye dlya preobrazovaniya soderzhimogo kataloga v pravil'nyj format. +------------------------------------------------------------+ | algoritm smeny kataloga | | vhodnaya informaciya: imya novogo kataloga | | vyhodnaya informaciya: otsutstvuet | | { | | poluchit' indeks dlya kataloga s novym imenem (algoritm | | namei); | | esli (indeks ne yavlyaetsya indeksom kataloga ili zhe pro- | | cessu ne razreshen dostup k fajlu) | | { | | osvobodit' indeks (algoritm iput); | | vozvratit' (oshibku); | | } | | snyat' blokirovku s indeksa; | | osvobodit' indeks prezhnego tekushchego kataloga (algoritm | | iput); | | pomestit' novyj indeks v poziciyu dlya tekushchego kataloga | | v prostranstve processa; | | } | +------------------------------------------------------------+ Risunok 5.14. Algoritm smeny tekushchego kataloga

    5.9 SMENA TEKUSHCHEGO I KORNEVOGO KATALOGA

Kogda sistema zagruzhaetsya vpervye, nulevoj process delaet kornevoj kata- log fajlovoj sistemy tekushchim na vremya inicializacii. Dlya indeksa kornevogo kataloga nulevoj process vypolnyaet algoritm iget, sohranyaet etot indeks v prostranstve processa v kachestve indeksa tekushchego kataloga i snimaet s in- deksa blokirovku. Kogda s pomoshch'yu funkcii fork sozdaetsya novyj process, on nasleduet tekushchij katalog starogo processa v svoem adresnom prostranstve, a yadro, sootvetstvenno, uvelichivaet znachenie schetchika ssylok v indekse. Algoritm chdir (Risunok 5.14) izmenyaet imya tekushchego kataloga dlya proces- sa. Sintaksis vyzova sistemnoj funkcii chdir: chdir(pathname); gde pathname - katalog, kotoryj stanovitsya tekushchim dlya processa. YAdro anali- ziruet imya kataloga, ispol'zuya algoritm namei, i proveryaet, yavlyaetsya li dan- nyj fajl katalogom i imeet li vladelec processa pravo dostupa k kataloga. YAdro snimaet s novogo indeksa blokirovku, no uderzhivaet indeks v kachestve vydelennogo i ostavlyaet schetchik ssylok bez izmenenij, osvobozhdaet indeks prezhnego tekushchego kataloga (algoritm iput), hranyashchijsya v prostranstve pro- cessa, i zapominaet v etom prostranstve novyj indeks. Posle smeny processom tekushchego kataloga algoritm namei ispol'zuet indeks v kachestve nachal'nogo ka- taloga pri analize vseh imen putej, kotorye ne berut nachalo ot kornya. Po okonchanii vypolneniya sistemnoj funkcii chdir schetchik ssylok na indeks novogo kataloga imeet znachenie, kak minimum, 1, a schetchik ssylok na indeks prezhnego tekushchego kataloga mozhet stat' ravnym 0. V etom otnoshenii funkciya chdir poho- zha na funkciyu open, poskol'ku obe funkcii obrashchayutsya k fajlu i ostavlyayut ego indeks v kachestve vydelennogo. Indeks, vydelennyj vo vremya vypolneniya funk- cii chdir, osvobozhdaetsya tol'ko togda, kogda process menyaet tekushchij katalog eshche raz ili kogda process zavershaetsya. 102 Processy obychno ispol'zuyut global'nyj kornevoj katalog fajlovoj sistemy dlya vseh imen putej poiska, nachinayushchihsya s "/". YAdro hranit global'nuyu pere- mennuyu, kotoraya ukazyvaet na indeks global'nogo kornya, vydelyaemyj po algo- ritmu iget pri zagruzke sistemy. Processy mogut menyat' svoe predstavlenie o kornevom kataloge fajlovoj sistemy s pomoshch'yu sistemnoj funkcii chroot. |to byvaet polezno, esli pol'zovatelyu nuzhno sozdat' model' obychnoj ierarhicheskoj struktury fajlovoj sistemy i zapustit' processy tam. Sintaksis vyzova funk- cii: chroot(pathname); gde pathname - katalog, kotoryj vposledstvii budet rassmatrivat'sya yadrom v kachestve kornevogo kataloga dlya processa. Vypolnyaya funkciyu chroot, yadro sle- duet tomu zhe algoritmu, chto i pri smene tekushchego kataloga. Ono zapominaet indeks novogo kornya v prostranstve processa, snimaya s indeksa blokirovku po zavershenii vypolneniya funkcii. Tem ne menee, tak kak umolchanie na koren' dlya yadra hranitsya v global'noj peremennoj, yadro osvobozhdaet indeks prezhnego kor- nya ne avtomaticheski, a tol'ko posle togo, kak ono samo ili process-predok ispolnyat vyzov funkcii chroot. Novyj indeks stanovitsya logicheskim kornem fajlovoj sistemy dlya processa (i dlya vseh porozhdennyh im processov) i eto oznachaet, chto vse puti poiska v algoritme namei, nachinayushchiesya s kornya ("/"), voz'mut nachalo s dannogo indeksa i chto vse popytki vojti v katalog ".." nad kornem privedut k tomu, chto rabochim katalogom processa ostanetsya novyj ko- ren'. Process peredaet vsem vnov' porozhdaemym processam etot katalog v ka- chestve kornevogo podobno tomu, kak peredaet svoj tekushchij katalog.

    5.10 SMENA VLADELXCA I REZHIMA DOSTUPA K FAJLU

Smena vladel'ca ili rezhima (prav) dostupa k fajlu yavlyaetsya operaciej, proizvodimoj nad indeksom, a ne nad fajlom. Sintaksis vyzova sootvetstvuyushchih sistemnyh funkcij: chown(pathname,owner,group) chmod(pathname,mode) Dlya togo, chtoby pomenyat' vladel'ca fajla, yadro preobrazuet imya fajla v identifikator indeksa, ispol'zuya algoritm namei. Vladelec processa dolzhen byt' superpol'zovatelem ili vladel'cem fajla (process ne mozhet rasporyazhat'sya tem, chto ne prinadlezhit emu). Zatem yadro naznachaet fajlu novogo vladel'ca i novogo gruppovogo pol'zovatelya, sbrasyvaet flagi prezhnih ustanovok (sm. raz- del 7.5) i osvobozhdaet indeks po algoritmu iput. Posle etogo prezhnij vlade- lec teryaet pravo "sobstvennosti" na fajl. Dlya togo, chtoby pomenyat' rezhim dostupa k fajlu, yadro vypolnyaet proceduru, podobnuyu opisannoj, vmesto koda vladel'ca menyaya flagi, ustanavlivayushchie rezhim dostupa.

    5.11 STAT I FSTAT

Sistemnye funkcii stat i fstat pozvolyayut processam zaprashivat' informa- ciyu o statuse fajla: tipe fajla, vladel'ce fajla, pravah dostupa, razmere fajla, chisle svyazej, nomere indeksa i vremeni dostupa k fajlu. Sintaksis vy- zova funkcij: stat(pathname,statbuffer); fstat(fd,statbuffer); gde pathname - imya fajla, fd - deskriptor fajla, vozvrashchaemyj funkciej open, statbuffer - adres struktury dannyh pol'zovatel'skogo processa, gde budet 103 hranit'sya informaciya o statuse fajla posle zaversheniya vypolneniya vyzova. Sistemnye funkcii prosto perepisyvayut polya iz indeksa v strukturu statbuffer. Programma na Risunke 5.33 illyustriruet ispol'zovanie funkcij stat i fstat. Vyzyvaet kanal Ne mogut sovmestno ispol'zovat' - kanal - - - - - - - - - - Process A - - | - - +-------------+--------------+ - - | | - Process B Process C | +-------+-------+ | | Process D - Process E - - - - - - - - - - Sovmestno ispol'zuyut kanal Risunok 5.15. Derevo processov i sovmestnoe ispol'zovanie kanalov

    5.12 KANALY

Kanaly pozvolyayut peredavat' dannye mezhdu processami v poryadke postuple- niya ("pervym prishel - pervym vyshel"), a takzhe sinhronizirovat' vypolnenie processov. Ih ispol'zovanie daet processam vozmozhnost' vzaimodejstvovat' mezhdu soboj, pust' dazhe ne izvestno, kakie processy nahodyatsya na drugom kon- ce kanala. Tradicionnaya realizaciya kanalov ispol'zuet fajlovuyu sistemu dlya hraneniya dannyh. Razlichayut dva vida kanalov: poimenovannye kanaly i, za ot- sutstviem luchshego termina, nepoimenovannye kanaly, kotorye identichny mezhdu soboj vo vsem, krome sposoba pervonachal'nogo obrashcheniya k nim processov. Dlya poimenovannyh kanalov processy ispol'zuyut sistemnuyu funkciyu open, a sistem- nuyu funkciyu pipe - dlya sozdaniya nepoimenovannogo kanala. Vposledstvii, pri rabote s kanalami processy pol'zuyutsya obychnymi sistemnymi funkciyami dlya faj- lov, takimi kak read, write i close. Tol'ko svyazannye mezhdu soboj processy, yavlyayushchiesya potomkami togo processa, kotoryj vyzval funkciyu pipe, mogut raz- delyat' dostup k nepoimenovannym kanalam. Naprimer (sm. Risunok 5.15), esli process B sozdaet kanal i porozhdaet processy D i E, eti tri processa razde- lyayut mezhdu soboj dostup k kanalu, v otlichie ot processov A i C. Odnako, vse processy mogut obrashchat'sya k poimenovannomu kanalu nezavisimo ot vzaimootno- shenij mezhdu nimi, pri uslovii nalichiya obychnyh prav dostupa k fajlu. Poskol'- ku nepoimenovannye kanaly vstrechayutsya chashche, oni budut rassmotreny pervymi.

    5.12.1 Sistemnaya funkciya pipe

Sintaksis vyzova funkcii sozdaniya kanala: pipe(fdptr); 104 gde fdptr - ukazatel' na massiv iz dvuh celyh peremennyh, v kotorom budut hranit'sya dva deskriptora fajla dlya chteniya iz kanala i dlya zapisi v kanal. Poskol'ku yadro realizuet kanaly vnutri fajlovoj sistemy i poskol'ku kanal ne sushchestvuet do togo, kak ego budut ispol'zovat', yadro dolzhno pri sozdanii ka- nala naznachit' emu indeks. Ono takzhe naznachaet dlya kanala paru pol'zovatel'- skih deskriptorov i sootvetstvuyushchie im zapisi v tablice fajlov: odin iz des- kriptorov dlya chteniya iz kanala, a drugoj dlya zapisi v kanal. Poskol'ku yadro pol'zuetsya tablicej fajlov, interfejs dlya vyzova funkcij read, write i dr. soglasuetsya s interfejsom dlya obychnyh fajlov. V rezul'tate processam net na- dobnosti znat', vedut li oni chtenie ili zapis' v obychnyj fajl ili v kanal. +------------------------------------------------------------+ | algoritm pipe | | vhodnaya informaciya: otsutstvuet | | vyhodnaya informaciya: deskriptor fajla dlya chteniya | | deskriptor fajla dlya zapisi | | { | | naznachit' novyj indeks iz ustrojstva kanala (algoritm | | ialloc); | | vydelit' odnu zapis' v tablice fajlov dlya chteniya, odnu -| | dlya perepisi; | | inicializirovat' zapisi v tablice fajlov takim obrazom, | | chtoby oni ukazyvali na novyj indeks; | | vydelit' odin pol'zovatel'skij deskriptor fajla dlya chte-| | niya, odin - dlya zapisi, proinicializirovat' ih takim | | obrazom, chtoby oni ukazyvali na sootvetstvuyushchie tochki | | vhoda v tablice fajlov; | | ustanovit' znachenie schetchika ssylok v indekse ravnym 2; | | ustanovit' znachenie schetchika chisla processov, proizvodya-| | shchih chtenie, i processov, proizvodyashchih zapis', ravnym 1;| | } | +------------------------------------------------------------+ Risunok 5.16. Algoritm sozdaniya kanalov (nepoimenovannyh) Na Risunke 5.16 pokazan algoritm sozdaniya nepoimenovannyh kanalov. YAdro naznachaet indeks dlya kanala iz fajlovoj sistemy, oboznachennoj kak "ustrojst- vo kanala", ispol'zuya algoritm ialloc. Ustrojstvo kanala - eto imenno ta fajlovaya sistema, iz kotoroj yadro mozhet naznachat' kanalam indeksy i vydelyat' bloki dlya dannyh. Administratory sistemy ukazyvayut ustrojstvo kanala pri konfigurirovanii sistemy i eti ustrojstva mogut sovpadat' u raznyh fajlovyh sistem. Poka kanal aktiven, yadro ne mozhet perenaznachit' indeks kanala i in- formacionnye bloki kanala drugomu fajlu. Zatem yadro vydelyaet v tablice fajlov dve zapisi, sootvetstvuyushchie desk- riptoram dlya chteniya i zapisi v kanal, i korrektiruet "buhgalterskuyu" infor- maciyu v kopii indeksa v pamyati. V kazhdoj iz vydelennyh zapisej v tablice fajlov hranitsya informaciya o tom, skol'ko ekzemplyarov kanala otkryto dlya chteniya ili zapisi (pervonachal'no 1), a schetchik ssylok v indekse ukazyvaet, skol'ko raz kanal byl "otkryt" (pervonachal'no 2 - po odnomu dlya kazhdoj zapi- si tablicy fajlov). Nakonec, v indekse zapisyvayutsya smeshcheniya v bajtah vnutri kanala do mesta, gde budet nachinat'sya sleduyushchaya operaciya zapisi ili chteniya. Blagodarya sohraneniyu etih smeshchenij v indekse imeetsya vozmozhnost' proizvodit' dostup k dannym v kanale v poryadke ih postupleniya v kanal ("pervym prishel - pervym vyshel"); etot moment yavlyaetsya osobennost'yu kanalov, poskol'ku dlya obychnyh fajlov smeshcheniya hranyatsya v tablice fajlov. Processy ne mogut menyat' eti smeshcheniya s pomoshch'yu sistemnoj funkcii lseek i poetomu proizvol'nyj dostup k dannym kanala nevozmozhen. 105

    5.12.2 Otkrytie poimenovannogo kanala

Poimenovannyj kanal - eto fajl, imeyushchij pochti takuyu zhe semantiku, kak i nepoimenovannyj kanal, za isklyucheniem togo, chto etomu fajlu sootvetstvuet zapis' v kataloge i obrashchenie k nemu proizvoditsya po imeni. Processy otkry- vayut poimenovannye kanaly tak zhe, kak i obychnye fajly, i, sledovatel'no, s pomoshch'yu poimenovannyh kanalov mogut vzaimodejstvovat' mezhdu soboj dazhe pro- cessy, ne imeyushchie drug k drugu blizkogo otnosheniya. Poimenovannye kanaly pos- toyanno prisutstvuyut v ierarhii fajlovoj sistemy (iz kotoroj oni udalyayutsya s pomoshch'yu sistemnoj funkcii unlink), a nepoimenovannye kanaly yavlyayutsya vremen- nymi: kogda vse processy zakanchivayut rabotu s kanalom, yadro otbiraet nazad ego indeks. Algoritm otkrytiya poimenovannogo kanala identichen algoritmu otkrytiya obychnogo fajla. Odnako, pered vyhodom iz funkcii yadro uvelichivaet znacheniya teh schetchikov v indekse, kotorye pokazyvayut kolichestvo processov, otkryvshih poimenovannyj kanal dlya chteniya ili zapisi. Process, otkryvayushchij poimenovan- nyj kanal dlya chteniya, priostanovit svoe vypolnenie do teh por, poka drugoj process ne otkroet poimenovannyj kanal dlya zapisi, i naoborot. Ne imeet smysla otkryvat' kanal dlya chteniya, esli process ne nadeetsya poluchit' dannye; to zhe samoe kasaetsya zapisi. V zavisimosti ot togo, otkryvaet li process po- imenovannyj kanal dlya zapisi ili dlya chteniya, yadro vozobnovlyaet vypolnenie teh processov, kotorye byli priostanovleny v ozhidanii processa, zapisyvayushche- go v poimenovannyj kanal ili schityvayushchego dannye iz kanala (sootvetstvenno). Esli process otkryvaet poimenovannyj kanal dlya chteniya, prichem process, zapisyvayushchij v kanal, sushchestvuet, otkrytie zavershaetsya. Ili esli process ot- kryvaet poimenovannyj fajl s parametrom "no delay", funkciya open vozvrashchaet upravlenie nemedlenno, dazhe kogda net ni odnogo zapisyvayushchego processa. Vo vseh ostal'nyh sluchayah process priostanavlivaetsya do teh por, poka zapisyva- yushchij process ne otkroet kanal. Analogichnye pravila dejstvuyut dlya processa, otkryvayushchego kanal dlya zapisi.

    5.12.3 CHtenie iz kanalov i zapis' v kanaly

Kanal sleduet rassmatrivat' pod takim uglom zreniya, chto processy vedut zapis' na odnom konce kanala, a schityvayut dannye na drugom konce. Kak uzhe govorilos' vyshe, processy obrashchayutsya k dannym v kanale v poryadke ih postup- leniya v kanal; eto oznachaet, chto ocherednost', v kotoroj dannye zapisyvayutsya v kanal, sovpadaet s ocherednost'yu ih vyborki iz kanala. Sovpadenie kolichest- va processov, schityvayushchih dannye iz kanala, s kolichestvom processov, vedushchih zapis' v kanal, sovsem ne obyazatel'no; esli odno chislo otlichaetsya ot drugogo bolee, chem na 1, processy dolzhny koordinirovat' svoi dejstviya po ispol'zova- niyu kanala s pomoshch'yu drugih mehanizmov. YAdro obrashchaetsya k dannym v kanale tochno tak zhe, kak i k dannym v obychnom fajle: ono sohranyaet dannye na ust- rojstve kanala i naznachaet kanalu stol'ko blokov, skol'ko nuzhno, vo vremya vypolneniya funkcii write. Razlichie v vydelenii pamyati dlya kanala i dlya +--------------------+--------------------+ | Ukazatel' chteniya | Ukazatel' zapisi | +----------+---------+----------+---------+ | +----------------+ +-- | --------------+ v v +---+---+---+---+---+---+---+---+---+---+ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | +---+---+---+---+---+---+---+---+---+---+ Bloki pryamoj adresacii v indekse Risunok 5.17. Logicheskaya shema chteniya i zapisi v kanal 106 obychnogo fajla sostoit v tom, chto kanal ispol'zuet v indekse tol'ko bloki pryamoj adresacii v celyah povysheniya effektivnosti raboty, hotya eto i naklady- vaet opredelennye ogranicheniya na ob®em dannyh, odnovremenno pomeshchayushchihsya v kanale. YAdro rabotaet s blokami pryamoj adresacii indeksa kak s ciklicheskoj ochered'yu, podderzhivaya v svoej strukture ukazateli chteniya i zapisi dlya obes- pecheniya ocherednosti obsluzhivaniya "pervym prishel - pervym vyshel" (Risunok 5.17). Rassmotrim chetyre primera vvoda-vyvoda v kanal: zapis' v kanal, v koto- rom est' mesto dlya zapisi dannyh; chtenie iz kanala, v kotorom dostatochno dannyh dlya udovletvoreniya zaprosa na chtenie; chtenie iz kanala, v kotorom dannyh nedostatochno; i zapis' v kanal, gde net mesta dlya zapisi. Rassmotrim pervyj sluchaj, v kotorom process vedet zapis' v kanal, imeyu- shchij mesto dlya vvoda dannyh: summa kolichestva zapisyvaemyh bajt s chislom bajt, uzhe nahodyashchihsya v kanale, men'she ili ravna emkosti kanala. YAdro sledu- et algoritmu zapisi dannyh v obychnyj fajl, za isklyucheniem togo, chto ono uve- lichivaet razmer kanala avtomaticheski posle kazhdogo vypolneniya funkcii write, poskol'ku po opredeleniyu ob®em dannyh v kanale rastet s kazhdoj operaciej za- pisi. Inache proishodit uvelichenie razmera obychnogo fajla: process uvelichiva- et razmer fajla tol'ko togda, kogda on pri zapisi dannyh perestupaet granicu konca fajla. Esli sleduyushchee smeshchenie v kanale trebuet ispol'zovaniya bloka kosvennoj adresacii, yadro ustanavlivaet znachenie smeshcheniya v prostranstve processa takim obrazom, chtoby ono ukazyvalo na nachalo kanala (smeshchenie v bajtah, ravnoe 0). YAdro nikogda ne zatiraet dannye v kanale; ono mozhet sbro- sit' znachenie smeshcheniya v 0, poskol'ku ono uzhe ustanovilo, chto dannye ne bu- dut perepolnyat' emkost' kanala. Kogda process zapishet v kanal vse svoi dan- nye, yadro otkorrektiruet znachenie ukazatelya zapisi (v indekse) kanala takim obrazom, chto sleduyushchij process prodolzhit zapis' v kanal s togo mesta, gde ostanovilas' predydushchaya operaciya write. Zatem yadro vozobnovit vypolnenie vseh drugih processov, priostanovlennyh v ozhidanii schityvaniya dannyh iz ka- nala. Kogda process zapuskaet funkciyu chteniya iz kanala, on proveryaet, pustoj li kanal ili net. Esli v kanale est' dannye, yadro schityvaet ih iz kanala tak, kak esli by kanal byl obychnym fajlom, vypolnyaya sootvetstvuyushchij algo- ritm. Odnako, nachal'nym smeshcheniem budet znachenie ukazatelya chteniya, hranyashche- gosya v indekse i pokazyvayushchego protyazhennost' prochitannyh ranee dannyh. Posle schityvaniya kazhdogo bloka yadro umen'shaet razmer kanala v sootvetstvii s koli- chestvom schitannyh dannyh i ustanavlivaet znachenie smeshcheniya v prostranstve processa tak, chtoby pri dostizhenii konca kanala ono ukazyvalo na ego nachalo. Kogda vypolnenie sistemnoj funkcii read zavershaetsya, yadro vozobnovlyaet vy- polnenie vseh priostanovlennyh processov zapisi i zapominaet tekushchee znache- nie ukazatelya chteniya v indekse (a ne v zapisi tablicy fajlov). Esli process pytaetsya schitat' bol'she informacii, chem fakticheski est' v kanale, funkciya read zavershitsya uspeshno, vozvrativ vse dannye, nahodyashchiesya v dannyj moment v kanale, pust' dazhe ne polnost'yu vypolniv zapros pol'zovate- lya. Esli kanal pust, process obychno priostanavlivaetsya do teh por, poka ka- koj-nibud' drugoj process ne zapishet dannye v kanal, posle chego vse priosta- novlennye processy, ozhidayushchie vvoda dannyh, vozobnovyat svoe vypolnenie i nachnut konkurirovat' za chtenie iz kanala. Esli, odnako, process otkryvaet poimenovannyj kanal s parametrom "no delay" (bez zaderzhki), funkciya read vozvratit upravlenie nemedlenno, esli v kanale otsutstvuyut dannye. Operacii chteniya i zapisi v kanal imeyut tu zhe semantiku, chto i analogichnye operacii dlya terminal'nyh ustrojstv (glava 10), ona pozvolyaet processam ignorirovat' tip teh fajlov, s kotorymi eti programmy imeyut delo. Esli process vedet zapis' v kanal i v kanale net mesta dlya vseh dannyh, yadro pomechaet indeks i priostanavlivaet vypolnenie processa do teh por, poka kanal ne nachnet ochishchat'sya ot dannyh. Kogda vposledstvii drugoj process budet schityvat' dannye iz kanala, yadro zametit sushchestvovanie processov, priosta- novlennyh v ozhidanii ochistki kanala, i vozobnovit ih vypolnenie podobno to- mu, kak eto bylo ob®yasneno vyshe. Isklyucheniem iz etogo utverzhdeniya yavlyaetsya 107 situaciya, kogda process zapisyvaet v kanal dannye, ob®em kotoryh prevyshaet emkost' kanala (to est', ob®em dannyh, kotorye mogut hranit'sya v blokah prya- moj adresacii); v etom sluchae yadro zapisyvaet v kanal stol'ko dannyh, skol'- ko on mozhet vmestit' v sebya, i priostanavlivaet process do teh por, poka ne osvoboditsya dopolnitel'noe mesto. Takim obrazom, vozmozhno polozhenie, pri ko- torom zapisyvaemye dannye ne budut zanimat' nepreryvnoe mesto v kanale, esli drugie processy vedut zapis' v kanal v to vremya, na kotoroe pervyj process prerval svoyu rabotu. Analiziruya realizaciyu kanalov, mozhno zametit', chto interfejs processov soglasuetsya s interfejsom obychnyh fajlov, no ego voploshchenie otlichaetsya, tak kak yadro zapominaet smeshcheniya dlya chteniya i zapisi v indekse vmesto togo, chto- by delat' eto v tablice fajlov. YAdro vynuzhdeno hranit' znacheniya smeshchenij dlya poimenovannyh kanalov v indekse dlya togo, chtoby processy mogli sovmestno is- pol'zovat' eti znacheniya: oni ne mogli by sovmestno ispol'zovat' znacheniya, hranyashchiesya v tablice fajlov, tak kak process poluchaet novuyu zapis' v tablice fajlov po kazhdomu vyzovu funkcii open. Tem ne menee, sovmestnoe ispol'zova- nie smeshchenij chteniya i zapisi v indekse nablyudalos' i do realizacii poimeno- vannyh kanalov. Processy, obrashchayushchiesya k nepoimenovannym kanalam, razdelyayut dostup k kanalu cherez obshchie tochki vhoda v tablicu fajlov, poetomu oni mogli by po umolchaniyu hranit' smeshcheniya zapisi i chteniya v tablice fajlov, kak eto prinyato dlya obychnyh fajlov. |to ne bylo sdelano, tak kak procedury nizkogo urovnya, rabotayushchie v yadre, bol'she ne imeyut dostupa k zapisyam v tablice faj- lov: programma uprostilas' za schet togo, chto processy sovmestno ispol'zuyut znacheniya smeshchenij, hranyashchiesya v indekse. .te1 5.12.4 Zakrytie kanalov Pri zakrytii kanala process vypolnyaet tu zhe samuyu proceduru, chto i pri zakrytii obychnogo fajla, za isklyucheniem togo, chto yadro, prezhde chem osvobo- dit' indeks kanala, vypolnyaet special'nuyu obrabotku. Ono umen'shaet kolichest- vo processov chteniya iz kanala ili zapisi v kanal v zavisimosti ot tipa faj- lovogo deskriptora. Esli znachenie schetchika chisla zapisyvayushchih v kanal pro- cessov stanovitsya ravnym 0 i imeyutsya processy, priostanovlennye v ozhidanii chteniya dannyh iz kanala, yadro vozobnovlyaet vypolnenie poslednih i oni zaver- shayut svoi operacii chteniya bez vozvrata kakih-libo dannyh. Esli stanovitsya ravnym 0 znachenie schetchika chisla schityvayushchih iz kanala processov i imeyutsya processy, priostanovlennye v ozhidanii vozmozhnosti zapisi dannyh v kanal, yad- ro vozobnovlyaet vypolnenie poslednih i posylaet im signal (glava 7) ob oshib- ke. V oboih sluchayah ne imeet smysla prodolzhat' derzhat' processy priostanov- lennymi, esli net nadezhdy na to, chto sostoyanie kanala kogda-nibud' izmenit- sya. Naprimer, esli process ozhidaet vozmozhnosti proizvodit' chtenie iz nepoi- menovannogo kanala i v sisteme bol'she net processov, zapisyvayushchih v etot ka- nal, znachit, zapisyvayushchij process nikogda ne poyavitsya. Nesmotrya na to, chto esli kanal poimenovannyj, v principe vozmozhno poyavlenie novogo schityvayushchego ili zapisyvayushchego processa, yadro traktuet etu situaciyu tochno tak zhe, kak i dlya nepoimenovannyh kanalov. Esli k kanalu ne obrashchaetsya ni odin zapisyvayu- shchij ili schityvayushchij process, yadro osvobozhdaet vse informacionnye bloki kana- la i pereustanavlivaet indeks takim obrazom, chtoby on ukazyval na to, chto kanal pust. Kogda yadro osvobozhdaet indeks obychnogo kanala, ono osvobozhdaet dlya perenaznacheniya i diskovuyu kopiyu etogo indeksa.

    5.12.5 Primery

Programma na Risunke 5.18 illyustriruet iskusstvennoe ispol'zovanie kana- lov. Process sozdaet kanal i vhodit v beskonechnyj cikl, zapisyvaya v kanal 108 +---------------------------------+ | char string[] = "hello"; | | main() | | { | | char buf[1024]; | | char *cp1,*cp2; | | int fds[2]; | | | | cp1 = string; | | cp2 = buf; | | while(*cp1) | | *cp2++ = *cp1++; | | pipe(fds); | | for (;;) | | { | | write(fds[1],buf,6); | | read(fds[0],buf,6); | | } | | } | +---------------------------------+ Risunok 5.18. CHtenie iz kanala i zapis' v kanal stroku simvolov "hello" i schityvaya ee iz kanala. YAdru ne nuzhno ni znat' o tom, chto process, vedushchij zapis' v kanal, yavlyaetsya i processom, schityvayushchim iz kanala, ni proyavlyat' po etomu povodu kakoe-libo bespokojstvo. Process, vypolnyayushchij programmu, kotoraya privedena na Risunke 5.19, soz- daet poimenovannyj kanal s imenem "fifo". Esli etot process zapushchen s ukaza- niem vtorogo (formal'nogo) argumenta, on pos- +------------------------------------------------------------+ | #include | | char string[] = "hello"; | | main(argc,argv) | | int argc; | | char *argv[]; | | { | | int fd; | | char buf[256]; | | | | /* sozdanie poimenovannogo kanala s razresheniem chteniya i | | zapisi dlya vseh pol'zovatelej */ | | mknod("fifo",010777,0); | | if(argc == 2) | | fd = open("fifo",O_WRONLY); | | else | | fd = open("fifo",O_RDONLY); | | for (;;) | | if(argc == 2) | | write(fd,string,6); | | else | | read(fd,buf,6); | | } | +------------------------------------------------------------+ Risunok 5.19. CHtenie i zapis' v poimenovannyj kanal 109 toyanno zapisyvaet v kanal stroku simvolov "hello"; buduchi zapushchen bez vtoro- go argumenta, on vedet chtenie iz poimenovannogo kanala. Dva processa zapus- kayutsya po odnoj i toj zhe programme, tajno dogovorivshis' vzaimodejstvovat' mezhdu soboj cherez poimenovannyj kanal "fifo", no im net neobhodimosti byt' rodstvennymi processami. Drugie pol'zovateli mogut vypolnyat' programmu i uchastvovat' v dialoge (ili meshat' emu).

    5.13 DUR

Sistemnaya funkciya dup kopiruet deskriptor fajla v pervoe svobodnoe mesto v tablice pol'zovatel'skih deskriptorov fajla, vozvrashchaya novyj deskriptor pol'zovatelyu. Ona dejstvuet dlya vseh tipov fajla. Sintaksis vyzova funkcii: newfd = dup(fd); gde fd - deskriptor fajla, kopiruemyj funkciej, a newfd - novyj deskriptor, ssylayushchijsya na fajl. Poskol'ku funkciya dup dubliruet deskriptor fajla, ona uvelichivaet znachenie schetchika v sootvetstvuyushchej zapisi tablicy fajlov - za- tablica pol'zova- tel'skih deskrip- torov fajla tablica fajlov tablica indeksov +---------+ +------------+ +--------------+ 0| ----+----+ | | | - | +---------+ | | | | - | 1| ----+---++-->| | | - | +---------+ | +------------+ | - | 2| ----+--++--->| - | | - | +---------+ +---->| - | | - | 3| ----+----+ | - | | - | +---------+ | | - | +--------------+ 4| ----+---+| | - | +---->| schet- | +---------+ || | - | | | chik (/etc/ | 5| ----+--+|| +------------+ | +-->| 2 passwd)| +---------+ ||| | schet- | | | +--------------+ 6| ----++ ||+-->| chik +--+ | | - | +---------++-||--->| 2 | | | - | 7| | || +------------+ | | - | +---------+ || | - | | | - | | - | || +------------+ | | - | +---------+ || | schetchik | | | - | |+--->| 1 +----|+ | - | | +------------+ || | - | | | - | || +--------------+ | | - | || | schet- | | | - | |+->| chik (local)| | | - | | | 1 | | | - | | +--------------+ | +------------+ | | - | | | schetchik | | | - | +---->| 1 +----+ | - | +------------+ | - | | - | +--------------+ | - | +------------+ Risunok 5.20. Struktury dannyh posle vypolneniya funkcii dup 110 pisi, na kotoruyu ukazyvayut svyazannye s nej tochki vhoda v tablice fajlovyh deskriptorov, kotoryh teper' stalo na odnu bol'she. Naprimer, obzor struktur dannyh, izobrazhennyh na Risunke 5.20, pokazyvaet, chto process vyzyvaet sle- duyushchuyu posledovatel'nost' funkcij: on otkryvaet (open) fajl s imenem "/etc/passwd" (fajlovyj deskriptor 3), zatem otkryvaet fajl s imenem "local" (fajlovyj deskriptor 4), snova fajl s imenem "/etc/passwd" (fajlovyj desk- riptor 5) i, nakonec, dubliruet (dup) fajlovyj deskriptor 3, vozvrashchaya desk- riptor 6. Vozmozhno, dup - funkciya, ne otlichayushchayasya izyashchestvom, poskol'ku ona pred- polagaet, chto pol'zovatel' znaet o tom, chto sistema vozvratit svobodnuyu toch- ku vhoda v tablice pol'zovatel'skih deskriptorov, imeyushchuyu naimen'shij nomer. Odnako, ona sluzhit vazhnoj zadache konstruirovaniya slozhnyh programm iz bolee prostyh konstrukcionnyh blokov, chto, v chastnosti, imeet mesto pri sozdanii konvejerov, sostavlennyh iz komandnyh processorov. Rassmotrim programmu, privedennuyu na Risunke 5.21. V peremennoj i hra- nitsya deskriptor fajla, vozvrashchaemyj v rezul'tate otkrytiya fajla "/etc/passwd", a v peremennoj j - deskriptor fajla, vozvrashchaemyj sistemoj v rezul'tate dublirovaniya deskriptora i s pomoshch'yu funkcii dup. V adresnom prostranstve processa oba pol'zovatel'skih deskriptora, predstavlennye pere- mennymi i i j, ssylayutsya na odnu i tu zhe zapis' v tablice fajlov i poetomu ispol'zuyut odno i to zhe znachenie smeshcheniya vnutri fajla. Takim obrazom, per- vye dva vyzova processom funkcii read realizuyut posledovatel'noe schityvanie dannyh, i v buferah buf1 i buf2 budut raspolagat'sya raznye dannye. Sovsem drugoj rezul'tat poluchaetsya, kogda process +--------------------------------------------------------+ | #include | | main() | | { | | int i,j; | | char buf1[512],buf2[512]; | | | | i = open("/etc/passwd",O_RDONLY); | | j = dup(i); | | read(i,buf1,sizeof(buf1)); | | read(j,buf2,sizeof(buf2)); | | close(i); | | read(j,buf2,sizeof(buf2)); | | } | +--------------------------------------------------------+ Risunok 5.21. Programma na yazyke Si, illyustriruyushchaya ispol'zo- vanie funkcii dup otkryvaet odin i tot zhe fajl dvazhdy i chitaet dvazhdy odni i te zhe dannye (razdel 5.2). Process mozhet osvobodit' s pomoshch'yu funkcii close lyuboj iz faj- lovyh deskriptorov po svoemu zhelaniyu, i vvod-vyvod poluchit normal'noe pro- dolzhenie po drugomu deskriptoru, kak pokazano na primere. V chastnosti, pro- cess mozhet "zakryt'" deskriptor fajla standartnogo vyvoda (fajlovyj deskrip- tor 1), snyat' s nego kopiyu, imeyushchuyu to zhe znachenie, i zatem rassmatrivat' novyj fajl v kachestve fajla standartnogo vyvoda. V glave 7 budet predstavlen bolee realisticheskij primer ispol'zovaniya funkcij pipe i dup pri opisanii osobennostej realizacii komandnogo processora. 111

    5.14 MONTIROVANIE I DEMONTIROVANIE FAJLOVYH SISTEM

Fizicheskij disk sostoit iz neskol'kih logicheskih razdelov, na kotorye on razbit diskovym drajverom, prichem kazhdomu razdelu sootvetstvuet fajl ustroj- stva, imeyushchij opredelennoe imya. Processy obrashchayutsya k dannym razdela, otkry- vaya sootvetstvuyushchij fajl ustrojstva i zatem vedya zapis' i chtenie iz etogo "fajla", predstavlyaya ego sebe v vide posledovatel'nosti diskovyh blokov. |to vzaimodejstvie vo vseh detalyah rassmatrivaetsya v glave 10. Razdel diska mo- zhet soderzhat' logicheskuyu fajlovuyu sistemu, sostoyashchuyu iz bloka nachal'noj zag- ruzki, superbloka, spiska indeksov i informacionnyh blokov (sm. glavu 2). Sistemnaya funkciya mount (montirovat') svyazyvaet fajlovuyu sistemu iz ukazan- nogo razdela na diske s sushchestvuyushchej ierarhiej fajlovyh sistem, a funkciya umount (demontirovat') vyklyuchaet fajlovuyu sistemu iz ierarhii. Funkciya mount, takim obrazom, daet pol'zovatelyam vozmozhnost' obrashchat'sya k dannym v diskovom razdele kak k fajlovoj sisteme, a ne kak k posledovatel'nosti dis- kovyh blokov. Sintaksis vyzova funkcii mount: mount(special pathname,directory pathname,options); gde special pathname - imya special'nogo fajla ustrojstva, sootvetstvuyushchego diskovomu razdelu s montiruemoj fajlovoj sistemoj, directory pathname - ka- talog v sushchestvuyushchej ierarhii, gde budet montirovat'sya fajlovaya sistema (drugimi slovami, tochka ili mesto montirovaniya), a options ukazyvaet, sledu- et li montirovat' fajlovuyu sistemu "tol'ko dlya chteniya" (pri etom ne budut vypolnyat'sya + - - - - - - - - - - - - - - - - - - - - - - - - + / | | | +----------------+--+-------------+ Kornevaya | | | | | fajlovaya bin etc usr sistema | | | - | +-----+-----+ +----+----+ - | | | | | | - | cc date sh getty passwd - + - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - + / | | | Fajlovaya +----------------+--+-------------+ sistema iz | | | | | razdela s bin include src imenem | | | | | /dev/dsk1 +-----+-----+ | | | | | | | | | awk banner yacc stdio.h uts + - - - - - - - - - - - - - - - - - - - - - - - - + Risunok 5.22. Derevo fajlovyh sistem do i posle vypolneniya funkcii mount takie funkcii, kak write i creat, kotorye proizvodyat zapis' v fajlovuyu sis- temu). Naprimer, esli process vyzyvaet funkciyu mount sleduyushchim obrazom: mount("/dev/dsk1","/usr",0); yadro prisoedinyaet fajlovuyu sistemu, nahodyashchuyusya v diskovom razdele s imenem "/dev/dsk1", k katalogu "/usr" v sushchestvuyushchem dereve fajlovyh sistem (sm. 112 Risunok 5.22). Fajl "/dev/dsk1" yavlyaetsya blochnym special'nym fajlom, t.e. on nosit imya ustrojstva blochnogo tipa, obychno imya razdela na diske. YAdro pred- polagaet, chto razdel na diske s ukazannym imenem soderzhit fajlovuyu sistemu s superblokom, spiskom indeksov i kornevym indeksom. Posle vypolneniya funkcii mount k kornyu smontirovannoj fajlovoj sistemy mozhno obrashchat'sya po imeni "/usr". Processy mogut obrashchat'sya k fajlam v montirovannoj fajlovoj sisteme i ignorirovat' tot fakt, chto sistema mozhet otsoedinyat'sya. Tol'ko sistemnaya funkciya link kontroliruet fajlovuyu sistemu, tak kak v versii V ne razreshayut- sya svyazi mezhdu fajlami, prinadlezhashchimi raznym fajlovym sistemam (sm. razdel 5.15). YAdro podderzhivaet tablicu montirovaniya s zapisyami o kazhdoj montirovannoj fajlovoj sisteme. V kazhdoj zapisi tablicy montirovaniya soderzhatsya: * nomer ustrojstva, identificiruyushchij montirovannuyu fajlovuyu sistemu (upo- myanutyj vyshe logicheskij nomer fajlovoj sistemy); * ukazatel' na bufer, gde nahoditsya superblok fajlovoj sistemy; * ukazatel' na kornevoj indeks montirovannoj fajlovoj sistemy ("/" dlya fajlovoj sistemy s imenem "/dev/dsk1" na Risunke 5.22); * ukazatel' na indeks kataloga, stavshego tochkoj montirovaniya (na Risunke 5.22 eto katalog "usr", prinadlezhashchij kornevoj fajlovoj sisteme). Svyaz' indeksa tochki montirovaniya s kornevym indeksom montirovannoj faj- lovoj sistemy, voznikshaya v rezul'tate vypolneniya sistemnoj funkcii mount, daet yadru vozmozhnost' legko dvigat'sya po ierarhii fajlovyh sistem bez polu- cheniya ot pol'zovatelej dopolnitel'nyh svedenij. +------------------------------------------------------------+ | algoritm mount | | vhodnaya informaciya: imya blochnogo special'nogo fajla | | imya kataloga tochki montirovaniya | | opcii ("tol'ko dlya chteniya") | | vyhodnaya informaciya: otsutstvuet | | { | | esli (pol'zovatel' ne yavlyaetsya superpol'zovatelem) | | vozvratit' (oshibku); | | poluchit' indeks dlya blochnogo special'nogo fajla (algo- | | ritm namei); | | proverit' dopustimost' znachenij parametrov; | | poluchit' indeks dlya imeni kataloga, gde proizvoditsya | | montirovanie (algoritm namei); | | esli (indeks ne yavlyaetsya indeksom kataloga ili schetchik | | ssylok imeet znachenie > 1) | | { | | osvobodit' indeksy (algoritm iput); | | vozvratit' (oshibku); | | } | | najti svobodnoe mesto v tablice montirovaniya; | | zapustit' proceduru otkrytiya blochnogo ustrojstva dlya | | dannogo drajvera; | | poluchit' svobodnyj bufer iz bufernogo kesha; | | schitat' superblok v svobodnyj bufer; | | proinicializirovat' polya superbloka; | | poluchit' kornevoj indeks montiruemoj sistemy (algoritm | | iget), sohranit' ego v tablice montirovaniya; | | sdelat' pometku v indekse kataloga o tom, chto katalog | | yavlyaetsya tochkoj montirovaniya; | | osvobodit' indeks special'nogo fajla (algoritm iput); | | snyat' blokirovku s indeksa kataloga tochki montirovaniya;| | } | +------------------------------------------------------------+ Risunok 5.23. Algoritm montirovaniya fajlovoj sistemy 113 Na Risunke 5.23 pokazan algoritm montirovaniya fajlovoj sistemy. YAdro pozvolyaet montirovat' i demontirovat' fajlovye sistemy tol'ko tem processam, vladel'cem kotoryh yavlyaetsya superpol'zovatel'. Predostavlenie vozmozhnosti vypolnyat' funkcii mount i umount vsem pol'zovatelyam privelo by k vneseniyu s ih storony haosa v rabotu fajlovoj sistemy, kak umyshlennomu, tak i yavivshemu- sya rezul'tatom neostorozhnosti. Superpol'zovateli mogut razrushit' sistemu tol'ko sluchajno. YAdro nahodit indeks special'nogo fajla, predstavlyayushchego fajlovuyu siste- mu, podlezhashchuyu montirovaniyu, izvlekaet starshij i mladshij nomera, kotorye identificiruyut sootvetstvuyushchij diskovyj razdel, i vybiraet indeks kataloga, v kotorom fajlovaya sistema budet smontirovana. Schetchik ssylok v indekse ka- taloga dolzhen imet' znachenie, ne prevyshayushchee 1 (i men'she 1 on ne dolzhen byt' - pochemu?), v svyazi s nalichiem potencial'no opasnyh pobochnyh effektov (sm. uprazhnenie 5.27). Zatem yadro naznachaet svobodnoe mesto v tablice montirova- niya, pomechaet ego dlya ispol'zovaniya i prisvaivaet znachenie polyu nomera ust- rojstva v tablice. Vysheukazannye naznacheniya proizvodyatsya nemedlenno, pos- kol'ku vyzyvayushchij process mozhet priostanovit'sya, sleduya procedure otkrytiya ustrojstva ili schityvaya superblok fajlovoj sistemy, a drugoj process tem vremenem popytalsya by smontirovat' fajlovuyu sistemu. Pometiv dlya ispol'zova- niya zapis' v tablice montirovaniya, yadro ne dopuskaet ispol'zovaniya v dvuh vyzovah funkcii mount odnoj i toj zhe zapisi tablicy. Zapominaya nomer ustroj- stva s montiruemoj sistemoj, yadro mozhet vosprepyatstvovat' povtornomu monti- rovaniyu odnoj i toj zhe sistemy drugimi processami, kotoroe, bud' ono dopushche- no, moglo by privesti k nepredskazuemym posledstviyam (sm. uprazhnenie 5.26). YAdro vyzyvaet proceduru otkrytiya dlya blochnogo ustrojstva, soderzhashchego fajlovuyu sistemu, tochno tak zhe, kak ono delaet eto pri neposredstvennom otk- rytii blochnogo ustrojstva (glava 10). Procedura otkrytiya ustrojstva obychno proveryaet sushchestvovanie takogo ustrojstva, inogda proizvodya inicializaciyu struktur dannyh drajvera i posylaya komandy inicializacii apparature. Zatem yadro vydelyaet iz bufernogo pula svobodnyj bufer (variant algoritma getblk) dlya hraneniya superbloka montiruemoj fajlovoj sistemy i schityvaet superblok, ispol'zuya odin iz variantov algoritma read. YAdro sohranyaet ukazatel' na in- deks kataloga, v kotorom montiruetsya sistema, davaya vozmozhnost' marshrutam poiska fajlovyh imen, soderzhashchih imya "..", peresekat' tochku montirovaniya, kak my uvidim dal'she. Ono nahodit kornevoj indeks montiruemoj fajlovoj sis- temy i zapominaet ukazatel' na indeks v tablice montirovaniya. S tochki zreniya pol'zovatelya, mesto (tochka) montirovaniya i koren' fajlovoj sistemy logicheski ekvivalentny, i yadro uprochivaet etu ekvivalentnost' blagodarya ih sosushchestvo- vaniyu v odnoj zapisi tablicy montirovaniya. Processy bol'she ne mogut obra- shchat'sya k indeksu kataloga - tochki montirovaniya. YAdro inicializiruet polya v superbloke fajlovoj sistemy, ochishchaya polya dlya spiska svobodnyh blokov i spiska svobodnyh indeksov i ustanavlivaya chislo svobodnyh indeksov v superbloke ravnym 0. Cel'yu inicializacii (zadaniya na- chal'nyh znachenij polej) yavlyaetsya svedenie k minimumu opasnosti razrushit' fajlovuyu sistemu, esli montirovanie osushchestvlyaetsya posle avarijnogo zavershe- niya raboty sistemy. Esli yadro zastavit' dumat', chto v superbloke otsutstvuyut svobodnye indeksy, to eto privedet k zapusku algoritma ialloc, vedushchego po- isk na diske svobodnyh indeksov. K sozhaleniyu, esli spisok svobodnyh diskovyh blokov isporchen, yadro ne ispravlyaet etot spisok iznutri (sm. razdel 5.17 o soprovozhdenii fajlovoj sistemy). Esli pol'zovatel' montiruet fajlovuyu siste- mu tol'ko dlya chteniya, zapreshchaya provedenie vseh operacij zapisi v sisteme, yadro ustanavlivaet v superbloke sootvetstvuyushchij flag. Nakonec, yadro pomechaet indeks kataloga kak "tochku montirovaniya", chtoby drugie processy pozdnee mog- li ssylat'sya na nee. Na Risunke 5.24 predstavlen vid razlichnyh struktur dan- nyh po zavershenii vypolneniya funkcii mount. 114

    5.14.1 Peresechenie tochek montirovaniya v marshrutah poiska imen fajlov

Davajte povtorno rassmotrim povedenie algoritmov namei i iget v sluchayah, kogda marshrut poiska fajlov prohodit cherez tochku montirovaniya. Tochku monti- rovaniya mozhno peresech' dvumya sposobami: iz fajlovoj sistemy, gde proizvodit- sya montirovanie, v fajlovuyu sistemu, kotoraya montiruetsya (v napravlenii ot global'nogo kornya k listu), i v obratnom napravlenii. |ti sposoby illyustri- ruet sleduyushchaya posledovatel'nost' komand shell'a. Tablica indeksov Tablica montirovaniya +------------------+ +--------------------+ +------------------+ | | | Indeks kataloga, + - - + | | | gde proizvoditsya | | | | montirovanie | | | | +-------+ | Pomechen kak "toch-|<---+ | |+->| Bufer | | ka montirovaniya" | || | || +-------+ | Schetchik ssylok =1| | | || +------------------+ |+ >+--------------------+| | | | | Superblok ---++ +------------------+ +---+ Indeks tochki monti-| | Indeks ustrojstva| | rovaniya | | Ne ispol'zuetsya | +---+- Kornevoj indeks | | Schetchik ssylok =0| | +--------------------+ +------------------+ | | | +------------------+<---+ | | | Indeks kornya mon-| | | | tiruemoj fajlovoj| | | | sistemy | | | | Schetchik ssylok =1| +--------------------+ +------------------+ +------------------+ Risunok 5.24. Struktury dannyh posle montirovaniya mount /dev/dsk1 /usr cd /usr/src/uts cd ../../.. Po komande mount posle vypolneniya nekotoryh logicheskih proverok zapuska- etsya sistemnaya funkciya mount, kotoraya montiruet fajlovuyu sistemu v diskovom razdele s imenem "/dev/dsk1" pod upravleniem kataloga "/usr". Pervaya iz ko- mand cd (smenit' katalog) pobuzhdaet komandnyj processor shell vyzvat' sis- temnuyu funkciyu chdir, vypolnyaya kotoruyu, yadro analiziruet imya puti poiska, peresekayushchego tochku montirovaniya v "/usr". Vtoraya iz komand cd privodit k tomu, chto yadro analiziruet imya puti poiska i peresekaet tochku montirovaniya v tret'ej komponente ".." imeni. Dlya sluchaya peresecheniya tochki montirovaniya v napravlenii iz fajlovoj sis- temy, gde proizvoditsya montirovanie, v fajlovuyu sistemu, kotoraya montiruet- sya, rassmotrim modifikaciyu algoritma iget (Risunok 5.25), kotoraya identichna versii algoritma, privedennoj na Risunke 4.3, pochti vo vsem, za isklyucheniem togo, chto v dannoj modifikacii proizvoditsya proverka, yavlyaetsya li indeks in- deksom tochki montirovaniya. Esli indeks imeet sootvetstvuyushchuyu pometku, yadro soglashaetsya, chto eto indeks tochki montirovaniya. Ono obnaruzhivaet v tablice montirovaniya zapis' s ukazannym indeksom tochki montirovaniya i zapominaet no- mer ustrojstva montiruemoj fajlovoj sistemy. Zatem, ispol'zuya nomer ustrojs- tva i nomer indeksa kornya, obshchego dlya vseh fajlovyh sistem, yadro obrashchaetsya k indeksu kornya 115 +------------------------------------------------------------+ | algoritm iget | | vhodnaya informaciya: nomer indeksa v fajlovoj sisteme | | vyhodnaya informaciya: zablokirovannyj indeks | | { | | vypolnit' | | { | | esli (indeks v indeksnom keshe) | | { | | esli (indeks zablokirovan) | | { | | priostanovit'sya (do osvobozhdeniya indeksa); | | prodolzhit'; /* cikl s usloviem prodolzheniya */ | | } | | /* special'naya obrabotka dlya tochek montirovaniya */ | | esli (indeks yavlyaetsya indeksom tochki montirovaniya) | | { | | najti zapis' v tablice montirovaniya dlya tochki mon- | | tirovaniya; | | poluchit' novyj nomer fajlovoj sistemy iz tablicy | | montirovaniya; | | ispol'zovat' nomer indeksa kornya dlya prosmotra; | | prodolzhit'; /* prodolzhenie cikla */ | | } | | esli (indeks v spiske svobodnyh indeksov) | | ubrat' iz spiska svobodnyh indeksov; | | uvelichit' schetchik ssylok dlya indeksa; | | vozvratit' (indeks); | | } | | | | /* indeks otsutstvuet v indeksnom keshe */ | | ubrat' novyj indeks iz spiska svobodnyh indeksov; | | sbrosit' nomer indeksa i fajlovoj sistemy; | | ubrat' indeks iz staroj hesh-ocheredi, pomestit' v novuyu;| | schitat' indeks s diska (algoritm bread); | | inicializirovat' indeks (naprimer, ustanoviv schetchik | | ssylok v 1); | | vozvratit' (indeks); | | } | | } | +------------------------------------------------------------+ Risunok 5.25. Modifikaciya algoritma polucheniya dostupa k in- deksu montiruemogo ustrojstva i vozvrashchaet pri vyhode iz funkcii etot indeks. V pervom primere smeny kataloga yadro obrashchaetsya k indeksu kataloga "/usr" iz fajlovoj sistemy, v kotoroj proizvoditsya montirovanie, obnaruzhivaet, chto etot indeks imeet pometku "tochka montirovaniya", nahodit v tablice montirova- niya indeks kornya montiruemoj fajlovoj sistemy i obrashchaetsya k etomu indeksu. Dlya vtorogo sluchaya peresecheniya tochki montirovaniya v napravlenii iz faj- lovoj sistemy, kotoraya montiruetsya, v fajlovuyu sistemu, gde vypolnyaetsya mon- tirovanie, rassmotrim modifikaciyu algoritma namei (Risunok 5.26). Ona pohozha na versiyu algoritma, privedennuyu na Risunke 4.11. Odnako, posle obnaruzheniya v kataloge nomera indeksa dlya dannoj komponenty puti poiska yadro proveryaet, ne ukazyvaet li nomer indeksa na to, chto eto kornevoj indeks fajlovoj siste- my. Esli eto tak i esli tekushchij rabochij indeks tak zhe yavlyaetsya kornevym, a 116 +------------------------------------------------------------+ | algoritm namei /* prevrashchenie imeni puti poiska v indeks */| | vhodnaya informaciya: imya puti poiska | | vyhodnaya informaciya: zablokirovannyj indeks | | { | | esli (put' poiska beret nachalo s kornya) | | rabochij indeks = indeksu kornya (algoritm iget); | | v protivnom sluchae | | rabochij indeks = indeksu tekushchego kataloga | | (algoritm iget); | | | | vypolnit' (poka put' poiska ne konchilsya) | | { | | schitat' sleduyushchuyu komponentu imeni puti poiska; | | proverit' sootvetstvie rabochego indeksa katalogu | | i prava dostupa; | | esli (rabochij indeks sootvetstvuet kornyu i kompo- | | nenta imeni "..") | | prodolzhit'; /* cikl s usloviem prodolzheniya */| | poisk komponenty: | | schitat' katalog (rabochij indeks), povtoryaya algo- | | ritmy bmap, bread i brelse; | | esli (komponenta sootvetstvuet zapisi v kataloge | | (rabochem indekse)) | | { | | poluchit' nomer indeksa dlya sovpavshej komponen-| | ty; | | esli (najdennyj indeks yavlyaetsya indeksom kor- | | nya i rabochij indeks yavlyaetsya indeksom kornya | | i imya komponenty "..") | | { | | /* peresechenie tochki montirovaniya */ | | poluchit' zapis' v tablice montirovaniya dlya | | rabochego indeksa; | | osvobodit' rabochij indeks (algoritm iput); | | rabochij indeks = indeksu tochki montirovaniya;| | zablokirovat' indeks tochki montirovaniya; | | uvelichit' znachenie schetchika ssylok na rabo- | | chij indeks; | | perejti k poisku komponenty (dlya ".."); | | } | | osvobodit' rabochij indeks (algoritm iput); | | rabochij indeks = indeksu s novym nomerom | | (algoritm iget); | | } | | v protivnom sluchae /* komponenta otsutstvuet v | | kataloge */ | | vozvratit' (net indeksa); | | } | | vozvratit' (rabochij indeks); | | } | +------------------------------------------------------------+ Risunok 5.26. Modifikaciya algoritma sintaksicheskogo analiza imeni fajla komponenta puti poiska, v svoyu ochered', imeet imya "..", yadro identificiruet indeks kak tochku montirovaniya. Ono nahodit v tablice montirovaniya zapis', 117 nomer ustrojstva v kotoroj sovpadaet s nomerom ustrojstva dlya poslednego iz najdennyh indeksov, poluchaet indeks dlya kataloga, v kotorom proizvoditsya montirovanie, i prodolzhaet poisk komponenty s imenem "..", ispol'zuya tol'ko chto poluchennyj indeks v kachestve rabochego. V korne fajlovoj sistemy, tem ne menee, kornevym katalogom yavlyaetsya "..". V vysheprivedennom primere (cd "../../..") predpolagaetsya, chto v nachale process imeet tekushchij katalog s imenem "/usr/src/uts". Kogda imya puti poiska podvergaetsya analizu v algoritme namei, nachal'nym rabochim indeksom yavlyaetsya indeks tekushchego kataloga. YAdro menyaet tekushchij rabochij indeks na indeks kata- loga s imenem "/usr/src" v rezul'tate rasshifrovki pervoj komponenty ".." v imeni puti poiska. Zatem yadro analiziruet vtoruyu komponentu ".." v imeni pu- ti poiska, nahodit kornevoj indeks smontirovannoj (pered etim) fajlovoj sis- temy - indeks kataloga "usr" - i delaet ego rabochim indeksom pri analize imeni s pomoshch'yu algoritma namei. Nakonec, ono rasshifrovyvaet tret'yu kompo- nentu ".." v imeni puti poiska. YAdro obnaruzhivaet, chto nomer indeksa dlya ".." sovpadaet s nomerom kornevogo indeksa, rabochim indeksom yavlyaetsya korne- voj indeks, a ".." yavlyaetsya tekushchej komponentoj imeni puti poiska. YAdro na- hodit zapis' v tablice montirovaniya, sootvetstvuyushchuyu tochke montirovaniya "usr", osvobozhdaet tekushchij rabochij indeks (koren' fajlovoj sistemy, smonti- rovannoj v kataloge "usr") i naznachaet indeks tochki montirovaniya (kataloga "usr" v kornevoj fajlovoj sisteme) v kachestve novogo rabochego indeksa. Zatem ono prosmatrivaet zapisi v kataloge tochki montirovaniya "/usr" v poiskah ime- ni ".." i nahodit nomer indeksa dlya kornya fajlovoj sistemy ("/"). Posle eto- go sistemnaya funkciya chdir zavershaetsya kak obychno, vyzyvayushchij process ne ob- rashchaet vnimaniya na tot fakt, chto on peresek tochku montirovaniya.

    5.14.2 Demontirovanie fajlovoj sistemy

Sintaksis vyzova sistemnoj funkcii umount: umount(special filename); gde special filename ukazyvaet demontiruemuyu fajlovuyu sistemu. Pri demonti- rovanii fajlovoj sistemy (Risunok 5.27) yadro obrashchaetsya k indeksu demontiru- emogo ustrojstva, vosstanavlivaet nomer ustrojstva dlya special'nogo fajla, osvobozhdaet indeks (algoritm iput) i nahodit v tablice montirovaniya zapis' s nomerom ustrojstva, ravnym nomeru ustrojstva dlya special'nogo fajla. Prezhde chem yadro dejstvitel'no demontiruet fajlovuyu sistemu, ono dolzhno udostove- rit'sya v tom, chto v sisteme ne ostalos' ispol'zuemyh fajlov, dlya etogo yadro prosmatrivaet tablicu indeksov v poiskah vseh fajlov, chej nomer ustrojstva sovpadaet s nomerom demontiruemoj sistemy. Aktivnym fajlam sootvetstvuet po- lozhitel'noe znachenie schetchika ssylok i v ih chislo vhodyat tekushchij katalog processa, fajly s razdelyaemym tekstom, kotorye ispolnyayutsya v tekushchij moment (glava 7), i otkrytye kogda-to fajly, kotorye potom ne byli zakryty. Esli kakie-nibud' fajly iz fajlovoj sistemy aktivny, funkciya umount zavershaetsya neudachno: esli by ona proshla uspeshno, aktivnye fajly sdelalis' by 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 prava dostupa i raspolozhenie blokov, a obshchij indeks soderzhit nomer ustrojstva, nomer in- deksa na diske, tip fajla, razmer, informaciyu o vladel'ce i schetchik ssylok. Drugaya chastnaya informaciya, opisyvayushchaya otdel'nuyu fajlovuyu sistemu, soderzhit- sya v superbloke i strukture katalogov. Na Risunke 5.34 izobrazheny tablica obshchih indeksov v pamyati i dve tablicy chastnyh indeksov otdel'nyh fajlovyh sistem, odna dlya struktur fajlovoj sistemy versii V, a drugaya dlya indeksa udalennoj (setevoj) sistemy. Predpolagaetsya, chto poslednij indeks soderzhit dostatochno informacii dlya togo, chtoby identificirovat' fajl, nahodyashchijsya v udalennoj sisteme. U fajlovoj sistemy mozhet otsutstvovat' struktura, podob- naya indeksu; no ishodnyj tekst programm otdel'noj fajlovoj sistemy pozvolyaet sozdat' ob®ektnyj kod, udovletvoryayushchij semanticheskim trebovaniyam fajlovoj sistemy UNIX i naznachayushchij svoj "indeks", kotoryj sootvetstvuet obshchemu in- deksu, naznachaemomu yadrom. Fajlovaya sistema kazhdogo tipa imeet nekuyu strukturu, v kotoroj hranyatsya adresa funkcij, realizuyushchih abstraktnye dejstviya. Kogda yadru nuzhno obratit'- sya k fajlu, ono vyzyvaet kosvennuyu funkciyu v zavisimosti ot tipa fajlovoj sistemy i abstraktnogo dejstviya (sm. Risunok 5.34). Primerami abstraktnyh dejstvij yavlyayutsya: otkrytie i zakrytie fajla, chtenie i zapis' dannyh, vozv- rashchenie indeksa dlya komponenty imeni fajla (podobno namei i iget), osvobozh- denie indeksa (podobno iput), korrekciya indeksa, proverka prav dostupa, us- tanovka atributov fajla (prav dostupa k nemu), a takzhe montirovanie i demon- tirovanie fajlovyh sistem. V glave 13 budet proillyustrirovano ispol'zovanie sistemnyh abstrakcij pri rassmotrenii raspredelennoj fajlovoj sistemy.

    5.18 SOPROVOZHDENIE FAJLOVOJ SISTEMY

YAdro podderzhivaet celostnost' sistemy v svoej obychnoj rabote. Tem ne me- nee, takie chrezvychajnye obstoyatel'stva, kak otkaz pitaniya, mogut privesti k fatal'nomu sboyu sistemy, v rezul'tate kotorogo soderzhimoe sistemy utrachivaet svoyu soglasovannost': bol'shinstvo dannyh v fajlovoj sisteme dostupno dlya is- pol'zovaniya, no nekotoraya nesoglasovannost' mezhdu nimi imeet mesto. Komanda fsck proveryaet soglasovannost' dannyh i v sluchae neobhodimosti vnosit v faj- lovuyu sistemu ispravleniya. Ona obrashchaetsya k fajlovoj sisteme cherez blochnyj ili strokovyj interfejs (glava 10) v obhod tradicionnyh metodov dostupa k fajlam. V etom razdele rassmatrivayutsya nekotorye primery protivorechivosti dannyh, kotoraya obnaruzhivaetsya komandoj fsck. Diskovyj blok mozhet prinadlezhat' bolee chem odnomu indeksu ili spisku svobodnyh blokov. Kogda fajlovaya sistema otkryvaetsya v pervyj raz, vse dis- kovye bloki nahodyatsya v spiske svobodnyh blokov. Kogda diskovyj blok vybira- etsya dlya ispol'zovaniya, yadro udalyaet ego nomer iz spiska svobodnyh blokov i naznachaet blok indeksu. YAdro ne mozhet perenaznachit' diskovyj blok drugomu indeksu do teh por, poka blok ne budet vozvrashchen v spisok svobodnyh blokov. Takim obrazom, diskovyj blok mozhet libo nahodit'sya v spiske svobodnyh blo- kov, libo byt' naznachennym odnomu iz indeksov. Rassmotrim razlichnye situa- cii, mogushchie imet' mesto pri osvobozhdenii yadrom diskovogo bloka, prinadle- zhavshego fajlu, s vozvrashcheniem nomera bloka v superblok, nahodyashchijsya v pamya- ti, i pri vydelenii diskovogo bloka novomu fajlu. Esli yadro zapisyvalo na disk indeks i bloki novogo fajla, no pered vneseniem izmenenij v indeks prezhnego fajla na diske proizoshel sboj, oba indeksa budut adresovat' k odno- 130 mu i tomu zhe nomeru diskovogo bloka. Podobnym zhe obrazom, esli yadro perepi- syvalo na disk superblok i ego spiski svobodnyh resursov i pered perepis'yu starogo indeksa sluchilsya sboj, diskovyj blok poyavitsya odnovremenno i v spis- ke svobodnyh blokov, i v starom indekse. Esli blok otsutstvuet kak v spiske svobodnyh blokov, tak i v fajle, faj- lovaya sistema yavlyaetsya nesoglasovannoj, ibo, kak uzhe govorilos' vyshe, vse bloki obyazany gde-nibud' prisutstvovat'. Takaya situaciya mogla by proizojti, esli by blok byl udalen iz fajla i pomeshchen v spisok svobodnyh blokov v su- perbloke. Esli proizvodilas' zapis' prezhnego fajla na disk i sistema dala sboj pered zapis'yu superbloka, blok budet otsutstvovat' vo vseh spiskah, hranyashchihsya na diske. Indeks mozhet imet' schetchik svyazej s nenulevym znacheniem pri tom, chto ego nomer otsutstvuet vo vseh katalogah fajlovoj sistemy. Vse fajly, za isklyuche- niem kanalov (nepoimenovannyh), dolzhny prisutstvovat' v drevovidnoj struktu- re fajlovoj sistemy. Esli sistema dala sboj posle sozdaniya kanala ili obych- nogo fajla, no pered sozdaniem sootvetstvuyushchej etomu kanalu ili fajlu tochki vhoda v katalog, indeks budet imet' v pole schetchika svyazej ustanovlennoe znachenie, pust' dazhe on yavno ne prisutstvuet v fajlovoj sisteme. Eshche odna problema mozhet vozniknut', esli s pomoshch'yu funkcii unlink byla udalena svyaz' kataloga bez proverki udaleniya iz kataloga vseh soderzhashchihsya v nem svyazej s otdel'nymi fajlami. Esli format indeksa neveren (naprimer, esli znachenie polya tipa fajla ne opredeleno), znachit gde-to imeetsya oshibka. |to mozhet proizojti, esli admi- nistrator smontiroval fajlovuyu sistemu, kotoraya otformatirovana nepravil'no. YAdro obrashchaetsya k tem diskovym blokam, kotorye, kak kazhetsya yadru, soderzhat indeksy, no v dejstvitel'nosti okazyvaetsya, chto oni soderzhat dannye. Esli nomer indeksa prisutstvuet v zapisi kataloga, no sam indeks svobo- den, fajlovaya sistema yavlyaetsya nesoglasovannoj, poskol'ku nomer indeksa v zapisi kataloga dolzhen byt' nomerom naznachennogo indeksa. |to moglo by proi- zojti, esli by yadro, sozdavaya novyj fajl i zapisyvaya na disk novuyu tochku vhoda v katalog, ne uspela by skopirovat' na disk indeks fajla iz-za sboya. Takzhe eto mozhet sluchit'sya, esli process, udalyaya svyaz' fajla s katalogom, za- pishet osvobodivshijsya indeks na disk, no ne uspeet otkorrektirovat' katalog iz-za sboya. Vozniknovenie podobnyh situacij mozhno predotvratit', kopiruya na disk rezul'taty raboty v nadlezhashchem poryadke. Esli chislo svobodnyh blokov ili svobodnyh indeksov, zapisannoe v superb- loke, ne sovpadaet s ih kolichestvom na diske, fajlovaya sistema tak zhe yavlya- etsya nesoglasovannoj. Itogovaya informaciya v superbloke vsegda dolzhna soot- vetstvovat' informacii o tekushchem sostoyanii fajlovoj sistemy.

    5.19 VYVODY

|toj glavoj zavershaetsya pervaya chast' knigi, posvyashchennaya rassmotreniyu osobennostej fajlovoj sistemy. Glava poznakomila pol'zovatelya s tremya tabli- cami, prinadlezhashchimi yadru: tablicej pol'zovatel'skih deskriptorov fajla, sistemnoj tablicej fajlov i tablicej montirovaniya. V nej rassmotreny algo- ritmy vypolneniya sistemnyh funkcij, imeyushchih otnoshenie k fajlovoj sisteme, i vzaimodejstvie mezhdu etimi funkciyami. Issledovany nekotorye abstraktnye svojstva fajlovoj sistemy, pozvolyayushchie sisteme UNIX podderzhivat' fajlovye sistemy razlichnyh tipov. Nakonec, opisan mehanizm vypolneniya komandy fsck, kontroliruyushchej celostnost' i soglasovannost' dannyh v fajlovoj sisteme.

    5.20 UPRAZHNENIYA

1. Rassmotrim programmu, privedennuyu na Risunke 5.35. Kakoe znachenie voz- vrashchaet kazhdaya operaciya read i chto pri etom soderzhitsya v bufere ? Opi- 131 shite, chto proishodit v yadre vo vremya vypolneniya kazhdogo vyzova read. 2. Vnov' vernemsya k programme na Risunke 5.35 i predpolozhim, chto operator lseek(fd,9000L,0); stoit pered pervym obrashcheniem k funkcii read. CHto ishchet process i chto pri etom proishodit v yadre ? 3. Process mozhet otkryt' fajl dlya raboty v rezhime dobavleniya zapisej v konec fajla, pri etom imeetsya v vidu, chto kazhdaya operaciya zapisi ras- polagaet dannye po adresu smeshcheniya, ukazyvayushchego tekushchij konec fajla. Takim obrazom, dva processa mogut otkryt' fajl dlya raboty v rezhime do- bavleniya zapisej v konec fajla i vvodit' dannye, ne opasayas' zateret' zapisi drug drugu. CHto proizojdet, esli process otkroet fajl v rezhime dobavleniya v konec, a zapisyvayushchuyu golovku ustanovit na nachalo fajla ? 4. Biblioteka standartnyh podprogramm vvoda-vyvoda povyshaet effektivnost' vypolneniya pol'zovatelem operacij chteniya i zapisi blagodarya buferiza- cii dannyh v biblioteke i sohraneniyu bol'shogo kolichestva modulej obra- shcheniya k operacionnoj sisteme, neobhodimyh pol'zovatelyu. Kak by vy rea- lizovali bibliotechnye funkcii fread i fwrite ? CHto dolzhny delat' bib- liotechnye funkcii fopen i fclose ? +------------------------------------------------------------+ | #include | | main() | | { | | int fd; | | char buf[1024]; | | fd = creat("junk",0666); | | lseek(fd,2000L,2); /* ishchetsya bajt s nomerom 2000 */ | | write(fd,"hello",5); | | close(fd); | | | | fd = open("junk",O_RDONLY); | | read(fd,buf,1024); /* chitaet nuli */ | | read(fd,buf,1024); /* schityvaet nechto, otlichnoe ot 0 */| | read(fd,buf,1024); | | } | +------------------------------------------------------------+ Risunok 5.35. Schityvanie nulej i konca fajla 5. Esli process chitaet dannye iz fajla posledovatel'no, yadro zapominaet znachenie bloka, prochitannogo s prodvizheniem, v indekse, hranyashchemsya v pamyati. CHto proizojdet, esli neskol'ko processov budut odnovremenno vesti posledovatel'noe schityvanie dannyh iz odnogo i togo zhe fajla ? +---------------------------------------------------------+ | #include | | main() | | { | | int fd; | | char buf[256]; | | | | fd = open("/etc/passwd",O_RDONLY); | | if (read(fd,buf,1024) < 0) | | printf("chtenie zavershaetsya neudachno\n"); | | } | +---------------------------------------------------------+ Risunok 5.36. CHtenie bol'shoj porcii dannyh v malen'kij bufer 132 6. Rassmotrim programmu, privedennuyu na Risunke 5.36. CHto proizojdet v rezul'tate vypolneniya programmy ? Obosnujte otvet. CHto proizoshlo by, esli by ob®yavlenie massiva buf bylo vstavleno mezhdu ob®yavleniyami dvuh drugih massivov razmerom 1024 elementa kazhdyj ? Kakim obrazom yadro us- tanavlivaet, chto prochitannaya porciya dannyh slishkom velika dlya bufera ? *7. V fajlovoj sisteme BSD razreshaetsya fragmentirovat' poslednij blok faj- la v sootvetstvii so sleduyushchimi pravilami: * Svobodnye fragmenty otslezhivayutsya v strukturah, podobnyh superbloku; * YAdro ne podderzhivaet pul ranee vydelennyh svobodnyh fragmentov, a razbivaet na fragmenty v sluchae neobhodimosti svobodnyj blok; * YAdro mozhet naznachat' fragmenty bloka tol'ko dlya poslednego bloka v fajle; * Esli blok razbit na neskol'ko fragmentov, yadro mozhet naznachit' ih razlichnym fajlam; * Kolichestvo fragmentov v bloke ne dolzhno prevyshat' velichinu, fiksiro- vannuyu dlya dannoj fajlovoj sistemy; * YAdro naznachaet fragmenty vo vremya vypolneniya sistemnoj funkcii write. Razrabotajte algoritm, prisoedinyayushchij k fajlu fragmenty bloka. Kakie izmeneniya dolzhny byt' sdelany v indekse, chtoby pozvolit' ispol'zovanie fragmentov ? Kakie preimushchestva s sistemnoj tochki zreniya predostavlyaet ispol'zovanie fragmentov dlya teh fajlov, kotorye ispol'zuyut bloki kos- vennoj adresacii ? Ne vygodnee li bylo by naznachat' fragmenty vo vremya vypolneniya funkcii close vmesto togo, chtoby naznachat' ih pri vypolne- nii funkcii write ? *8. Vernemsya k obsuzhdeniyu, nachatomu v glave 4 i kasayushchemusya raspolozheniya dannyh v indekse fajla. Dlya togo sluchaya, kogda indeks imeet razmer diskovogo bloka, razrabotajte algoritm, po kotoromu ostatok dannyh fajla perepisyvaetsya v indeksnyj blok, esli pomeshchaetsya tuda. Sravnite etot metod s metodom, predlozhennym dlya resheniya predydushchej problemy. *9. V versii V sistemy funkciya fcntl ispol'zuetsya dlya realizacii mehanizma zahvata fajla i zapisi i imeet sleduyushchij format: fcntl(fd,cmd,arg); gde fd - deskriptor fajla, cmd - tip blokiruyushchej operacii, a v arg ukazyvayutsya razlichnye parametry, takie kak tip blokirovki (zapisi ili chteniya) i smeshcheniya v bajtah (sm. prilozhenie). K blokiruyushchim operaciyam otnosyatsya * Proverka nalichiya blokirovok, prinadlezhashchih drugim processam, s ne- medlennym vozvratom upravleniya v sluchae obnaruzheniya takih blokiro- vok, * Ustanovka blokirovki i priostanov do uspeshnogo zaversheniya, * Ustanovka blokirovki s nemedlennym vozvratom upravleniya v sluchae ne- udachi. YAdro avtomaticheski snimaet blokirovki, ustanovlennye processom, pri zakrytii fajla. Opishite rabotu algoritma, realizuyushchego zahvat fajla i zapisi. Esli blokirovki yavlyayutsya obyazatel'nymi, drugim processam sle- duet zapretit' dostup k fajlu. Kakie izmeneniya sleduet sdelat' v ope- raciyah chteniya i zapisi ? *10. Esli process priostanovil svoyu rabotu v ozhidanii snyatiya s fajla bloki- rovki, voznikaet opasnost' vzaimnoj blokirovki: process A mozhet zablo- kirovat' fajl "one" i popytat'sya zablokirovat' fajl "two", a process B mozhet zablokirovat' fajl "two" i popytat'sya zablokirovat' fajl "one". Oba processa perejdut v sostoyanie, pri kotorom oni ne smogut prodol- zhit' svoyu rabotu. Rasshir'te algoritm resheniya predydushchej problemy takim obrazom, chtoby yadro moglo obnaruzhivat' situacii vzaimnoj blokirovki i preryvat' vypolnenie sistemnyh funkcij. Sleduet li poruchat' obnaruzhe- nie vzaimnyh blokirovok yadru ? 11. Do sushchestvovaniya special'noj sistemnoj funkcii zahvata fajla pol'zova- telyam prihodilos' pribegat' k uslugam parallel'no dejstvuyushchih proces- 133 sov dlya realizacii mehanizma zahvata putem vyzova sistemnyh funkcij, vypolnyayushchih elementarnye dejstviya. Kakie iz sistemnyh funkcij, opisan- nyh v etoj glave, mogli by ispol'zovat'sya ? Kakie opasnosti podstere- gayut pri ispol'zovanii etih metodov ? 12. Richi zayavlyal (sm. [Ritchie 81]), chto zahvata fajla nedostatochno dlya togo, chtoby predotvratit' putanicu, vyzyvaemuyu takimi programmami, kak redaktory, kotorye sozdayut kopiyu fajla pri redaktirovanii i perepisy- vayut pervonachal'nyj fajl po okonchanii raboty. Ob®yasnite, chto on imel v vidu, i prokommentirujte. 13. Rassmotrim eshche odin sposob blokirovki fajlov, predotvrashchayushchij razrushi- tel'nye posledstviya korrektirovki. Predpolozhim, chto v indekse soder- zhitsya novaya ustanovka prav dostupa, pozvolyayushchaya tol'ko odnomu processu v tekushchij moment otkryvat' fajl dlya zapisi i neskol'kim processam otk- ryvat' fajl dlya chteniya. Opishite realizaciyu etogo sposoba. +----------------------------------------------------------+ | main(argc,argv) | | int argc; | | char *argv[]; | | { | | if (argc != 2) | | { | | printf("vvedite: komanda imya kataloga\n"); | | exit(); | | } | | | | /* prava dostupa k katalogu: zapis', chtenie i is- | | polnenie razresheny dlya vseh */ | | /* tol'ko superpol'zovatel' mozhet delat' sleduyu- | | shchee */ | | if (mknod(argv[1],040777,0) == -1) | | printf("mknod zavershilas' neudachno\n"); | | } | +----------------------------------------------------------+ Risunok 5.37. Katalog, sozdanie kotorogo ne zaversheno *14. Rassmotrim programmu (Risunok 5.37), kotoraya sozdaet katalog s never- nym formatom (v kataloge otsutstvuyut zapisi s imenami "." i ".."). Poprobujte, nahodyas' v etom kataloge, vypolnit' neskol'ko komand, ta- kih kak ls -l, ls -ld, ili cd. CHto proizojdet pri etom ? 15. Napishite programmu, kotoraya vyvodit dlya fajlov, imena kotoryh ukazany v kachestve parametrov, informaciyu o vladel'ce, tipe fajla, pravah dos- tupa i vremeni dostupa. Esli fajl (parametr) yavlyaetsya katalogom, prog- ramma dolzhna chitat' zapisi iz kataloga i vyvodit' vysheukazannuyu infor- maciyu dlya vseh fajlov v kataloge. 16. Predpolozhim, chto u pol'zovatelya est' razreshenie na chtenie iz kataloga, no net razresheniya na ispolnenie. CHto proizojdet, esli katalog ispol'- zovat' v kachestve parametra komandy ls, zadannoj s opciej "-i" ? CHto budet, esli ukazana opciya "-l" ? Poyasnite svoi otvety. Otvet'te na vopros, sformulirovannyj dlya sluchaya, kogda est' razreshenie na ispolne- nie, no net razresheniya na chtenie iz kataloga. 17. Sravnite prava dostupa, kotorye dolzhny byt' u processa dlya vypolneniya sleduyushchih dejstvij, i prokommentirujte: * Dlya sozdaniya novogo fajla trebuetsya razreshenie na zapis' v katalog. * Dlya "sozdaniya" sushchestvuyushchego fajla trebuetsya razreshenie na zapis' v fajl. * Dlya udaleniya svyazi fajla s katalogom trebuetsya razreshenie na zapis' 134 v katalog, a ne v fajl. *18. Napishite programmu, kotoraya naveshchaet vse katalogi, nachinaya s tekushchego. Kak ona dolzhna upravlyat' ciklami v ierarhii katalogov ? 19. Vypolnite programmu, privedennuyu na Risunke 5.38, i ob®yasnite, chto pri etom proishodit v yadre. (Namek: vypolnite komandu pwd, kogda programma zakonchitsya). 20. Napishite programmu, kotoraya zamenyaet kornevoj katalog ukazannym kata- logom, i issledujte derevo katalogov, dostupnoe dlya etoj programmy. 21. Pochemu process ne mozhet otmenit' predydushchij vyzov funkcii chroot ? Iz- menite konkretnuyu realizaciyu processa takim obrazom, chtoby on mog me- nyat' tekushchee znachenie kornya na predydushchee. Kakie u etoj vozmozhnosti preimushchestva i neudobstva ? 22. Rassmotrim prostoj primer kanala (Risunok 5.19), kogda process zapisy- vaet v kanal stroku "hello" i zatem schityvaet +----------------------------------------------------------+ | main(argc,argv) | | int argc; | | char *argv[]; | | { | | if (argc != 2) | | { | | printf("nuzhen 1 argument - imya kataloga\n"); | | exit(); | | } | | | | if (chdir(argv[1]) == -1) | | printf("%s fajl ne yavlyaetsya katalogom\n",argv[1]);| | } | +----------------------------------------------------------+ Risunok 5.38. Primer programmy s ispol'zovaniem funkcii chdir ee. CHto proizoshlo by, esli by massiv dlya zapisi dannyh v kanal imel razmer 1024 bajta vmesto 6 (a ob®em schityvaemyh za odnu operaciyu dan- nyh ostavalsya ravnym 6) ? CHto proizojdet, esli poryadok vyzova funkcij read i write v programme izmenit', pomenyav funkcii mestami ? 23. CHto proizojdet pri vypolnenii programmy, illyustriruyushchej ispol'zovanie poimenovannyh kanalov (Risunok 5.19), esli funkciya mknod obnaruzhit, chto kanal s takim imenem uzhe sushchestvuet ? Kak etot moment realizuetsya yadrom ? CHto proizoshlo by, esli by vmesto podrazumevaemyh v tekste programmy odnogo schityvayushchego i odnogo zapisyvayushchego processov svyaz' mezhdu soboj cherez kanal popytalis' ustanovit' neskol'ko schityvayushchih i zapisyvayushchih processov ? Kak v etom sluchae garantirovalas' by svyaz' odnogo schityvayushchego processa s odnim zapisyvayushchim processom ? 24. Otkryvaya poimenovannyj kanal dlya chteniya, process priostanavlivaetsya do teh por, poka eshche odin process ne otkroet kanal dlya zapisi. Pochemu ? Ne mog by process uspeshno projti funkciyu open, prodolzhit' rabotu do togo momenta, kogda im budet predprinyata popytka chteniya dannyh iz ka- nala, i priostanovit'sya pri vypolnenii funkcii read ? 25. Kak by vy realizovali algoritm vypolneniya sistemnoj funkcii dup2 (iz versii 7), vyzyvaemoj sleduyushchim obrazom: dup2(oldfd,newfd); gde oldfd - fajlovyj deskriptor, kotoryj dubliruetsya deskriptorom newfd ? CHto proizoshlo by, esli by deskriptor newfd uzhe prinadlezhal ot- krytomu fajlu? *26. Kakie posledstviya imelo by reshenie yadra pozvolit' dvum processam od- novremenno smontirovat' odnu i tu zhe fajlovuyu sistemu v dvuh tochkah montirovaniya ? 135 27. Predpolozhim, chto odin process menyaet svoj tekushchij katalog na katalog "/mnt/a/b/c", posle chego drugoj process v kataloge "/mnt" montiruet fajlovuyu sistemu. Zavershitsya li funkciya mount uspeshno ? CHto proizoj- det, esli pervyj process vypolnit komandu pwd ? YAdro ne pozvolit funk- cii mount uspeshno zavershit'sya, esli znachenie schetchika ssylok v indekse kataloga "/mnt" prevyshaet 1. Prokommentirujte etot moment. 28. Pri ispolnenii algoritma peresecheniya tochki montirovaniya po imeni ".." v marshrute poiska fajla yadro proveryaet vypolnenie treh uslovij, svya- zannyh s tochkoj montirovaniya: chto nomer obnaruzhennogo indeksa sovpada- et s nomerom kornevogo indeksa, chto rabochij indeks yavlyaetsya kornem fajlovoj sistemy i chto imya komponenty marshruta poiska - "..". Pochemu neobhodimo proveryat' vypolnenie vseh treh uslovij ? Dokazhite, chto pro- verki lyubyh dvuh uslovij nedostatochno dlya togo, chtoby razreshit' pro- cessu peresech' tochku montirovaniya. 29. Esli pol'zovatel' montiruet fajlovuyu sistemu tol'ko dlya chteniya, yadro ustanavlivaet sootvetstvuyushchij flag v superbloke. Kak yadro mozhet vosp- repyatstvovat' vypolneniyu operacij zapisi v funkciyah write, creat, link, unlink, chown i chmod ? Kakogo roda informaciyu zapisyvayut v faj- lovuyu sistemu vse perechislennye funkcii ? *30. Predpolozhim, chto odin process pytaetsya demontirovat' fajlovuyu sistemu, v to vremya kak drugoj process pytaetsya sozdat' v fajlovoj sisteme no- vyj fajl. Tol'ko odna iz funkcij umount i creat vypolnitsya uspeshno. Podrobno rassmotrite voznikshuyu konkurenciyu. *31. Kogda funkciya umount proveryaet otsutstvie v fajlovoj sisteme aktivnyh fajlov, voznikaet odna problema, svyazannaya s tem, chto kornevoj indeks fajlovoj sistemy, naznachaemyj pri vypolnenii funkcii mount s pomoshch'yu algoritma iget, imeet schetchik ssylok s polozhitel'nym znacheniem. Kak funkciya umount smozhet ubedit'sya v otsutstvii aktivnyh fajlov i otchi- tat'sya pered kornem fajlovoj sistemy ? Rassmotrite dva sluchaya: * funkciya umount osvobozhdaet kornevoj indeks po algoritmu iput pered proverkoj aktivnyh indeksov. (Kak funkcii vernut' etot indeks obrat- no, esli budut obnaruzheny aktivnye fajly ?) * funkciya umount proveryaet otsutstvie aktivnyh fajlov do togo, kak os- vobodit' kornevoj indeks, i razreshaya kornevomu indeksu ostavat'sya aktivnym. (Naskol'ko aktivnym mozhet byt' kornevoj indeks ?) 32. Obratite vnimanie na to, chto pri vypolnenii komandy ls -ld kolichestvo svyazej s katalogom nikogda ne ravno 1. Pochemu ? 33. Kak rabotaet komanda mkdir (sozdat' novyj katalog) ? (Navodyashchij vop- ros: kakie nomera po zavershenii vypolneniya komandy imeyut indeksy dlya fajlov "." i ".." ?) *34. Ponyatie "simvolicheskie svyazi" imeet otnoshenie k vozmozhnosti ukazaniya s pomoshch'yu funkcii link svyazej mezhdu fajlami, prinadlezhashchimi k razlichnym fajlovym sistemam. S fajlom simvolicheskoj svyazi associirovan ukazatel' novogo tipa; soderzhimym fajla yavlyaetsya imya puti poiska togo fajla, s kotorym on svyazan. Opishite realizaciyu simvolicheskih svyazej. *35. CHto proizojdet, esli process vyzovet funkciyu unlink("."); Kakim budet tekushchij katalog processa ? Predpolagaetsya, chto process ob- ladaet pravami superpol'zovatelya. 36. Razrabotajte sistemnuyu funkciyu, kotoraya usekaet sushchestvuyushchij fajl do proizvol'nyh razmerov, ukazannyh v kachestve argumenta, i opishite ee rabotu. Realizujte sistemnuyu funkciyu, kotoraya pozvolyala by pol'zovate- lyu udalyat' segment fajla, raspolozhennyj mezhdu dvumya adresami, zadanny- mi v vide smeshchenij, i szhimat' fajl. Napishite programmu, kotoraya ne vy- zyvala by eti funkcii, no obladala by temi zhe funkcional'nymi vozmozh- nostyami. 37. Opishite vse usloviya, pri kotoryh schetchik ssylok v indekse mozhet prevy- shat' znachenie 1. 38. Zatragivaya temu abstraktnyh obrashchenij k fajlovym sistemam, otvet'te na vopros: sleduet li fajlovoj sisteme kazhdogo tipa imet' lichnuyu operaciyu blokirovaniya, vyzyvaemuyu iz obshchej programmy, ili zhe dostatochno obshchej operacii blokirovaniya ? 136

Last-modified: Thu, 12 Feb 1998 07:19:20 GMT
Ocenite etot tekst: