Ocenite etot tekst:





    Nalichie  mehanizmov  vzaimodejstviya  daet proizvol'nym processam vozmozh-
nost' osushchestvlyat' obmen dannymi i sinhronizirovat' svoe vypolnenie s drugi-
mi processami. My uzhe rassmotreli neskol'ko form  vzaimodejstviya  processov,
takie  kak  kanal'naya  svyaz',  ispol'zovanie poimenovannyh kanalov i posylka
signalov. Kanaly (nepoimenovannye) imeyut nedostatok, svyazannyj  s  tem,  chto
oni izvestny tol'ko potomkam processa, vyzvavshego sistemnuyu funkciyu pipe: ne
imeyushchie rodstvennyh svyazej processy ne mogut vzaimodejstvovat' mezhdu soboj s
pomoshch'yu  nepoimenovannyh  kanalov.  Nesmotrya na to, chto poimenovannye kanaly
pozvolyayut vzaimodejstvovat' mezhdu soboj processam,  ne  imeyushchim  rodstvennyh
svyazej, oni ne mogut ispol'zovat'sya ni v seti (sm. glavu 13), ni v organiza-
cii mnozhestvennyh svyazej mezhdu razlichnymi gruppami vzaimodejstvuyushchih proces-
sov:  poimenovannyj kanal ne poddaetsya takomu mul'tipleksirovaniyu, pri koto-
rom u kazhdoj pary vzaimodejstvuyushchih processov imelsya by svoj vydelennyj  ka-
nal. Proizvol'nye processy mogut takzhe svyazyvat'sya mezhdu soboj blagodarya po-
sylke  signalov  s  pomoshch'yu sistemnoj funkcii kill, odnako takoe "soobshchenie"
sostoit iz odnogo tol'ko nomera signala.
    V dannoj glave opisyvayutsya drugie formy vzaimodejstviya processov. V  na-
chale  rech'  idet  o trassirovke processov, o tom, kakim obrazom odin process
sledit za hodom vypolneniya drugogo  processa,  zatem  rassmatrivaetsya  paket
IPC:  soobshcheniya,  razdelyaemaya pamyat' i semafory. Delaetsya obzor tradicionnyh
metodov setevogo vzaimodejstviya processov, vypolnyayushchihsya na raznyh  mashinah,
i,  nakonec,  daetsya predstavlenie o "gnezdah", primenyayushchihsya v sisteme BSD.
Voprosy setevogo vzaimodejstviya, imeyushchie  special'nyj  harakter,  takie  kak
protokoly,  adresaciya  i  dr.,  ne rassmatrivayutsya, poskol'ku oni vyhodyat za
ramki nastoyashchej raboty.




    V sisteme UNIX imeetsya prostejshaya forma  vzaimodejstviya  processov,  is-
pol'zuemaya  v celyah otladki, - trassirovka processov. Process-otladchik, nap-

     +-------------------------------------------------------+
     | if ((pid = fork()) == 0)                              |
     | {                                                     |
     |     /* potomok - trassiruemyj process */              |
     |     ptrace(0,0,0,0);                                  |
     |     exec("imya trassiruemogo processa");               |
     | }                                                     |
     | /* prodolzhenie vypolneniya processa-otladchika */       |
     | for (;;)                                              |
     | {                                                     |
     |     wait((int *) 0);                                  |
     |     read(vhodnaya informaciya dlya trassirovki komand)   |
     |     ptrace(cmd,pid,...);                              |
     |     if (uslovie zaversheniya trassirovki)               |
     |          break;                                       |
     | }                                                     |
     +-------------------------------------------------------+

             Risunok 11.1. Struktura processa otladki

                                    330



rimer sdb, porozhdaet trassiruemyj process i upravlyaet ego vypolneniem s  po-
moshch'yu  sistemnoj  funkcii  ptrace, rasstavlyaya i sbrasyvaya kontrol'nye tochki,
schityvaya i zapisyvaya dannye v ego virtual'noe adresnoe prostranstvo. Trassi-
rovka processov, takim obrazom, vklyuchaet  v  sebya  sinhronizaciyu  vypolneniya
processa-otladchika i trassiruemogo processa i upravlenie vypolneniem posled-
nego.
    Psevdoprogramma, predstavlennaya na Risunke 11.1, imeet tipichnuyu struktu-
ru  otladochnoj programmy. Otladchik porozhdaet novyj process, zapuskayushchij sis-
temnuyu funkciyu ptrace, v rezul'tate chego v sootvetstvuyushchej  processu-potomku
zapisi tablicy processov yadro ustanavlivaet bit trassirovki. Process-potomok
prednaznachen dlya zapuska (exec) trassiruemoj programmy. Naprimer, esli pol'-
zovatel' vedet otladku programmy a.out, process-potomok zapuskaet fajl s tem
zhe  imenem. YAdro otrabatyvaet funkciyu exec obychnym poryadkom, no v finale za-
mechaet, chto bit trassirovki ustanovlen, i posylaet  processu-potomku  signal
preryvaniya. Na vyhode iz funkcii exec, kak i na vyhode iz lyuboj drugoj funk-
cii, yadro proveryaet nalichie signalov, obnaruzhivaet tol'ko chto poslannyj sig-
nal  preryvaniya i ispolnyaet programmu trassirovki processa kak osobyj sluchaj
obrabotki signalov. Zametiv ustanovku bita trassirovki, process-potomok  vy-
vodit svoego roditelya iz sostoyaniya priostanova, v kotorom poslednij nahodit-
sya  vsledstvie ispolneniya funkcii wait, sam perehodit v sostoyanie trassirov-
ki, podobnoe sostoyaniyu priostanova (no ne pokazannoe na diagramme  sostoyanij
processa, sm. Risunok 6.1), i vypolnyaet pereklyuchenie konteksta.
    Tem vremenem v obychnoj situacii process-roditel' (otladchik) perehodit na
pol'zovatel'skij uroven', ozhidaya polucheniya izvestiya ot trassiruemogo proces-
sa.  Kogda  sootvetstvuyushchee  izvestie processom-roditelem budet polucheno, on
vyjdet iz sostoyaniya ozhidaniya (wait), prochitaet (read) vvedennye  pol'zovate-
lem  komandy  i prevratit ih v seriyu obrashchenij k funkcii ptrace, upravlyayushchih
trassirovkoj processa-potomka. Sintaksis vyzova sistemnoj funkcii ptrace:

    ptrace(cmd,pid,addr,data);

gde v kachestve cmd ukazyvayutsya razlichnye komandy, naprimer,  chteniya  dannyh,
zapisi  dannyh, vozobnovleniya vypolneniya i t.p., pid - identifikator trassi-
ruemogo processa, addr - virtual'nyj adres yachejki v  trassiruemom  processe,
gde budet proizvodit'sya chtenie ili zapis', data - celoe znachenie, prednazna-
chennoe  dlya zapisi. Vo vremya ispolneniya sistemnoj funkcii ptrace yadro prove-
ryaet, imeetsya li u otladchika potomok s identifikatorom pid  i  nahoditsya  li
etot potomok v sostoyanii trassirovki, posle chego zavodit global'nuyu struktu-
ru dannyh, prednaznachennuyu dlya peredachi dannyh mezhdu dvumya processami. CHtoby
drugie  processy, vypolnyayushchie trassirovku, ne mogli zateret' soderzhimoe etoj
struktury, ona blokiruetsya yadrom, yadro zapisyvaet v nee parametry cmd,  addr
i  data, vozobnovlyaet process-potomok, perevodit ego v sostoyanie "gotovnosti
k vypolneniyu" i priostanavlivaetsya do polucheniya ot nego otveta.  Kogda  pro-
cess-potomok prodolzhit svoe vypolnenie (v rezhime yadra), on ispolnit sootvet-
stvuyushchuyu  (trassiruemuyu) komandu, zapishet rezul'tat v global'nuyu strukturu i
"razbudit" otladchika. V zavisimosti ot tipa komandy potomok mozhet vnov'  pe-
rejti  v  sostoyanie  trassirovki  i ozhidat' postupleniya novoj komandy ili zhe
vyjti iz cikla obrabotki signalov i prodolzhit' svoe vypolnenie.  Pri  vozob-
novlenii  raboty otladchika yadro zapominaet znachenie, vozvrashchennoe trassirue-
mym processom, snimaet s global'noj struktury blokirovku i vozvrashchaet uprav-
lenie pol'zovatelyu.
    Esli v moment perehoda processa-potomka v sostoyanie trassirovki otladchik
ne nahoditsya v sostoyanii priostanova (wait), on ne obnaruzhit  potomka,  poka
ne  obratitsya k funkcii wait, posle chego nemedlenno vyjdet iz funkcii i pro-
dolzhit rabotu po vysheopisannomu planu.



                                    331
    +------------------------------------------------------+
    | int data[32];                                        |
    | main()                                               |
    | {                                                    |
    |     int i;                                           |
    |     for (i = 0; i < 32; i++)                         |
    |         printf("data[%d] = %d\n@,i,data[i]);         |
    |     printf("ptrace data addr Ox%x\n",data);          |
    | }                                                    |
    +------------------------------------------------------+

      Risunok 11.2. Programma trace (trassiruemyj process)


    Rassmotrim dve programmy, privedennye na Risunkah 11.2 i 11.3 i  imenue-
mye  trace  i debug, sootvetstvenno. Pri zapuske programmy trace s terminala
massiv data budet soderzhat' nulevye znacheniya; process vyvodit adres  massiva
i  zavershaet  rabotu.  Pri zapuske programmy debug s peredachej ej v kachestve
parametra znacheniya,  vyvedennogo  programmoj  trace,  proishodit  sleduyushchee:
programma  zapominaet  znachenie  parametra  v peremennoj addr, sozdaet novyj
process, s pomoshch'yu funkcii ptrace podgotavlivayushchij sebya k trassirovke, i za-
puskaet programmu trace. Na vyhode iz funkcii  exec  yadro  posylaet  proces-
su-potomku (nazovem ego tozhe trace) signal SIGTRAP (signal preryvaniya), pro-

    +------------------------------------------------------------+
    | #define TR_SETUP 0                                         |
    | #define TR_WRITE 5                                         |
    | #define TR_RESUME 7                                        |
    | int addr;                                                  |
    |                                                            |
    | main(argc,argv)                                            |
    |      int argc;                                             |
    |      char *argv[];                                         |
    | {                                                          |
    |      int i,pid;                                            |
    |                                                            |
    |      sscanf(argv[1],"%x",&addr);                           |
    |                                                            |
    |      if ((pid = fork() == 0)                               |
    |      {                                                     |
    |          ptrace(TR_SETUP,0,0,0);                           |
    |          execl("trace","trace",0);                         |
    |          exit();                                           |
    |      }                                                     |
    |      for (i = 0; i < 32, i++)                              |
    |      {                                                     |
    |          wait((int *) 0);                                  |
    |          /* zapisat' znachenie i v prostranstvo processa s  |
    |           * identifikatorom pid po adresu, soderzhashchemusya v |
    |           * peremennoj addr */                             |
    |          if (ptrace(TR_WRITE,pid,addr,i) == -1)            |
    |               exit();                                      |
    |          addr += sizeof(int);                              |
    |      }                                                     |
    |      /* trassiruemyj process vozobnovlyaet vypolnenie */    |
    |      ptrace(TR_RESUME,pid,1,0);                            |
    | }                                                          |
    +------------------------------------------------------------+

        Risunok 11.3. Programma debug (trassiruyushchij process)

                                    332



cess  trace perehodit v sostoyanie trassirovki, ozhidaya postupleniya komandy ot
programmy debug. Esli process, realizuyushchij programmu debug, nahodilsya v sos-
toyanii priostanova, svyazannogo s vypolneniem funkcii wait,  on  "probuzhdaet-
sya",  obnaruzhivaet  nalichie porozhdennogo trassiruemogo processa i vyhodit iz
funkcii wait. Zatem process debug vyzyvaet funkciyu ptrace, zapisyvaet znache-
nie peremennoj cikla i v prostranstvo dannyh processa trace po  adresu,  so-
derzhashchemusya  v  peremennoj  addr,  i uvelichivaet znachenie peremennoj addr; v
programme trace peremennaya addr hranit adres tochki vhoda v massiv data. Pos-
lednee obrashchenie processa debug k funkcii ptrace vyzyvaet  zapusk  programmy
trace, i v etot moment massiv data soderzhit znacheniya ot 0 do 31. Otlad-
chiki,  podobnye  sdb,  imeyut  dostup k tablice identifikatorov trassiruemogo
processa, iz kotoroj oni poluchayut informaciyu ob adresah dannyh, ispol'zuemyh
v kachestve parametrov funkcii ptrace.
    Ispol'zovanie funkcii ptrace dlya trassirovki processov yavlyaetsya  obychnym
delom, no ono imeet ryad nedostatkov.
  *  Dlya  togo, chtoby proizvesti peredachu porcii dannyh dlinoyu v slovo mezhdu
    processom-otladchikom i trassiruemym processom, yadro dolzhno vypolnit' che-
    tyre pereklyucheniya konteksta: ono pereklyuchaet kontekst  vo  vremya  vyzova
    otladchikom  funkcii ptrace, zagruzhaet i vygruzhaet kontekst trassiruemogo
    processa i pereklyuchaet kontekst vnov' na process-otladchik  po  poluchenii
    otveta ot trassiruemogo processa. Vse vysheukazannoe neobhodimo, poskol'-
    ku u otladchika net inogo sposoba poluchit' dostup k virtual'nomu adresno-
    mu  prostranstvu trassiruemogo processa, otsyuda zamedlennost' protekaniya
    procedury trassirovki.
  * Process-otladchik mozhet vesti odnovremennuyu trassirovku  neskol'kih  pro-
    cessov-potomkov,  hotya  na  praktike eta vozmozhnost' ispol'zuetsya redko.
    Esli byt' bolee kritichnym, sleduet otmetit', chto otladchik mozhet  trassi-
    rovat'  tol'ko svoih blizhajshih potomkov: esli trassiruemyj process-poto-
    mok vyzovet funkciyu fork, otladchik ne budet imet' kontrolya nad porozhdae-
    mym, vnuchatym dlya nego, processom, chto yavlyaetsya ser'eznym prepyatstviem v
    otladke mnogourovnevyh programm. Esli trassiruemyj process vyzyvaet fun-
    kciyu exec, zapuskaemye obrazy zadach tozhe  podvergayutsya  trassirovke  pod
    upravleniem  ranee  vyzvannoj  funkcii  ptrace, odnako otladchik mozhet ne
    znat' imeni ispolnyaemogo obraza, chto  zatrudnyaet  provedenie  simvol'noj
    otladki.
  *  Otladchik  ne  mozhet vesti trassirovku uzhe vypolnyayushchegosya processa, esli
    otlazhivaemyj process ne vyzval predvaritel'no funkciyu  ptrace,  dav  tem
    samym yadru svoe soglasie na trassirovku. |to neudobno, tak kak v ukazan-
    nom  sluchae  vypolnyayushchijsya process pridetsya udalit' iz sistemy i pereza-
    pustit' v rezhime trassirovki.
  * Ne razreshaetsya trassirovat' setuid-programmy, poskol'ku eto  mozhet  pri-
    vesti  k  narusheniyu  zashchity  dannyh (ibo v rezul'tate vypolneniya funkcii
    ptrace v ih adresnoe prostranstvo proizvodilas' by zapis'  dannyh)  i  k
    vypolneniyu    nedopustimyh    dejstvij.   Predpolozhim,   naprimer,   chto
    setuid-programma zapuskaet fajl s imenem "privatefile". Umelyj pol'zova-
    tel' s pomoshch'yu funkcii ptrace mog by zamenit' imya  fajla  na  "/bin/sh",
    zapustiv  na  vypolnenie komandnyj processor shell (i vse programmy, is-
    polnyaemye shell'om), ne imeya na to sootvetstvuyushchih  polnomochij.  Funkciya
    exec  ignoriruet  bit setuid, esli process podvergaetsya trassirovke, tem
    samym adresnoe prostranstvo setuid-programm zashchishchaetsya ot  pol'zovatel'-
    skoj zapisi.

    Killian [Killian 84] opisyvaet druguyu shemu trassirovki processov, osno-
vannuyu na pereklyuchenii fajlovyh sistem (sm. glavu 5). Administrator montiru-
et fajlovuyu sistemu pod imenem "/proc"; pol'zovateli identificiruyut processy
s pomoshch'yu kodov identifikacii i traktuyut ih kak fajly, prinadlezhashchie katalo-
gu  "/proc". YAdro daet razreshenie na otkrytie fajlov, ishodya iz koda identi-

                                    333

fikacii pol'zovatelya processa i koda identifikacii gruppy. Pol'zovateli  mo-
gut obrashchat'sya k adresnomu prostranstvu processa putem chteniya (read) fajla i
ustanavlivat' tochki preryvanij putem zapisi (write) v fajl. Funkciya stat so-
obshchaet  razlichnuyu  statisticheskuyu  informaciyu, kasayushchuyusya processa. V dannom
podhode ustraneny tri nedostatka, prisushchie funkcii  ptrace.  Vo-pervyh,  eta
shema  rabotaet bystree, poskol'ku process-otladchik za odno obrashchenie k uka-
zannym sistemnym funkciyam mozhet peredavat' bol'she informacii, chem pri rabote
s ptrace. Vo-vtoryh, otladchik zdes' mozhet vesti trassirovku sovershenno  pro-
izvol'nyh  processov, a ne tol'ko svoih potomkov. Nakonec, trassiruemyj pro-
cess ne dolzhen predprinimat' predvaritel'no nikakih dejstvij po podgotovke k
trassirovke; otladchik mozhet trassirovat' i  sushchestvuyushchie  processy.  Vozmozh-
nost' vesti otladku setuid-programm, predostavlyaemaya tol'ko superpol'zovate-
lyu, realizuetsya kak sostavnaya chast' tradicionnogo mehanizma zashchity fajlov.




    Paket  IPC (interprocess communication) v versii V sistemy UNIX vklyuchaet
v sebya tri mehanizma. Mehanizm soobshchenij daet processam vozmozhnost' posylat'
drugim processam potoki sformatirovannyh dannyh, mehanizm razdeleniya  pamyati
pozvolyaet  processam sovmestno ispol'zovat' otdel'nye chasti virtual'nogo ad-
resnogo prostranstva, a semafory - sinhronizirovat' svoe vypolnenie s vypol-
neniem parallel'nyh processov. Nesmotrya na to, chto oni  realizuyutsya  v  vide
otdel'nyh blokov, im prisushchi obshchie svojstva.
  *  S  kazhdym mehanizmom svyazana tablica, v zapisyah kotoroj opisyvayutsya vse
    ego detali.
  * V kazhdoj zapisi soderzhitsya chislovoj klyuch (key), kotoryj predstavlyaet so-
    boj identifikator zapisi, vybrannyj pol'zovatelem.
  * V kazhdom mehanizme imeetsya sistemnaya funkciya  tipa  "get",  ispol'zuemaya
    dlya  sozdaniya  novoj ili poiska sushchestvuyushchej zapisi; parametrami funkcii
    yavlyayutsya identifikator zapisi i razlichnye flagi (flag). YAdro vedet poisk
    zapisi po ee identifikatoru v sootvetstvuyushchej tablice. Processy mogut  s
    pomoshch'yu flaga IPC_PRIVATE garantirovat' poluchenie eshche neispol'zuemoj za-
    pisi. S pomoshch'yu flaga IPC_CREAT oni mogut sozdat' novuyu zapis', esli za-
    pisi  s  ukazannym  identifikatorom net, a esli eshche k tomu zhe ustanovit'
    flag IPC_EXCL, mozhno poluchit' uvedomlenie ob oshibke v tom  sluchae,  esli
    zapis' s takim identifikatorom sushchestvuet. Funkciya vozvrashchaet nekij vyb-
    rannyj  yadrom deskriptor, prednaznachennyj dlya posleduyushchego ispol'zovaniya
    v drugih sistemnyh funkciyah, takim obrazom, ona rabotaet analogichno sis-
    temnym funkciyam creat i open.
  * V kazhdom mehanizme yadro ispol'zuet sleduyushchuyu formulu dlya poiska po desk-
    riptoru ukazatelya na zapis' v tablice struktur dannyh:

    ukazatel' = znachenie deskriptora po modulyu ot chisla zapisej v tablice

    Esli, naprimer, tablica struktur soobshchenij sostoit iz 100 zapisej, desk-
    riptory, svyazannye s zapis'yu nomer 1, imeyut znacheniya, ravnye 1, 101, 201
    i t.d. Kogda process udalyaet zapis', yadro uvelichivaet znachenie svyazanno-
    go s nej deskriptora na chislo zapisej v tablice:  poluchennyj  deskriptor
    stanet  novym deskriptorom etoj zapisi, kogda k nej vnov' budet proizve-
    deno obrashchenie pri pomoshchi funkcii tipa "get".  Processy,  kotorye  budut
    pytat'sya  obratit'sya k zapisi po ee staromu deskriptoru, poterpyat neuda-
    chu. Obratimsya vnov' k predydushchemu primeru. Esli s zapis'yu 1 svyazan desk-
    riptor, imeyushchij znachenie 201, pri ego udalenii yadro naznachit zapisi  no-
    vyj  deskriptor, imeyushchij znachenie 301. Processy, pytayushchiesya obratit'sya k
    deskriptoru 201, poluchat oshibku, poskol'ku etogo deskriptora bol'she net.
    V konechnom itoge yadro proizvedet perenumeraciyu deskriptorov, no poka eto
    proizojdet, mozhet projti znachitel'nyj promezhutok vremeni.
  * Kazhdaya zapis' imeet nekuyu strukturu dannyh, opisyvayushchuyu prava dostupa  k

                                    334

    nej i vklyuchayushchuyu v sebya pol'zovatel'skij i gruppovoj kody identifikacii,
    kotorye  imeet  process,  sozdavshij  zapis',  a takzhe pol'zovatel'skij i
    gruppovoj kody  identifikacii,  ustanovlennye  sistemnoj  funkciej  tipa
    "control"  (ob  etom nizhe), i dvoichnye kody razreshenij chteniya-zapisi-is-
    polneniya dlya vladel'ca, gruppy i prochih pol'zovatelej, po analogii s us-
    tanovkoj prav dostupa k fajlam.
  * V kazhdoj zapisi imeetsya drugaya informaciya, opisyvayushchaya sostoyanie zapisi,
    v chastnosti, identifikator poslednego iz processov, vnesshih izmeneniya  v
    zapis'  (posylka soobshcheniya, priem soobshcheniya, podklyuchenie razdelyaemoj pa-
    myati i t.d.), i vremya poslednego obrashcheniya ili korrektirovki.
  * V kazhdom mehanizme imeetsya sistemnaya funkciya tipa "control", zaprashivayu-
    shchaya informaciyu o sostoyanii zapisi, izmenyayushchaya etu informaciyu ili udalyayu-
    shchaya zapis' iz sistemy. Kogda process zaprashivaet informaciyu o  sostoyanii
    zapisi,  yadro  proveryaet,  imeet li process razreshenie na chtenie zapisi,
    posle chego kopiruet dannye iz zapisi tablicy po adresu, ukazannomu pol'-
    zovatelem. Pri ustanovke znachenij prinadlezhashchih zapisi  parametrov  yadro
    proveryaet,  sovpadayut  li mezhdu soboj pol'zovatel'skij kod identifikacii
    processa i identifikator pol'zovatelya (ili sozdatelya), ukazannyj v zapi-
    si, ne zapushchen li process pod upravleniem superpol'zovatelya; odnogo raz-
    resheniya na zapis' nedostatochno dlya ustanovki parametrov.  YAdro  kopiruet
    soobshchennuyu  pol'zovatelem informaciyu v zapis' tablicy, ustanavlivaya zna-
    cheniya pol'zovatel'skogo i gruppovogo kodov identifikacii, rezhimy dostupa
    i drugie parametry (v zavisimosti ot tipa mehanizma). YAdro  ne  izmenyaet
    znacheniya  polej, opisyvayushchih pol'zovatel'skij i gruppovoj kody identifi-
    kacii sozdatelya zapisi, poetomu pol'zovatel', sozdavshij zapis', sohranya-
    et upravlyayushchie prava na nee. Pol'zovatel' mozhet udalit' zapis', libo es-
    li on yavlyaetsya superpol'zovatelem, libo esli identifikator processa sov-
    padaet s lyubym iz identifikatorov, ukazannyh v  strukture  zapisi.  YAdro
    uvelichivaet  nomer deskriptora, chtoby pri sleduyushchem naznachenii zapisi ej
    byl prisvoen novyj deskriptor. Sledovatel'no, kak uzhe ranee  govorilos',
    esli process popytaetsya obratit'sya k zapisi po staromu deskriptoru, vyz-
    vannaya im funkciya poluchit otkaz.




    S soobshcheniyami rabotayut chetyre sistemnyh funkcii: msgget, kotoraya vozvra-
shchaet (i v nekotoryh sluchayah sozdaet) deskriptor soobshcheniya, opredelyayushchij oche-
red'  soobshchenij i ispol'zuemyj drugimi sistemnymi funkciyami, msgctl, kotoraya
ustanavlivaet i vozvrashchaet svyazannye s deskriptorom soobshchenij parametry  ili
udalyaet  deskriptory,  msgsnd, kotoraya posylaet soobshchenie, i msgrcv, kotoraya
poluchaet soobshchenie.
    Sintaksis vyzova sistemnoj funkcii msgget:

    msgqid = msgget(key,flag);

gde msgqid - vozvrashchaemyj funkciej deskriptor, a key i flag imeyut tu zhe  se-
mantiku, chto i v sistemnoj funkcii tipa "get". YAdro hranit soobshcheniya v svyaz-
nom  spiske (ocheredi), opredelyaemom znacheniem deskriptora, i ispol'zuet zna-
chenie msgqid v kachestve ukazatelya na massiv zagolovkov ocheredej. Krome vyshe-
ukazannyh polej, opisyvayushchih obshchie dlya vsego mehanizma prava dostupa,  zago-
lovok ocheredi soderzhit sleduyushchie polya:
  * Ukazateli na pervoe i poslednee soobshchenie v spiske;
  * Kolichestvo soobshchenij i obshchij ob容m informacii v spiske v bajtah;
  * Maksimal'naya emkost' spiska v bajtah;
  * Identifikatory processov, poslavshih i prinyavshih soobshcheniya poslednimi;
  *  Polya,  ukazyvayushchie vremya poslednego vypolneniya funkcij msgsnd, msgrcv i
    msgctl.
    Kogda pol'zovatel' vyzyvaet funkciyu msgget dlya togo, chtoby sozdat' novyj

                                    335

deskriptor, yadro prosmatrivaet massiv ocheredej soobshchenij v poiskah sushchestvu-
yushchej ocheredi s ukazannym identifikatorom. Esli takoj ocheredi net, yadro vyde-
lyaet novuyu ochered', inicializiruet ee i vozvrashchaet identifikator pol'zovate-
lyu. V protivnom sluchae yadro proveryaet nalichie neobhodimyh prav dostupa i za-
vershaet vypolnenie funkcii.
    Dlya posylki soobshcheniya process ispol'zuet sistemnuyu funkciyu msgsnd:

    msgsnd(msgqid,msg,count,flag);

gde msgqid - deskriptor  ocheredi  soobshchenij,  obychno  vozvrashchaemyj  funkciej
msgget,  msg - ukazatel' na strukturu, sostoyashchuyu iz tipa v vide naznachaemogo
pol'zovatelem celogo chisla i massiva simvolov, count - razmer informacionno-
go massiva, flag - dejstvie, predprinimaemoe  yadrom  v  sluchae  perepolneniya
vnutrennego bufernogo prostranstva.
    YAdro  proveryaet  (Risunok 11.4), imeetsya li u posylayushchego soobshchenie pro-
cessa razresheniya na zapis' po ukazannomu deskriptoru, ne vyhodit  li  razmer
soobshcheniya  za  ustanovlennuyu  sistemoj  granicu,  ne soderzhitsya li v ocheredi
slishkom bol'shoj ob容m informacii, a takzhe yavlyaetsya li tip soobshcheniya  polozhi-
tel'nym  celym  chislom.  Esli vse usloviya soblyudeny, yadro vydelyaet soobshcheniyu
mesto, ispol'zuya kartu soobshchenij (sm. razdel 9.1), i kopiruet  v  eto  mesto
dannye  iz  prostranstva pol'zovatelya. K soobshcheniyu prisoedinyaetsya zagolovok,
posle chego ono pomeshchaetsya v konec svyaznogo spiska  zagolovkov  soobshchenij.  V
zagolovke soobshcheniya zapisyvaetsya tip i razmer soobshche-

    +------------------------------------------------------------+
    | algoritm msgsnd       /* poslat' soobshchenie */              |
    | vhodnaya informaciya:  (1) deskriptor ocheredi soobshchenij      |
    |                      (2) adres struktury soobshcheniya         |
    |                      (3) razmer soobshcheniya                  |
    |                      (4) flagi                             |
    | vyhodnaya informaciya: kolichestvo poslannyh bajt             |
    | {                                                          |
    |    proverit' pravil'nost' ukazaniya deskriptora i nalichie   |
    |     sootvetstvuyushchih prav dostupa;                          |
    |    vypolnit' poka (dlya hraneniya soobshcheniya ne budet vydeleno|
    |     mesto)                                                 |
    |    {                                                       |
    |        esli (flagi ne razreshayut zhdat')                     |
    |              vernut'sya;                                    |
    |        priostanovit'sya (do teh por, poka mesto ne osvobo-  |
    |         ditsya);                                            |
    |    }                                                       |
    |    poluchit' zagolovok soobshcheniya;                           |
    |    schitat' tekst soobshcheniya iz prostranstva zadachi v prost- |
    |     ranstvo yadra;                                          |
    |    nastroit' struktury dannyh: vystroit' ochered' zagolovkov|
    |     soobshchenij, ustanovit' v zagolovke ukazatel' na tekst   |
    |     soobshcheniya, zapolnit' polya, soderzhashchie schetchiki, vremya  |
    |     poslednego vypolneniya operacij i identifikator proces- |
    |     sa;                                                    |
    |    vyvesti iz sostoyaniya priostanova vse processy, ozhidayushchie|
    |     razresheniya schitat' soobshchenie iz ocheredi;               |
    | }                                                          |
    +------------------------------------------------------------+

              Risunok 11.4. Algoritm posylki soobshcheniya


niya,  ustanavlivaetsya  ukazatel' na tekst soobshcheniya i proizvoditsya korrekti-

                                    336

rovka soderzhimogo razlichnyh polej zagolovka ocheredi, soderzhashchih statistiches-
kuyu informaciyu (kolichestvo soobshchenij v ocheredi i ih summarnyj ob容m  v  baj-
tah,  vremya poslednego vypolneniya operacij i identifikator processa, poslav-
shego soobshchenie). Zatem yadro vyvodit iz sostoyaniya priostanova  vse  processy,
ozhidayushchie  popolneniya ocheredi soobshchenij. Esli razmer ocheredi v bajtah prevy-
shaet granicu dopustimosti, process priostanavlivaetsya do teh por, poka  dru-
gie  soobshcheniya ne ujdut iz ocheredi. Odnako, esli processu bylo dano ukazanie
ne zhdat' (flag IPC_NOWAIT), on nemedlenno vozvrashchaet upravlenie s  uvedomle-
niem ob oshibke. Na Risunke 11.5 pokazana ochered' soobshchenij, sostoyashchaya iz za-
golovkov  soobshchenij,  organizovannyh  v svyaznye spiski, s ukazatelyami na ob-
last' teksta.
    Rassmotrim programmu, predstavlennuyu na Risunke 11.6.  Process  vyzyvaet
funkciyu  msgget dlya togo, chtoby poluchit' deskriptor dlya zapisi s identifika-
torom MSGKEY. Dlina soobshcheniya prinimaetsya ravnoj 256 bajt, hotya ispol'zuetsya
tol'ko pervoe pole celogo tipa, v oblast' teksta soobshcheniya kopiruetsya  iden-
tifikator  processa, tipu soobshcheniya prisvaivaetsya znachenie 1, posle chego vy-
zyvaetsya funkciya msgsnd dlya posylki soobshcheniya. My vernemsya k  etomu  primeru
pozzhe.
    Process  poluchaet soobshcheniya, vyzyvaya funkciyu msgrcv po sleduyushchemu forma-
tu:
    count = msgrcv(id,msg,maxcount,type,flag);

gde id - deskriptor soobshcheniya, msg - adres pol'zovatel'skoj struktury, koto-
raya budet soderzhat' poluchennoe soobshchenie, maxcount - razmer  struktury  msg,
type  - tip schityvaemogo soobshcheniya, flag - dejstvie, predprinimaemoe yadrom v
tom sluchae, esli v ocheredi so-

    Zagolovki                                         Oblast'
    ocheredej                                          teksta
    +------+           Zagolovki soobshchenij        +->+------+
    |      |     +------+    +------+    +------+ |  |      |
    |    --+---->|      +--->|      +--->|      | |  |      |
    |      |     +---+--+    +---+--+    +---+--+ |  |      |
    +------+         |           |           +----+  |      |
    |      |         +-----------|------------------>+------+
    |      |                     |                   |      |
    |      |                     |                   |      |
    +------+                     |                   |      |
    |      |     +------+        |                   |      |
    |    --+---->|      |        |                   |      |
    |      |     +---+--+        |                   |      |
    +------+         |           |                   |      |
    |   -  |         |           |                   +------+
    |   -  |         +-----------|------------------>+------+
    |   -  |                     |                   |      |
    |   -  |                     |                   |      |
    |   -  |                     +------------------>+------+
    |   -  |                                         |      |
    |   -  |                                         +------+
    |   -  |                                         |   -  |
    |   -  |                                         |   -  |
    |   -  |                                         |   -  |
    +------+                                         +------+

    Risunok 11.5. Struktury dannyh, ispol'zuemye v organizacii soobshchenij


obshchenij net. V peremennoj count pol'zovatelyu vozvrashchaetsya chislo  prochitannyh
bajt soobshcheniya.

                                    337

    YAdro  proveryaet  (Risunok 11.7), imeet li pol'zovatel' neobhodimye prava
dostupa k ocheredi soobshchenij. Esli tip schityvaemogo soobshcheniya  imeet  nulevoe
znachenie,  yadro  ishchet  pervoe  po schetu soobshchenie v svyaznom spiske. Esli ego
razmer men'she ili raven razmeru,  ukazannomu  pol'zovatelem,  yadro  kopiruet
tekst soobshcheniya v pol'zovatel'skuyu strukturu i sootvetstvuyushchim obrazom nast-
raivaet  svoi  vnutrennie struktury: umen'shaet schetchik soobshchenij v ocheredi i
summarnyj ob容m informacii v bajtah, zapominaet vremya polucheniya soobshcheniya  i
identifikator processa-poluchatelya, perestraivaet svyaznyj spisok i osvobozhda-
et  mesto  v  sistemnom prostranstve, gde hranilsya tekst soobshcheniya. Esli ka-
kie-libo processy, ozhidavshie polucheniya  soobshcheniya,  nahodilis'  v  sostoyanii
priostanova  iz-za  otsutstviya svobodnogo mesta v spiske, yadro vyvodit ih iz
etogo sostoyaniya. Esli razmer soobshcheniya prevyshaet znachenie maxcount,  ukazan-
noe  pol'zovatelem,  yadro posylaet sistemnoj funkcii uvedomlenie ob oshibke i
ostavlyaet soobshchenie v ocheredi. Esli, tem ne menee, process ignoriruet  ogra-
nicheniya  na  razmer  (v pole flag ustanovlen bit MSG_NOERROR), yadro obrezaet
soobshchenie, vozvrashchaet zaproshennoe kolichestvo bajt  i  udalyaet  soobshchenie  iz
spiska celikom.

    +------------------------------------------------------------+
    | #include                                      |
    | #include                                        |
    | #include                                        |
    |                                                            |
    | #define MSGKEY     75                                      |
    |                                                            |
    | struct msgform {                                           |
    |        long     mtype;                                     |
    |        char     mtext[256];                                |
    | };                                                         |
    |                                                            |
    | main()                                                     |
    | {                                                          |
    |        struct msgform msg;                                 |
    |        int msgid,pid,*pint;                                |
    |                                                            |
    |        msgid = msgget(MSGKEY,0777);                        |
    |                                                            |
    |        pid = getpid();                                     |
    |        pint = (int *) msg.mtext;                           |
    |        *pint = pid;         /* kopirovanie identifikatora  |
    |                              * processa v oblast' teksta   |
    |                              * soobshcheniya */                |
    |        msg.mtype = 1;                                      |
    |                                                            |
    |        msgsnd(msgid,&msg,sizeof(int),0);                   |
    |        msgrcv(msgid,&msg,256,pid,0);   /* identifikator    |
    |                               * processa ispol'zuetsya v    |
    |                               * kachestve tipa soobshcheniya */ |
    |        printf("klient: poluchil ot processa s pid %d\n",    |
    |               *pint);                                      |
    | }                                                          |
    +------------------------------------------------------------+

              Risunok 11.6. Pol'zovatel'skij process


    Process mozhet poluchat' soobshcheniya opredelennogo tipa, esli prisvoit para-
metru  type  sootvetstvuyushchee  znachenie.  Esli eto polozhitel'noe celoe chislo,
funkciya vozvrashchaet pervoe znachenie dannogo tipa,  esli  otricatel'noe,  yadro

                                    338

opredelyaet minimal'noe znachenie tipa soobshchenij v ocheredi, i esli ono ne pre-
vyshaet  absolyutnoe znachenie parametra type, vozvrashchaet processu pervoe soob-
shchenie etogo tipa. Naprimer, esli ochered' sostoit iz treh soobshchenij,  imeyushchih
tip  3,  1 i 2, sootvetstvenno, a pol'zovatel' zaprashivaet soobshchenie s tipom
-2, yadro vozvrashchaet emu soobshchenie tipa 1. Vo  vseh  sluchayah,  esli  usloviyam
zaprosa ne udovletvoryaet ni odno iz soobshchenij v ocheredi, yadro perevodit pro-
cess v sostoyanie priostanova, razumeetsya esli tol'ko v parametre flag ne us-
tanovlen bit IPC_NOWAIT (inache process nemedlenno vyhodit iz funkcii).
    Rassmotrim  programmy, predstavlennye na Risunkah 11.6 i 11.8. Programma
na Risunke 11.8 osushchestvlyaet obshchee  obsluzhivanie  zaprosov  pol'zovatel'skih
processov  (klientov).  Zaprosy, naprimer, mogut kasat'sya informacii, hranya-
shchejsya v baze dannyh; obsluzhivayushchij process  (server)  vystupaet  neobhodimym
posrednikom pri obrashchenii k baze dannyh, takoj poryadok oblegchaet podderzhanie
celostnosti  dannyh i organizaciyu ih zashchity ot nesankcionirovannogo dostupa.
Obsluzhivayushchij process sozdaet soobshchenie putem ustanovki flaga IPC _CREAT pri

    +------------------------------------------------------------+
    | algoritm msgrcv     /* poluchenie soobshcheniya */              |
    | vhodnaya informaciya:  (1) deskriptor soobshcheniya              |
    |                      (2) adres massiva, v kotoryj zanositsya|
    |                          soobshchenie                         |
    |                      (3) razmer massiva                    |
    |                      (4) tip soobshcheniya v zaprose           |
    |                      (5) flagi                             |
    | vyhodnaya informaciya: kolichestvo bajt v poluchennom soobshchenii|
    | {                                                          |
    |      proverit' prava dostupa;                              |
    |   loop:                                                    |
    |      proverit' pravil'nost' deskriptora soobshcheniya;         |
    |      /* najti soobshchenie, nuzhnoe pol'zovatelyu */            |
    |      esli (tip soobshcheniya v zaprose == 0)                   |
    |           rassmotret' pervoe soobshchenie v ocheredi;          |
    |      v protivnom sluchae esli (tip soobshcheniya v zaprose > 0) |
    |           rassmotret' pervoe soobshchenie v ocheredi, imeyushchee  |
    |            dannyj tip;                                     |
    |      v protivnom sluchae   /* tip soobshcheniya v zaprose < 0 */|
    |           rassmotret' pervoe iz soobshchenij v ocheredi s nai- |
    |            men'shim znacheniem tipa pri uslovii, chto ego tip |
    |            ne prevyshaet absolyutnoe znachenie tipa, ukazanno-|
    |            go v zaprose;                                   |
    |      esli (soobshchenie najdeno)                              |
    |      {                                                     |
    |           pereustanovit' razmer soobshcheniya ili vernut' oshib-|
    |            ku, esli razmer, ukazannyj pol'zovatelem slishkom|
    |            mal;                                            |
    |           skopirovat' tip soobshcheniya i ego tekst iz prost-  |
    |            ranstva yadra v prostranstvo zadachi;             |
    |           razorvat' svyaz' soobshcheniya s ochered'yu;            |
    |           vernut' upravlenie;                              |
    |      }                                                     |
    |      /* soobshchenij net */                                   |
    |      esli (flagi ne razreshayut priostanavlivat' rabotu)     |
    |           vernut' upravlenie s oshibkoj;                    |
    |      priostanovit'sya (poka soobshchenie ne poyavitsya v ochere-  |
    |       di);                                                 |
    |      perejti na loop;                                      |
    | }                                                          |
    +------------------------------------------------------------+
             Risunok 11.7. Algoritm polucheniya soobshcheniya

                                    339



vypolnenii funkcii msgget i poluchaet vse soobshcheniya ti-
pa 1 - zaprosy ot processov-klientov. On  chitaet  tekst  soobshcheniya,  nahodit
identifikator processa-klienta i priravnivaet vozvrashchaemoe znachenie tipa so-
obshcheniya  znacheniyu  etogo identifikatora. V dannom primere obsluzhivayushchij pro-
cess vozvrashchaet v tekste soobshcheniya  processu-klientu  ego  identifikator,  i
klient  poluchaet soobshcheniya s tipom, ravnym identifikatoru klienta. Takim ob-
razom, obsluzhivayushchij process poluchaet soobshcheniya tol'ko ot klientov, a klient
- tol'ko ot obsluzhivayushchego processa. Rabota  processov  realizuetsya  v  vide
mnogokanal'nogo  vzaimodejstviya, stroyashchegosya na osnove odnoj ocheredi soobshche-
nij.

    +------------------------------------------------------------+
    | #include                                      |
    | #include                                        |
    | #include                                        |
    |                                                            |
    | #define MSGKEY     75                                      |
    | struct msgform                                             |
    | {                                                          |
    |        long     mtype;                                     |
    |        char     mtext[256];                                |
    | }msg;                                                      |
    | int msgid;                                                 |
    |                                                            |
    | main()                                                     |
    | {                                                          |
    |       int i,pid,*pint;                                     |
    |       extern cleanup();                                    |
    |                                                            |
    |       for (i = 0; i < 20; i++)                             |
    |            signal(i,cleanup);                              |
    |       msgid = msgget(MSGKEY,0777|IPC_CREAT);               |
    |                                                            |
    |       for (;;)                                             |
    |       {                                                    |
    |            msgrcv(msgid,&msg,256,1,0);                     |
    |            pint = (int *) msg.mtext;                       |
    |            pid = *pint;                                    |
    |            printf("server: poluchil ot processa s pid %d\n",|
    |                   pid);                                    |
    |            msg.mtype = pid;                                |
    |            *pint = getpid();                               |
    |            msgsnd(msgid,&msg,sizeof(int),0);               |
    |       }                                                    |
    | }                                                          |
    |                                                            |
    | cleanup()                                                  |
    | {                                                          |
    |       msgctl(msgid,IPC_RMID,0);                            |
    |       exit();                                              |
    | }                                                          |
    +------------------------------------------------------------+

            Risunok 11.8. Obsluzhivayushchij process (server)


    Soobshcheniya imeyut formu "tip - tekst", gde tekst predstavlyaet soboj  potok

                                    340

bajtov.  Ukazanie  tipa daet processam vozmozhnost' vybirat' soobshcheniya tol'ko
opredelennogo roda, chto v fajlovoj sisteme ne tak legko sdelat'. Takim obra-
zom, processy mogut vybirat' iz ocheredi soobshcheniya opredelennogo tipa  v  po-
ryadke  ih  postupleniya, prichem eta ocherednost' garantiruetsya yadrom. Nesmotrya
na to, chto obmen soobshcheniyami mozhet byt' realizovan na pol'zovatel'skom urov-
ne sredstvami fajlovoj  sistemy,  predstavlennyj  vashemu  vnimaniyu  mehanizm
obespechivaet bolee effektivnuyu organizaciyu peredachi dannyh mezhdu processami.
    S  pomoshch'yu sistemnoj funkcii msgctl process mozhet zaprosit' informaciyu o
statuse deskriptora soobshcheniya, ustanovit' etot status ili udalit' deskriptor
soobshcheniya iz sistemy. Sintaksis vyzova funkcii:

    msgctl(id,cmd,mstatbuf)

gde id - deskriptor soobshcheniya, cmd - tip komandy, mstatbuf - adres pol'zova-
tel'skoj struktury, v kotoroj budut hranit'sya upravlyayushchie parametry ili  re-
zul'taty obrabotki zaprosa. Bolee podrobno ob argumentah funkcii pojdet rech'
v Prilozhenii.
    Vernemsya  k primeru, predstavlennomu na Risunke 11.8. Obsluzhivayushchij pro-
cess prinimaet signaly i s pomoshch'yu funkcii cleanup udalyaet ochered' soobshchenij
iz sistemy. Esli zhe im ne bylo pojmano ni odnogo  signala  ili  byl  poluchen
signal  SIGKILL,  ochered'  soobshchenij ostaetsya v sisteme, dazhe esli na nee ne
ssylaetsya ni odin iz processov. Dal'nejshie  popytki  isklyuchitel'no  sozdaniya
novoj ocheredi soobshchenij s dannym klyuchom (identifikatorom) ne budut imet' us-
peh do teh por, poka staraya ochered' ne budet udalena iz sistemy.


    11.2.2 Razdelenie pamyati

Processy mogut vzaimodejstvovat' drug s drugom neposredstvenno putem razdeleniya (sovmestnogo ispol'zovaniya) uchastkov virtual'nogo adresnogo pros- transtva i obmena dannymi cherez razdelyaemuyu pamyat'. Sistemnye funkcii dlya raboty s razdelyaemoj pamyat'yu imeyut mnogo shodnogo s sistemnymi funkciyami dlya raboty s soobshcheniyami. Funkciya shmget sozdaet novuyu oblast' razdelyaemoj pamya- ti ili vozvrashchaet adres uzhe sushchestvuyushchej oblasti, funkciya shmat logicheski prisoedinyaet oblast' k virtual'nomu adresnomu prostranstvu processa, funkciya shmdt otsoedinyaet ee, a funkciya shmctl imeet delo s razlichnymi parametrami, svyazannymi s razdelyaemoj pamyat'yu. Processy vedut chtenie i zapis' dannyh v oblasti razdelyaemoj pamyati, ispol'zuya dlya etogo te zhe samye mashinnye koman- dy, chto i pri rabote s obychnoj pamyat'yu. Posle prisoedineniya k virtual'nomu adresnomu prostranstvu processa oblast' razdelyaemoj pamyati stanovitsya dos- tupna tak zhe, kak lyuboj uchastok virtual'noj pamyati; dlya dostupa k nahodyashchim- sya v nej dannym ne nuzhny obrashcheniya k kakim-to dopolnitel'nym sistemnym funk- ciyam. Sintaksis vyzova sistemnoj funkcii shmget: shmid = shmget(key,size,flag); gde size - ob容m oblasti v bajtah. YAdro ispol'zuet key dlya vedeniya poiska v tablice razdelyaemoj pamyati: esli podhodyashchaya zapis' obnaruzhena i esli razre- shenie na dostup imeetsya, yadro vozvrashchaet vyzyvayushchemu processu ukazannyj v zapisi deskriptor. Esli zapis' ne najdena i esli pol'zovatel' ustanovil flag IPC_CREAT, ukazyvayushchij na neobhodimost' sozdaniya novoj oblasti, yadro prove- ryaet nahozhdenie razmera oblasti v ustanovlennyh sistemoj predelah i vydelyaet oblast' po algoritmu allocreg (razdel 6.5.2). YAdro zapisyvaet ustanovki prav dostupa, razmer oblasti i ukazatel' na sootvetstvuyushchuyu zapis' tablicy oblas- tej v tablicu razdelyaemoj pamyati (Risunok 11.9) i ustanavlivaet flag, svide- tel'stvuyushchij o tom, chto s oblast'yu ne svyazana otdel'naya pamyat'. Oblasti vy- delyaetsya pamyat' (tablicy stranic i t.p.) tol'ko togda, kogda process prisoe- dinyaet oblast' k svoemu adresnomu prostranstvu. YAdro ustanavlivaet takzhe 341 flag, govoryashchij o tom, chto po zavershenii poslednego svyazannogo s oblast'yu processa oblast' ne dolzhna osvobozhdat'sya. Takim obrazom, dannye v razdelyae- moj pamyati ostayutsya v sohrannosti, dazhe esli ona ne prinadlezhit ni odnomu iz processov (kak chast' virtual'nogo adresnogo prostranstva poslednego). Tablica raz- Tablica processov - delyaemoj pa- Tablica oblastej chastnaya tablica ob- myati lastej processa +----------+ +--------------+ +---------+ | ----+----+ | | +----+---- | +----------+ +|->+--------------+<----+ +---------+ | ----+---+| | | +---+---- | +----------+ | +--------------+<----+| +---------+ | ----+--+ | | | +|---+---- | +----------+ | | +--------------+ | +---------+ | - | | | | | | | | | - | | +->+--------------+ | +---------+ | - | | | | | | | | - | +--->+--------------+<-----+ +---------+ | - | | | (posle | | | - | +--------------+ shmat) +---------+ | - | | - | | | | - | | - | +---------+ | - | +--------------+ | - | | - | | - | +----------+ +---------+ Risunok 11.9. Struktury dannyh, ispol'zuemye pri razdelenii pamyati Process prisoedinyaet oblast' razdelyaemoj pamyati k svoemu virtual'nomu adresnomu prostranstvu s pomoshch'yu sistemnoj funkcii shmat: virtaddr = shmat(id,addr,flags); Znachenie id, vozvrashchaemoe funkciej shmget, identificiruet oblast' razdelyae- moj pamyati, addr yavlyaetsya virtual'nym adresom, po kotoromu pol'zovatel' ho- chet podklyuchit' oblast', a s pomoshch'yu flagov (flags) mozhno ukazat', prednazna- chena li oblast' tol'ko dlya chteniya i nuzhno li yadru okruglyat' znachenie ukazan- nogo pol'zovatelem adresa. Vozvrashchaemoe funkciej znachenie, virtaddr, preds- tavlyaet soboj virtual'nyj adres, po kotoromu yadro proizvelo podklyuchenie ob- lasti i kotoryj ne vsegda sovpadaet s adresom, ukazannym pol'zovatelem. V nachale vypolneniya sistemnoj funkcii shmat yadro proveryaet nalichie u processa neobhodimyh prav dostupa k oblasti (Risunok 11.10). Ono issleduet ukazannyj pol'zovatelem adres; esli on raven 0, yadro vybiraet virtual'nyj adres po svoemu usmotreniyu. Oblast' razdelyaemoj pamyati ne dolzhna peresekat'sya v virtual'nom adresnom prostranstve processa s drugimi oblastyami; sledovatel'no, ee vybor dolzhen proizvodit'sya razumno i ostorozhno. Tak, naprimer, process mozhet uvelichit' razmer prinadlezhashchej emu oblasti dannyh s pomoshch'yu sistemnoj funkcii brk, i novaya oblast' dannyh budet soderzhat' adresa, smezhnye s prezhnej oblast'yu; po- etomu, yadru ne sleduet prisoedinyat' oblast' razdelyaemoj pamyati slishkom bliz- ko k oblasti dannyh processa. Tak zhe ne sleduet razmeshchat' oblast' razdelyae- moj pamyati vblizi ot vershiny steka, chtoby stek pri svoem posleduyushchem uveli- chenii ne zalezal za ee predely. Esli, naprimer, stek rastet v napravlenii uvelicheniya adresov, luchshe vsego razmestit' oblast' razdelyaemoj pamyati nepos- redstvenno pered nachalom oblasti steka. YAdro proveryaet vozmozhnost' razmeshcheniya oblasti razdelyaemoj pamyati v ad- 342 +------------------------------------------------------------+ | algoritm shmat /* podklyuchit' razdelyaemuyu pamyat' */ | | vhodnaya informaciya: (1) deskriptor oblasti razdelyaemoj | | pamyati | | (2) virtual'nyj adres dlya podklyucheniya | | oblasti | | (3) flagi | | vyhodnaya informaciya: virtual'nyj adres, po kotoromu oblast'| | podklyuchena fakticheski | | { | | proverit' pravil'nost' ukazaniya deskriptora, prava do- | | stupa k oblasti; | | esli (pol'zovatel' ukazal virtual'nyj adres) | | { | | okruglit' virtual'nyj adres v sootvetstvii s fla- | | gami; | | proverit' sushchestvovanie poluchennogo adresa, razmer| | oblasti; | | } | | v protivnom sluchae /* pol'zovatel' hochet, chtoby yadro | | * samo nashlo podhodyashchij adres */ | | yadro vybiraet adres: v sluchae neudachi vydaetsya | | oshibka; | | prisoedinit' oblast' k adresnomu prostranstvu processa | | (algoritm attachreg); | | esli (oblast' prisoedinyaetsya vpervye) | | vydelit' tablicy stranic i otvesti pamyat' pod nee | | (algoritm growreg); | | vernut' (virtual'nyj adres fakticheskogo prisoedineniya | | oblasti); | | } | +------------------------------------------------------------+ Risunok 11.10. Algoritm prisoedineniya razdelyaemoj pamyati resnom prostranstve processa i prisoedinyaet ee s pomoshch'yu algoritma attachreg. Esli vyzyvayushchij process yavlyaetsya pervym processom, kotoryj priso- edinyaet oblast', yadro vydelyaet dlya oblasti vse neobhodimye tablicy, ispol'- zuya algoritm growreg, zapisyvaet vremya prisoedineniya v sootvetstvuyushchee pole tablicy razdelyaemoj pamyati i vozvrashchaet processu virtual'nyj adres, po koto- romu oblast' byla im podklyuchena fakticheski. Otsoedinenie oblasti razdelyaemoj pamyati ot virtual'nogo adresnogo prost- ranstva processa vypolnyaet funkciya shmdt(addr) gde addr - virtual'nyj adres, vozvrashchennyj funkciej shmat. Nesmotrya na to, chto bolee logichnoj predstavlyaetsya peredacha identifikatora, process ispol'zu- et virtual'nyj adres razdelyaemoj pamyati, poskol'ku odna i ta zhe oblast' raz- delyaemoj pamyati mozhet byt' podklyuchena k adresnomu prostranstvu processa nes- kol'ko raz, k tomu zhe ee identifikator mozhet byt' udalen iz sistemy. YAdro proizvodit poisk oblasti po ukazannomu adresu i otsoedinyaet ee ot adresnogo prostranstva processa, ispol'zuya algoritm detachreg (razdel 6.5.7). Poskol'- ku v tablicah oblastej otsutstvuyut obratnye ukazateli na tablicu razdelyaemoj pamyati, yadru prihoditsya prosmatrivat' tablicu razdelyaemoj pamyati v poiskah zapisi, ukazyvayushchej na dannuyu oblast', i zapisyvat' v sootvetstvuyushchee pole vremya poslednego otklyucheniya oblasti. Rassmotrim programmu, predstavlennuyu na Risunke 11.11. V nej opisyvaetsya 343 process, sozdayushchij oblast' razdelyaemoj pamyati razmerom 128 Kbajt i dvazhdy prisoedinyayushchij ee k svoemu adresnomu prostranstvu po raznym virtual'nym ad- resam. V "pervuyu" oblast' on zapisyvaet dannye, a chitaet ih iz "vtoroj" ob- lasti. Na Risunke 11.12 pokazan drugoj process, prisoedinyayushchij tu zhe oblast' (on poluchaet tol'ko 64 Kbajta, takim obrazom, kazhdyj process mozhet ispol'zo- vat' raznyj ob容m oblasti razdelyaemoj pamyati); on zhdet momenta, kogda pervyj process zapishet v pervoe prinadlezhashchee oblasti slovo lyuboe otlichnoe ot nulya znachenie, i zatem prinimaetsya schityvat' dannye iz oblasti. Pervyj process delaet "pauzu" (pause), predostavlyaya vtoromu processu vozmozhnost' vypolne- niya; kogda pervyj process prinimaet signal, on udalyaet oblast' razdelyaemoj pamyati iz sistemy. Process zaprashivaet informaciyu o sostoyanii oblasti razdelyaemoj pamyati i proizvodit ustanovku parametrov dlya nee s pomoshch'yu sistemnoj funkcii shmctl: shmctl(id,cmd,shmstatbuf); Znachenie id identificiruet zapis' tablicy razdelyaemoj pamyati, cmd opredelyaet tip operacii, a shmstatbuf yavlyaetsya adresom pol'zovatel'skoj struktury, v kotoruyu pomeshchaetsya informaciya o sostoyanii oblasti. YAdro traktuet tip opera- cii tochno tak zhe, kak i pri upravlenii soobshcheniyami. Udalyaya oblast' razdelyae- moj pamyati, yadro osvobozhdaet sootvetstvuyushchuyu ej zapis' v tablice razdelyaemoj pamyati i prosmatrivaet tablicu oblastej: esli oblast' ne byla prisoedinena ni k odnomu iz processov, yadro osvobozhdaet zapis' tablicy i vse vydelennye oblasti resursy, ispol'zuya dlya etogo algoritm freereg (razdel 6.5.6). Esli zhe oblast' po-prezhnemu podklyuchena k kakim-to processam (znachenie schetchika ssylok na nee bol'she 0), yadro tol'ko sbrasyvaet flag, govoryashchij o tom, chto po zavershenii poslednego svyazannogo s neyu processa oblast' ne dolzhna osvo- bozhdat'sya. Processy, uzhe ispol'zuyushchie oblast' razdelyaemoj pamyati, prodolzhayut rabotat' s nej, novye zhe processy ne mogut prisoedinit' ee. Kogda vse pro- cessy otklyuchat oblast', yadro osvobodit ee. |to pohozhe na to, kak v fajlovoj sisteme posle razryva svyazi s fajlom process mozhet vnov' otkryt' ego i pro- dolzhat' s nim rabotu.

    11.2.3 Semafory

Sistemnye funkcii raboty s semaforami obespechivayut sinhronizaciyu vypol- neniya parallel'nyh processov, proizvodya nabor dejstvij edinstvenno nad grup- poj semaforov (sredstvami nizkogo urovnya). Do ispol'zovaniya semaforov, esli processu nuzhno bylo zablokirovat' nekij resurs, on pribegal k sozdaniyu s po- moshch'yu sistemnoj funkcii creat special'nogo blokiruyushchego fajla. Esli fajl uzhe sushchestvoval, funkciya creat zavershalas' neudachno, i process delal vyvod o tom, chto resurs uzhe zablokirovan drugim processom. Glavnye nedostatki takogo podhoda zaklyuchalis' v tom, chto process ne znal, v kakoj moment emu sleduet predprinyat' sleduyushchuyu popytku, a takzhe v tom, chto blokiruyushchie fajly sluchajno ostavalis' v sisteme v sluchae ee avarijnogo zaversheniya ili perezagruzki. Dijkstroj byl opublikovan algoritm Dekkera, opisyvayushchij realizaciyu sema- forov kak celochislennyh ob容ktov, dlya kotoryh opredeleny dve elementarnye operacii: P i V (sm. [Dijkstra 68]). Operaciya P zaklyuchaetsya v umen'shenii znacheniya semafora v tom sluchae, esli ono bol'she 0, operaciya V - v uvelichenii etogo znacheniya (i tam, i tam na edinicu). Poskol'ku operacii elementarnye, v lyuboj moment vremeni dlya kazhdogo semafora vypolnyaetsya ne bolee odnoj opera- cii P ili V. Svyazannye s semaforami sistemnye funkcii yavlyayutsya obobshcheniem operacij, predlozhennyh Dijkstroj, v nih dopuskaetsya odnovremennoe vypolnenie neskol'kih operacij, prichem operacii umen'sheniya i uvelicheniya vypolnyayutsya nad znacheniyami, prevyshayushchimi 1. YAdro vypolnyaet operacii kompleksno; ni odin iz postoronnih processov ne smozhet pereustanavlivat' znacheniya semaforov, poka 344 vse operacii ne budut vypolneny. Esli yadro po kakim-libo prichinam ne mozhet vypolnit' vse operacii, ono ne vypolnyaet ni odnoj; process priostanavlivaet svoyu rabotu do teh por, poka eta vozmozhnost' ne budet predostavlena. Semafor v versii V sistemy UNIX sostoit iz sleduyushchih elementov: * Znachenie semafora, * Identifikator poslednego iz processov, rabotavshih s semaforom, * Kolichestvo processov, ozhidayushchih uvelicheniya znacheniya semafora, * Kolichestvo processov, ozhidayushchih momenta, kogda znachenie semafora stanet ravnym 0. Dlya sozdaniya nabora semaforov i polucheniya dostupa k nim ispol'zuetsya sistemnaya funkciya semget, dlya vypolneniya razlichnyh upravlyayushchih operacij nad naborom - funkciya semctl, dlya raboty so znacheniyami semaforov - funkciya semop. +------------------------------------------------------------+ | #include | | #include | | #include | | #define SHMKEY 75 | | #define K 1024 | | int shmid; | | | | main() | | { | | int i, *pint; | | char *addr1, *addr2; | | extern char *shmat(); | | extern cleanup(); | | | | for (i = 0; i < 20; i++) | | signal(i,cleanup); | | shmid = shmget(SHMKEY,128*K,0777|IPC_CREAT); | | addr1 = shmat(shmid,0,0); | | addr2 = shmat(shmid,0,0); | | printf("addr1 Ox%x addr2 Ox%x\n",addr1,addr2); | | pint = (int *) addr1; | | | | for (i = 0; i < 256, i++) | | *pint++ = i; | | pint = (int *) addr1; | | *pint = 256; | | | | pint = (int *) addr2; | | for (i = 0; i < 256, i++) | | printf("index %d\tvalue %d\n",i,*pint++); | | | | pause(); | | } | | | | cleanup() | | { | | shmctl(shmid,IPC_RMID,0); | | exit(); | | } | +------------------------------------------------------------+ Risunok 11.11. Prisoedinenie processom odnoj i toj zhe oblasti razdelyaemoj pamyati dvazhdy 345 +-----------------------------------------------------+ | #include | | #include | | #include | | | | #define SHMKEY 75 | | #define K 1024 | | int shmid; | | | | main() | | { | | int i, *pint; | | char *addr; | | extern char *shmat(); | | | | shmid = shmget(SHMKEY,64*K,0777); | | | | addr = shmat(shmid,0,0); | | pint = (int *) addr; | | | | while (*pint == 0) | | ; | | for (i = 0; i < 256, i++) | | printf("%d\n",*pint++); | | } | +-----------------------------------------------------+ Risunok 11.12. Razdelenie pamyati mezhdu processami Tablica semaforov Massivy semaforov +-------+ | | +---+---+---+---+---+---+---+ | +------->| 0 | 1 | 2 | 3 | 4 | 5 | 6 | | | +---+---+---+---+---+---+---+ +-------+ | | +---+---+---+ | +------->| 0 | 1 | 2 | | | +---+---+---+ +-------+ | | +---+ | +------->| 0 | | | +---+ +-------+ | | +---+---+---+ | +------->| 0 | 1 | 2 | | | +---+---+---+ +-------+ | - | | - | | - | | - | | - | +-------+ Risunok 11.13. Struktury dannyh, ispol'zuemye v rabote nad semaforami 346 Sintaksis vyzova sistemnoj funkcii semget: id = semget(key,count,flag); gde key, flag i id imeyut tot zhe smysl, chto i v drugih mehanizmah vzaimodejs- tviya processov (obmen soobshcheniyami i razdelenie pamyati). V rezul'tate vypol- neniya funkcii yadro vydelyaet zapis', ukazyvayushchuyu na massiv semaforov i soder- zhashchuyu schetchik count (Risunok 11.13). V zapisi takzhe hranitsya kolichestvo se- maforov v massive, vremya poslednego vypolneniya funkcij semop i semctl. Sis- temnaya funkciya semget na Risunke 11.14, naprimer, sozdaet semafor iz dvuh elementov. Sintaksis vyzova sistemnoj funkcii semop: oldval = semop(id,oplist,count); gde id - deskriptor, vozvrashchaemyj funkciej semget, oplist - ukazatel' na spisok operacij, count - razmer spiska. Vozvrashchaemoe funkciej znachenie oldval yavlyaetsya prezhnim znacheniem semafora, nad +------------------------------------------------------------+ | #include | | #include | | #include | | | | #define SEMKEY 75 | | int semid; | | unsigned int count; | | /* opredelenie struktury sembuf v fajle sys/sem.h | | * struct sembuf { | | * unsigned shortsem_num; | | * short sem_op; | | * short sem_flg; | | }; */ | | struct sembuf psembuf,vsembuf; /* operacii tipa P i V */| | | | main(argc,argv) | | int argc; | | char *argv[]; | | { | | int i,first,second; | | short initarray[2],outarray[2]; | | extern cleanup(); | | | | if (argc == 1) | | { | | for (i = 0; i < 20; i++) | | signal(i,cleanup); | | semid = semget(SEMKEY,2,0777|IPC_CREAT); | | initarray[0] = initarray[1] = 1; | | semctl(semid,2,SETALL,initarray); | | semctl(semid,2,GETALL,outarray); | | printf("nachal'nye znacheniya semaforov %d %d\n", | | outarray[0],outarray[1]); | | pause(); /* priostanov do polucheniya signala */ | | } | | | | /* prodolzhenie na sleduyushchej stranice */ | +------------------------------------------------------------+ Risunok 11.14. Operacii ustanovki i snyatiya blokirovki 347 kotorym proizvodilas' operaciya. Kazhdyj element spiska operacij imeet sleduyu- shchij format: * nomer semafora, identificiruyushchij element massiva semaforov, nad kotorym vypolnyaetsya operaciya, * kod operacii, * flagi. +------------------------------------------------------------+ | else if (argv[1][0] == 'a') | | { | | first = 0; | | second = 1; | | } | | else | | { | | first = 1; | | second = 0; | | } | | | | semid = semget(SEMKEY,2,0777); | | psembuf.sem_op = -1; | | psembuf.sem_flg = SEM_UNDO; | | vsembuf.sem_op = 1; | | vsembuf.sem_flg = SEM_UNDO; | | | | for (count = 0; ; count++) | | { | | psembuf.sem_num = first; | | semop(semid,&psembuf,1); | | psembuf.sem_num = second; | | semop(semid,&psembuf,1); | | printf("process %d schetchik %d\n",getpid(),count); | | vsembuf.sem_num = second; | | semop(semid,&vsembuf,1); | | vsembuf.sem_num = first; | | semop(semid,&vsembuf,1); | | } | | } | | | | cleanup() | | { | | semctl(semid,2,IPC_RMID,0); | | exit(); | | } | +------------------------------------------------------------+ Risunok 11.14. Operacii ustanovki i snyatiya blokirovki (prodolzhenie) YAdro schityvaet spisok operacij oplist iz adresnogo prostranstva zadachi i proveryaet korrektnost' nomerov semaforov, a takzhe nalichie u processa neobho- dimyh razreshenij na chtenie i korrektirovku semaforov (Risunok 11.15). Esli takih razreshenij ne imeetsya, sistemnaya funkciya zavershaetsya neudachno. Esli yadru prihoditsya priostanavlivat' svoyu rabotu pri obrashchenii k spisku opera- cij, ono vozvrashchaet semaforam ih prezhnie znacheniya i nahoditsya v sostoyanii priostanova do nastupleniya ozhidaemogo sobytiya, posle chego sistem- naya funkciya zapuskaetsya vnov'. Poskol'ku yadro hranit kody operacij nad sema- forami v global'nom spiske, ono vnov' schityvaet etot spisok iz prostranstva 348 +------------------------------------------------------------+ | algoritm semop /* operacii nad semaforom */ | | vhodnaya informaciya: (1) deskriptor semafora | | (2) spisok operacij nad semaforom | | (3) kolichestvo elementov v spiske | | vyhodnaya informaciya: ishodnoe znachenie semafora | | { | | proverit' korrektnost' deskriptora semafora; | | start: schitat' spisok operacij nad semaforom iz prostran- | | stva zadachi v prostranstvo yadra; | | proverit' nalichie razreshenij na vypolnenie vseh opera- | | cij; | | | | dlya (kazhdoj operacii v spiske) | | { | | esli (kod operacii imeet polozhitel'noe znachenie) | | { | | pribavit' kod operacii k znacheniyu semafora; | | esli (dlya dannoj operacii ustanovlen flag UNDO)| | skorrektirovat' strukturu vosstanovleniya | | dlya dannogo processa; | | vyvesti iz sostoyaniya priostanova vse processy, | | ozhidayushchie uvelicheniya znacheniya semafora; | | } | | v protivnom sluchae esli (kod operacii imeet otrica-| | tel'noe znachenie) | | { | | esli (kod operacii + znachenie semafora >= 0) | | { | | pribavit' kod operacii k znacheniyu semafo- | | ra; | | esli (flag UNDO ustanovlen) | | skorrektirovat' strukturu vosstanov- | | leniya dlya dannogo processa; | | esli (znachenie semafora ravno 0) | | /* prodolzhenie na sleduyushchej strani- | | * ce */ | +------------------------------------------------------------+ Risunok 11.15. Algoritm vypolneniya operacij nad semaforom zadachi, kogda perezapuskaet sistemnuyu funkciyu. Takim obrazom, operacii vy- polnyayutsya kompleksno - ili vse za odin seans ili ni odnoj. YAdro menyaet znachenie semafora v zavisimosti ot koda operacii. Esli kod operacii imeet polozhitel'noe znachenie, yadro uvelichivaet znachenie semafora i vyvodit iz sostoyaniya priostanova vse processy, ozhidayushchie nastupleniya etogo sobytiya. Esli kod operacii raven 0, yadro proveryaet znachenie semafora: esli ono ravno 0, yadro perehodit k vypolneniyu drugih operacij; v protivnom sluchae yadro uvelichivaet chislo priostanovlennyh processov, ozhidayushchih, kogda znachenie semafora stanet nulevym, i "zasypaet". Esli kod operacii imeet otricatel'noe znachenie i esli ego absolyutnoe znachenie ne prevyshaet znachenie semafora, yadro pribavlyaet kod operacii (otricatel'noe chislo) k znacheniyu semafora. Esli re- zul'tat raven 0, yadro vyvodit iz sostoyaniya priostanova vse processy, ozhidayu- shchie obnuleniya znacheniya semafora. Esli rezul'tat men'she absolyutnogo znacheniya koda operacii, yadro priostanavlivaet process do teh por, poka zna- chenie semafora ne uvelichitsya. Esli process priostanavlivaetsya posredi opera- cii, on imeet prioritet, dopuskayushchij preryvaniya; sledovatel'no, poluchiv sig- nal, on vyhodit iz etogo sostoyaniya. 349 +------------------------------------------------------------+ | vyvesti iz sostoyaniya priostanova vse | | processy, ozhidayushchie obnuleniya znache-| | niya semafora; | | prodolzhit'; | | } | | vypolnit' vse proizvedennye nad semaforom v | | dannom seanse operacii v obratnoj posledova- | | tel'nosti (vosstanovit' staroe znachenie sema- | | fora); | | esli (flagi ne velyat priostanavlivat'sya) | | vernut'sya s oshibkoj; | | priostanovit'sya (do teh por, poka znachenie se- | | mafora ne uvelichitsya); | | perejti na start; /* povtorit' cikl s samogo | | * nachala * / | | } | | v protivnom sluchae /* kod operacii raven nulyu */| | { | | esli (znachenie semafora otlichno ot nulya) | | { | | vypolnit' vse proizvedennye nad semaforom | | v dannom seanse operacii v obratnoj po- | | sledovatel'nosti (vosstanovit' staroe | | znachenie semafora); | | esli (flagi ne velyat priostanavlivat'sya) | | vernut'sya s oshibkoj; | | priostanovit'sya (do teh por, poka znachenie| | semafora ne stanet nulevym); | | perejti na start; /* povtorit' cikl */ | | } | | } | | } /* konec cikla */ | | /* vse operacii nad semaforom vypolneny */ | | skorrektirovat' znacheniya polej, v kotoryh hranitsya vre-| | mya poslednego vypolneniya operacij i identifikatory | | processov; | | vernut' ishodnoe znachenie semafora, sushchestvovavshee v | | moment vyzova funkcii semop; | | } | +------------------------------------------------------------+ Risunok 11.15. Algoritm vypolneniya operacij nad semaforom (prodolzhenie) Perejdem k programme, predstavlennoj na Risunke 11.14, i predpolozhim, chto pol'zovatel' ispolnyaet ee (pod imenem a.out) tri raza v sleduyushchem poryad- ke: a.out & a.out a & a.out b & Esli programma vyzyvaetsya bez parametrov, process sozdaet nabor semafo- rov iz dvuh elementov i prisvaivaet kazhdomu semaforu znachenie, ravnoe 1. Za- tem process vyzyvaet funkciyu pause i priostanavlivaetsya dlya polucheniya signa- la, posle chego udalyaet semafor iz sistemy (cleanup). Pri vypolnenii program- my s parametrom 'a' process (A) proizvodit nad semaforami v cikle chetyre operacii: on umen'shaet na edinicu znachenie semafora 0, to zhe samoe delaet s semaforom 1, vypolnyaet komandu vyvoda na pechat' i vnov' uvelichivaet znacheniya semaforov 0 i 1. Esli by process popytalsya umen'shit' znachenie semafora, rav- 350 noe 0, emu prishlos' by priostanovit'sya, sledovatel'no, semafor mozhno schitat' zahvachennym (nedostupnym dlya umen'sheniya). Poskol'ku ishodnye znacheniya sema- forov byli ravny 1 i poskol'ku k semaforam ne bylo obrashchenij so storony dru- gih processov, process A nikogda ne priostanovitsya, a znacheniya semaforov bu- dut izmenyat'sya tol'ko mezhdu 1 i 0. Pri vypolnenii programmy s parametrom 'b' process (B) umen'shaet znacheniya semaforov 0 i 1 v poryadke, obratnom hodu vy- polneniya processa A. Kogda processy A i B vypolnyayutsya parallel'no, mozhet slozhit'sya situaciya, v kotoroj process A zahvatil semafor 0 i hochet zahvatit' semafor 1, a process B zahvatil semafor 1 i hochet zahvatit' semafor 0. Oba processa perejdut v sostoyanie priostanova, ne imeya vozmozhnosti prodolzhit' svoe vypolnenie. Voznikaet vzaimnaya blokirovka, iz kotoroj processy mogut vyjti tol'ko po poluchenii signala. CHtoby predotvratit' vozniknovenie podobnyh problem, processy mogut vy- polnyat' odnovremenno neskol'ko operacij nad semaforami. V poslednem primere zhelaemyj effekt dostigaetsya blagodarya ispol'zovaniyu sleduyushchih operatorov: struct sembuf psembuf[2]; psembuf[0].sem_num = 0; psembuf[1].sem_num = 1; psembuf[0].sem_op = -1; psembuf[1].sem_op = -1; semop(semid,psembuf,2); Psembuf - eto spisok operacij, vypolnyayushchih odnovremennoe umen'shenie znachenij semaforov 0 i 1. Esli kakaya-to operaciya ne mozhet vypolnyat'sya, process prios- tanavlivaetsya. Tak, naprimer, esli znachenie semafora 0 ravno 1, a znachenie semafora 1 ravno 0, yadro ostavit oba znacheniya neizmennymi do teh por, poka ne smozhet umen'shit' i to, i drugoe. Ustanovka flaga IPC_NOWAIT v funkcii semop imeet sleduyushchij smysl: esli yadro popadaet v takuyu situaciyu, kogda process dolzhen priostanovit' svoe vy- polnenie v ozhidanii uvelicheniya znacheniya semafora vyshe opredelennogo urovnya ili, naoborot, snizheniya etogo znacheniya do 0, i esli pri etom flag IPC_NOWAIT ustanovlen, yadro vyhodit iz funkcii s izveshcheniem ob oshibke. Takim obrazom, esli ne priostanavlivat' process v sluchae nevozmozhnosti vypolneniya otdel'noj operacii, mozhno realizovat' uslovnyj tip semafora. Esli process vypolnyaet operaciyu nad semaforom, zahvatyvaya pri etom neko- torye resursy, i zavershaet svoyu rabotu bez privedeniya semafora v ishodnoe sostoyanie, mogut vozniknut' opasnye situacii. Prichinami vozniknoveniya takih situacij mogut byt' kak oshibki programmirovaniya, tak i signaly, privodyashchie k vnezapnomu zaversheniyu vypolneniya processa. Esli posle togo, kak process umen'shit znacheniya semaforov, on poluchit signal kill, vosstanovit' prezhnie znacheniya processu uzhe ne udastsya, poskol'ku signaly dannogo tipa ne analizi- ruyutsya processom. Sledovatel'no, drugie processy, pytayas' obratit'sya k sema- foram, obnaruzhat, chto poslednie zablokirovany, hotya sam zablokirovavshij ih process uzhe prekratil svoe sushchestvovanie. CHtoby izbezhat' vozniknoveniya po- dobnyh situacij, v funkcii semop process mozhet ustanovit' flag SEM_UNDO; kogda process zavershitsya, yadro dast obratnyj hod vsem operaciyam, vypolnennym processom. Dlya etogo v rasporyazhenii u yadra imeetsya tablica, v kotoroj kazhdo- mu processu v sisteme otvedena otdel'naya zapis'. Zapis' tablicy soderzhit ukazatel' na gruppu struktur vosstanovle- niya, po odnoj strukture na kazhdyj ispol'zuemyj processom semafor (Risunok 11.16). Kazhdaya struktura vosstanovleniya sostoit iz treh elementov - identi- fikatora semafora, ego poryadkovogo nomera v nabore i ustanovochnogo znacheniya. YAdro vydelyaet struktury vosstanovleniya dinamicheski, vo vremya pervogo vy- polneniya sistemnoj funkcii semop s ustanovlennym flagom SEM_UNDO. Pri posle- duyushchih obrashcheniyah k funkcii s tem zhe flagom yadro prosmatrivaet struktury vosstanovleniya dlya processa v poiskah struktury s tem zhe samym identifikato- 351 Zagolovki chastnyh struktur vosstanovleniya Struktury vosstanovleniya +------+ | - | | - | | - | | - | +----------+ +----------+ +----------+ +------+ |Deskriptor| |Deskriptor| |Deskriptor| | +-->| Nomer +-->| Nomer +-->| Nomer | +------+ | Znachenie | | Znachenie | | Znachenie | | | +----------+ +----------+ +----------+ | | +----------+ +------+ |Deskriptor| | +-->| Nomer | +------+ | Znachenie | | - | +----------+ | - | | - | | - | +------+ Risunok 11.16. Struktury vosstanovleniya semaforov rom i poryadkovym nomerom semafora, chto i v formate vyzova funkcii. Esli struktura obnaruzhena, yadro vychitaet znachenie proizvedennoj nad semaforom operacii iz ustanovochnogo znacheniya. Takim obrazom, v strukture vosstanovle- niya hranitsya rezul'tat vychitaniya summy znachenij vseh operacij, proizvedennyh nad semaforom, dlya kotorogo ustanovlen flag SEM_UNDO. Esli sootvetstvuyushchej struktury net, yadro sozdaet ee, sortiruya pri etom spisok struktur po identi- fikatoram i nomeram semaforov. Esli ustanovochnoe znachenie stanovitsya ravnym 0, yadro udalyaet strukturu iz spiska. Kogda process zavershaetsya, yadro vyzyva- +---------------++-------+ +---------------++-------+-------+ | identifikator || | | identifikator || | | | semafora || semid | | semafora || semid | semid | +---------------++-------+ +---------------++-------+-------+ | nomer semafora|| 0 | | nomer semafora|| 0 | 1 | +---------------++-------+ +---------------++-------+-------+ | ustanovochnoe || | | ustanovochnoe || | | | znachenie || 1 | | znachenie || 1 | 1 | +---------------++-------+ +---------------++-------+-------+ (a) Posle pervoj operacii (b) Posle vtoroj operacii +---------------++-------+ | identifikator || | | semafora || semid | +---------------++-------+ | nomer semafora|| 0 | pusto +---------------++-------+ | ustanovochnoe || | | znachenie || 1 | +---------------++-------+ (v) Posle tret'ej operacii (g) Posle chetvertoj operacii Risunok 11.17. Posledovatel'nost' sostoyanij spiska struktur vosstanovleniya 352 et special'nuyu proceduru, kotoraya prosmatrivaet vse svyazannye s processom struktury vosstanovleniya i vypolnyaet nad ukazannym semaforom vse obuslovlen- nye dejstviya. YAdro sozdaet strukturu vosstanovleniya vsyakij raz, kogda process umen'sha- et znachenie semafora, a udalyaet ee, kogda process uvelichivaet znachenie sema- fora, poskol'ku ustanovochnoe znachenie struktury ravno 0. Na Risunke 11.17 pokazana posledovatel'nost' sostoyanij spiska struktur pri vypolnenii programmy s parametrom 'a'. Posle pervoj ope- racii process imeet odnu strukturu, sostoyashchuyu iz identifikatora semid, nome- ra semafora, ravnogo 0, i ustanovochnogo znacheniya, ravnogo 1, a posle vtoroj operacii poyavlyaetsya vtoraya struktura s nomerom semafora, ravnym 1, i ustano- vochnym znacheniem, ravnym 1. Esli process neozhidanno zavershaetsya, yadro proho- dit po vsem strukturam i pribavlyaet k kazhdomu semaforu po edinice, vossta- navlivaya ih znacheniya v 0. V chastnom sluchae yadro umen'shaet ustanovochnoe zna- chenie dlya semafora 1 na tret'ej operacii, v sootvetstvii s uvelicheniem zna- cheniya samogo semafora, i udalyaet vsyu strukturu celikom, poskol'ku ustanovoch- noe znachenie stanovitsya nulevym. Posle chetvertoj operacii u processa bol'she net struktur vosstanovleniya, poskol'ku vse ustanovochnye znacheniya stali nule- vymi. Vektornye operacii nad semaforami pozvolyayut izbezhat' vzaimnyh blokiro- vok, kak bylo pokazano vyshe, odnako oni predstavlyayut izvestnuyu trudnost' dlya ponimaniya i realizacii, i v bol'shinstve prilozhenij polnyj nabor ih vozmozh- nostej ne yavlyaetsya obyazatel'nym. Programmy, ispytyvayushchie potrebnost' v is- pol'zovanii nabora semaforov, stalkivayutsya s vozniknoveniem vzaimnyh bloki- rovok na pol'zovatel'skom urovne, i yadru uzhe net neobhodimosti podderzhivat' takie slozhnye formy sistemnyh funkcij. Sintaksis vyzova sistemnoj funkcii semctl: semctl(id,number,cmd,arg); Parametr arg ob座avlen kak ob容dinenie tipov dannyh: union semunion { int val; struct semid_ds *semstat; /* opisanie tipov sm. v Pri- * lozhenii */ unsigned short *array; } arg; YAdro interpretiruet parametr arg v zavisimosti ot znacheniya parametra cmd, podobno tomu, kak interpretiruet komandy ioctl (glava 10). Tipy dejst- vij, kotorye mogut ispol'zovat'sya v parametre cmd: poluchit' ili ustanovit' znacheniya upravlyayushchih parametrov (prava dostupa i dr.), ustanovit' znacheniya odnogo ili vseh semaforov v nabore, prochitat' znacheniya semaforov. Podrobnos- ti po kazhdomu dejstviyu soderzhatsya v Prilozhenii. Esli ukazana komanda udale- niya, IPC_RMID, yadro vedet poisk vseh processov, soderzhashchih struktury vossta- novleniya dlya dannogo semafora, i udalyaet sootvetstvuyushchie struktury iz siste- my. Zatem yadro inicializiruet ispol'zuemye semaforom struktury dannyh i vy- vodit iz sostoyaniya priostanova vse processy, ozhidayushchie nastupleniya nekotoro- go svyazannogo s semaforom sobytiya: kogda processy vozobnovlyayut svoe vypolne- nie, oni obnaruzhivayut, chto identifikator semafora bol'she ne yavlyaetsya korrek- tnym, i vozvrashchayut vyzyvayushchej programme oshibku.

    11.2.4 Obshchie zamechaniya

Mehanizm funkcionirovaniya fajlovoj sistemy i mehanizmy vzaimodejstviya 353 processov imeyut ryad obshchih chert. Sistemnye funkcii tipa "get" pohozhi na funk- cii creat i open, funkcii tipa "control" predostavlyayut vozmozhnost' udalyat' deskriptory iz sistemy, chem pohozhi na funkciyu unlink. Tem ne menee, v meha- nizmah vzaimodejstviya processov otsutstvuyut operacii, analogichnye operaciyam, vypolnyaemym sistemnoj funkciej close. Sledovatel'no, yadro ne raspolagaet svedeniyami o tom, kakie processy mogut ispol'zovat' mehanizm IPC, i, dejst- vitel'no, processy mogut pribegat' k uslugam etogo mehanizma, esli pravil'no ugadyvayut sootvetstvuyushchij identifikator i esli u nih imeyutsya neobhodimye prava dostupa, dazhe esli oni ne vypolnili predvaritel'no funkciyu tipa "get". YAdro ne mozhet avtomaticheski ochishchat' neispol'zuemye struktury mehanizma vzai- modejstviya processov, poskol'ku yadru neizvestno, kakie iz etih struktur bol'she ne nuzhny. Takim obrazom, zavershivshiesya vsledstvie vozniknoveniya oshib- ki processy mogut ostavit' posle sebya nenuzhnye i neispol'zuemye struktury, peregruzhayushchie i zasoryayushchie sistemu. Nesmotrya na to, chto v strukturah meha- nizma vzaimodejstviya posle zaversheniya sushchestvovaniya processa yadro mozhet soh- ranit' informaciyu o sostoyanii i dannye, luchshe vse-taki dlya etih celej is- pol'zovat' fajly. Vmesto tradicionnyh, poluchivshih shirokoe rasprostranenie fajlov mehanizmy vzaimodejstviya processov ispol'zuyut novoe prostranstvo imen, sostoyashchee iz klyuchej (keys). Rasshirit' semantiku klyuchej na vsyu set' dovol'no trudno, pos- kol'ku na raznyh mashinah klyuchi mogut opisyvat' razlichnye ob容kty. Koroche go- vorya, klyuchi v osnovnom prednaznacheny dlya ispol'zovaniya v odnomashinnyh siste- mah. Imena fajlov v bol'shej stepeni podhodyat dlya raspredelennyh sistem (sm. glavu 13). Ispol'zovanie klyuchej vmesto imen fajlov takzhe svidetel'stvuet o tom, chto sredstva vzaimodejstviya processov yavlyayutsya "veshch'yu v sebe", poleznoj v special'nyh prilozheniyah, no ne imeyushchej teh vozmozhnostej, kotorymi oblada- yut, naprimer, kanaly i fajly. Bol'shaya chast' funkcional'nyh vozmozhnostej, predostavlyaemyh dannymi sredstvami, mozhet byt' realizovana s pomoshch'yu drugih sistemnyh sredstv, poetomu vklyuchat' ih v sostav yadra vryad li sledovalo by. Tem ne menee, ih ispol'zovanie v sostave paketov prikladnyh programm tesnogo vzaimodejstviya daet luchshie rezul'taty po sravneniyu so standartnymi fajlovymi sredstvami (sm. Uprazhneniya).

    11.3 VZAIMODEJSTVIE V SETI

Programmy, podderzhivayushchie mezhmashinnuyu svyaz', takie, kak elektronnaya poch- ta, programmy distancionnoj peresylki fajlov i udalennoj registracii, izdav- na ispol'zuyutsya v kachestve special'nyh sredstv organizacii podklyuchenij i in- formacionnogo obmena. Tak, naprimer, standartnye programmy, rabotayushchie v sostave elektronnoj pochty, sohranyayut tekst pochtovyh soobshchenij pol'zovatelya v otdel'nom fajle (dlya pol'zovatelya "mjb" etot fajl imeet imya "/usr/mail/mjb"). Kogda odin pol'zovatel' posylaet drugomu pochtovoe soobshche- nie na tu zhe mashinu, programma mail (pochta) dobavlyaet soobshchenie v konec faj- la adresata, ispol'zuya v celyah sohraneniya celostnosti razlichnye blokiruyushchie i vremennye fajly. Kogda adresat poluchaet pochtu, programma mail otkryvaet prinadlezhashchij emu pochtovyj fajl i chitaet soobshcheniya. Dlya togo, chtoby poslat' soobshchenie na druguyu mashinu, programma mail dolzhna v konechnom itoge otyskat' na nej sootvetstvuyushchij pochtovyj fajl. Poskol'ku programma ne mozhet rabotat' s udalennymi fajlami neposredstvenno, process, protekayushchij na drugoj mashine, dolzhen dejstvovat' v kachestve agenta lokal'nogo pochtovogo processa; sledova- tel'no, lokal'nomu processu neobhodim sposob svyazi so svoim udalennym agen- tom cherez mezhmashinnye granicy. Lokal'nyj process yavlyaetsya klientom udalenno- go obsluzhivayushchego (servernogo) processa. Poskol'ku v sisteme UNIX novye processy sozdayutsya s pomoshch'yu sistemnoj funkcii fork, k tomu momentu, kogda klient popytaetsya vypolnit' podklyuchenie, obsluzhivayushchij process uzhe dolzhen sushchestvovat'. Esli by v moment sozdaniya no- vogo processa udalennoe yadro poluchalo zapros na podklyuchenie (po kanalam mezh- mashinnoj svyazi), voznikla by nesoglasovannost' s arhitekturoj sistemy. CHtoby 354 izbezhat' etogo, nekij process, obychno init, porozhdaet obsluzhivayushchij process, kotoryj vedet chtenie iz kanala svyazi, poka ne poluchaet zapros na obsluzhiva- nie, posle chego v sootvetstvii s nekotorym protokolom vypolnyaet ustanovku soedineniya. Vybor setevyh sredstv i protokolov obychno vypolnyayut programmy klienta i servera, osnovyvayas' na informacii, hranyashchejsya v prikladnyh bazah dannyh; s drugoj storony, vybrannye pol'zovatelem sredstva mogut byt' zako- dirovany v samih programmah. V kachestve primera rassmotrim programmu uucp, kotoraya obsluzhivaet pere- sylku fajlov v seti i ispolnenie komand na udalenii (sm. [Nowitz 80]). Pro- cess-klient zaprashivaet v baze dannyh adres i druguyu marshrutnuyu informaciyu (naprimer, nomer telefona), otkryvaet avtokommutator, zapisyvaet ili prove- ryaet informaciyu v deskriptore otkryvaemogo fajla i vyzyvaet udalennuyu mashi- nu. Udalennaya mashina mozhet imet' special'nye linii, vydelennye dlya ispol'zo- vaniya programmoj uucp; vypolnyayushchijsya na etoj mashine process init porozhdaet getty-processy - servery, kotorye upravlyayut liniyami i poluchayut izveshcheniya o podklyucheniyah. Posle vypolneniya apparatnogo podklyucheniya process-klient regis- triruetsya v sisteme v sootvetstvii s obychnym protokolom registracii: getty-process zapuskaet special'nyj interpretator komand, uucico, ukazannyj v fajle "/etc/passwd", a process-klient peredaet na udalennuyu mashinu posle- dovatel'nost' komand, tem samym zastavlyaya ee ispolnyat' processy ot imeni lo- kal'noj mashiny. Setevoe vzaimodejstvie v sisteme UNIX predstavlyaet ser'eznuyu problemu, poskol'ku soobshcheniya dolzhny vklyuchat' v sebya kak informacionnuyu, tak i uprav- lyayushchuyu chasti. V upravlyayushchej chasti soobshcheniya mozhet raspolagat'sya adres nazna- cheniya soobshcheniya. V svoyu ochered', struktura adresnyh dannyh zavisit ot tipa seti i ispol'zuemogo protokola. Sledovatel'no, processam nuzhno znat' tip se- ti, a eto idet vrazrez s tem principom, po kotoromu pol'zovateli ne dolzhny obrashchat' vnimaniya na tip fajla, ibo vse ustrojstva dlya pol'zovatelej vyglya- dyat kak fajly. Tradicionnye metody realizacii setevogo vzaimodejstviya pri ustanovke upravlyayushchih parametrov v sil'noj stepeni polagayutsya na pomoshch' sis- temnoj funkcii ioctl, odnako v raznyh tipah setej etot moment voploshchaetsya po-raznomu. Otsyuda voznikaet nezhelatel'nyj pobochnyj effekt, svyazannyj s tem, chto programmy, razrabotannye dlya odnoj seti, v drugih setyah mogut ne zarabo- tat'. CHtoby razrabotat' setevye interfejsy dlya sistemy UNIX, byli predprinyaty znachitel'nye usiliya. Realizaciya potokov v poslednih redakciyah versii V ras- polagaet elegantnym mehanizmom podderzhki setevogo vzaimodejstviya, obespechi- vayushchim gibkoe sochetanie otdel'nyh modulej protokolov i ih soglasovannoe is- pol'zovanie na urovne zadach. Sleduyushchij razdel posvyashchen kratkomu opisaniyu me- toda resheniya dannyh problem v sisteme BSD, osnovannogo na ispol'zovanii gnezd.

    11.4 GNEZDA

V predydushchem razdele bylo pokazano, kakim obrazom vzaimodejstvuyut mezhdu soboj processy, protekayushchie na raznyh mashinah, pri etom obrashchalos' vnimanie na to, chto sposoby realizacii vzaimodejstviya mogut byt' razlichat'sya v zavi- simosti ot ispol'zuemyh protokolov i setevyh sredstv. Bolee togo, eti sposo- by ne vsegda primenimy dlya obsluzhivaniya vzaimodejstviya processov, vypolnyayu- shchihsya na odnoj i toj zhe mashine, poskol'ku v nih predpolagaetsya sushchestvovanie obsluzhivayushchego (servernogo) processa, kotoryj pri vypolnenii sistemnyh funk- cij open ili read budet priostanavlivat'sya drajverom. V celyah sozdaniya bolee universal'nyh metodov vzaimodejstviya processov na osnove ispol'zovaniya mno- gourovnevyh setevyh protokolov dlya sistemy BSD byl razrabotan mehanizm, po- luchivshij nazvanie "sockets" (gnezda) (sm. [Berkeley 83]). V dannom razdele my rassmotrim nekotorye aspekty primeneniya gnezd (na pol'zovatel'skom urovne predstavleniya). 355 Process-klient Process-server | | +--+ +--+ +-------------------------+--+ +--+--------------------------+ | Uroven' gnezd | | Uroven' gnezd | +-------------------------+--+ +--+--------------------------+ | TCP | | TCP | | Uroven' protokolov | | | | Uroven' protokolov | | IP | | IP | +-------------------------+--+ +--+--------------------------+ | Drajver| | Drajver | | Uroven' ustrojstv Ethernet| |Ethernet Uroven' ustrojstv | +-------------------------+--+ +--+--------------------------+ +---+ +---+ | | S e t ' Risunok 11.18. Model' s ispol'zovaniem gnezd Struktura yadra imeet tri urovnya: gnezd, protokolov i ustrojstv (Risunok 11.18). Uroven' gnezd vypolnyaet funkcii interfejsa mezhdu obrashcheniyami k ope- racionnoj sisteme (sistemnym funkciyam) i sredstvami nizkih urovnej, uroven' protokolov soderzhit moduli, obespechivayushchie vzaimodejstvie processov (na ri- sunke upomyanuty protokoly TCP i IP), a uroven' ustrojstv soderzhit drajvery, upravlyayushchie setevymi ustrojstvami. Dopustimye sochetaniya protokolov i drajve- rov ukazyvayutsya pri postroenii sistemy (v sekcii konfiguracii); etot sposob ustupaet po gibkosti vysheupomyanutomu potokovomu mehanizmu. Processy vzaimo- dejstvuyut mezhdu soboj po sheme klient-server: server zhdet signala ot gnezda, nahodyas' na odnom konce dupleksnoj linii svyazi, a processy-klienty vzaimo- dejstvuyut s serverom cherez gnezdo, nahodyashcheesya na drugom konce, kotoryj mo- zhet raspolagat'sya na drugoj mashine. YAdro obespechivaet vnutrennyuyu svyaz' i pe- redaet dannye ot klienta k serveru. Gnezda, obladayushchie odinakovymi svojstvami, naprimer, opirayushchiesya na ob- shchie soglasheniya po identifikacii i formaty adresov (v protokolah), gruppiru- yutsya v domeny (upravlyaemye odnim uzlom). V sisteme BSD 4.2 podderzhivayutsya domeny: "UNIX system" - dlya vzaimodejstviya processov vnutri odnoj mashiny i "Internet" (mezhsetevoj) - dlya vzaimodejstviya cherez set' s pomoshch'yu protokola DARPA (Upravlenie perspektivnyh issledovanij i razrabotok Ministerstva obo- rony SSHA) (sm. [Postel 80] i [Postel 81]). Gnezda byvayut dvuh tipov: virtu- al'nyj kanal (potokovoe gnezdo, esli pol'zovat'sya terminologiej Berkli) i dejtagramma. Virtual'nyj kanal obespechivaet nadezhnuyu dostavku dannyh s soh- raneniem ishodnoj posledovatel'nosti. Dejtagrammy ne garantiruyut nadezhnuyu dostavku s sohraneniem unikal'nosti i posledovatel'nosti, no oni bolee eko- nomny v smysle ispol'zovaniya resursov, poskol'ku dlya nih ne trebuyutsya slozh- nye ustanovochnye operacii; takim obrazom, dejtagrammy polezny v otdel'nyh sluchayah vzaimodejstviya. Dlya kazhdoj dopustimoj kombinacii tipa domen-gnezdo v sisteme podderzhivaetsya umolchanie na ispol'zuemyj protokol. Tak, naprimer, dlya domena "Internet" uslugi virtual'nogo kanala vypolnyaet protokol trans- portnoj svyazi (TCP), a funkcii dejtagrammy - pol'zovatel'skij dejtagrammnyj protokol (UDP). Sushchestvuet neskol'ko sistemnyh funkcij raboty s gnezdami. Funkciya socket ustanavlivaet okonechnuyu tochku linii svyazi. sd = socket(format,type,protocol); Format oboznachaet domen ("UNIX system" ili "Internet"), type - tip svyazi che- rez gnezdo (virtual'nyj kanal ili dejtagramma), a protocol - tip protokola, upravlyayushchego vzaimodejstviem. Deskriptor gnezda sd, vozvrashchaemyj funkciej socket, ispol'zuetsya drugimi sistemnymi funkciyami. Zakrytie gnezd vypolnyaet 356 funkciya close. Funkciya bind svyazyvaet deskriptor gnezda s imenem: bind(sd,address,length); gde sd - deskriptor gnezda, address - adres struktury, opredelyayushchej identi- fikator, harakternyj dlya dannoj kombinacii domena i protokola (v funkcii socket). Length - dlina struktury address; bez etogo parametra yadro ne znalo by, kakova dlina struktury, poskol'ku dlya raznyh domenov i protokolov ona mozhet byt' razlichnoj. Naprimer, dlya domena "UNIX system" struktura soderzhit imya fajla. Processy-servery svyazyvayut gnezda s imenami i ob座avlyayut o sosto- yavshemsya prisvoenii imen processam-klientam. S pomoshch'yu sistemnoj funkcii connect delaetsya zapros na podklyuchenie k su- shchestvuyushchemu gnezdu: connect(sd,address,length); Semanticheskij smysl parametrov funkcii ostaetsya prezhnim (sm. funkciyu bind), no address ukazyvaet uzhe na vyhodnoe gnezdo, obrazuyushchee protivopolozhnyj ko- nec linii svyazi. Oba gnezda dolzhny ispol'zovat' odni i te zhe domen i proto- kol svyazi, i togda yadro udostoverit pravil'nost' ustanovki linii svyazi. Esli tip gnezda - dejtagramma, soobshchaemyj funkciej connect yadru adres budet is- pol'zovat'sya v posleduyushchih obrashcheniyah k funkcii send cherez dannoe gnezdo; v moment vyzova nikakih soedinenij ne proizvoditsya. Poka process-server gotovitsya k priemu svyazi po virtual'nomu kanalu, yad- ru sleduet vystroit' postupayushchie zaprosy v ochered' na obsluzhivanie. Maksi- mal'naya dlina ocheredi zadaetsya s pomoshch'yu sistemnoj funkcii listen: listen(sd,qlength) gde sd - deskriptor gnezda, a qlength - maksimal'no-dopustimoe chislo zapro- sov, ozhidayushchih obrabotki. +--------------------+ +-------------------------+ | Process-klient | | Process-server | | | | | | - | | | | | +----+ ------ | | | | | | - | | | | |listen addr accept addr| +---------+----------+ +-----+-------------------+ | | - +--------------------------+------------- Risunok 11.19. Priem vyzova serverom Sistemnaya funkciya accept prinimaet zaprosy na podklyuchenie, postupayushchie na vhod processa-servera: nsd = accept(sd,address,addrlen); gde sd - deskriptor gnezda, address - ukazatel' na pol'zovatel'skij massiv, v kotorom yadro vozvrashchaet adres podklyuchaemogo klienta, addrlen - razmer pol'zovatel'skogo massiva. Po zavershenii vypolneniya funkcii yadro zapisyvaet v peremennuyu addrlen razmer prostranstva, fakticheski zanyatogo massivom. Fun- kciya vozvrashchaet novyj deskriptor gnezda (nsd), otlichnyj ot deskriptora sd. Process-server mozhet prodolzhat' slezhenie za sostoyaniem ob座avlennogo gnezda, podderzhivaya svyaz' s klientom po otdel'nomu kanalu (Risunok 11.19). 357 Funkcii send i recv vypolnyayut peredachu dannyh cherez podklyuchennoe gnezdo. Sintaksis vyzova funkcii send: count = send(sd,msg,length,flags); gde sd - deskriptor gnezda, msg - ukazatel' na posylaemye dannye, length - razmer dannyh, count - kolichestvo fakticheski peredannyh bajt. Parametr flags mozhet soderzhat' znachenie SOF_OOB (poslat' dannye out-of-band - "cherez tamozh- nyu"), esli posylaemye dannye ne uchityvayutsya v obshchem informacionnom obmene mezhdu vzaimodejstvuyushchimi processami. Programma udalennoj registracii, napri- mer, mozhet poslat' out-of-band soobshchenie, imitiruyushchee nazhatie na klaviature terminala klavishi "delete". Sintaksis vyzova sistemnoj funkcii recv: count = recv(sd,buf,length,flags); gde buf - massiv dlya priema dannyh, length - ozhidaemyj ob容m dannyh, count - kolichestvo bajt, fakticheski peredannyh pol'zovatel'skoj programme. Flagi (flags) mogut byt' ustanovleny takim obrazom, chto postupivshee soobshchenie pos- le chteniya i analiza ego soderzhimogo ne budet udaleno iz ocheredi, ili nastro- eny na poluchenie dannyh out-of-band. V dejtagrammnyh versiyah ukazannyh funk- cij, sendto i recvfrom, v kachestve dopolnitel'nyh parametrov ukazyvayutsya ad- resa. Posle vypolneniya podklyucheniya k gnezdam potokovogo tipa processy mogut vmesto funkcij send i recv ispol'zovat' funkcii read i write. Takim obrazom, soglasovav tip protokola, servery mogli by porozhdat' processy, rabotayushchie tol'ko s funkciyami read i write, slovno imeyut delo s obychnymi fajlami. Funkciya shutdown zakryvaet gnezdovuyu svyaz': shutdown(sd,mode) gde mode ukazyvaet, kakoj iz storon (posylayushchej, prinimayushchej ili obeim vmes- te) otnyne zapreshcheno uchastie v processe peredachi dannyh. Funkciya soobshchaet ispol'zuemomu protokolu o zavershenii seansa setevogo vzaimodejstviya, ostav- lyaya, tem ne menee, deskriptory gnezd v neprikosnovennosti. Osvobozhdaetsya deskriptor gnezda tol'ko v rezul'tate vypolneniya funkcii close. Sistemnaya funkciya getsockname poluchaet imya gnezdovoj svyazi, ustanovlen- noj ranee s pomoshch'yu funkcii bind: getsockname(sd,name,length); Funkcii getsockopt i setsockopt poluchayut i ustanavlivayut znacheniya raz- lichnyh svyazannyh s gnezdom parametrov v sootvetstvii s tipom domena i proto- kola. Rassmotrim obsluzhivayushchuyu programmu, predstavlennuyu na Risunke 11.20. Process sozdaet v domene "UNIX system" gnezdo potokovogo tipa i prisvaivaet emu imya sockname. Zatem s pomoshch'yu funkcii listen ustanavlivaetsya dlina oche- redi postupayushchih soobshchenij i nachinaetsya cikl ozhidaniya postupleniya zaprosov. Funkciya accept priostanavlivaet svoe vypolnenie do teh por, poka protokolom ne budet zaregistrirovan zapros na podklyuchenie k gnezdu s oznachennym imenem; posle etogo funkciya zavershaetsya, vozvrashchaya postupivshemu zaprosu novyj desk- riptor gnezda. Process-server porozhdaet potomka, cherez kotorogo budet pod- derzhivat'sya svyaz' s processom-klientom; roditel' i potomok pri etom zakryva- yut svoi deskriptory, chtoby oni ne stanovilis' pomehoj dlya kommunikacionnogo traffika drugogo processa. Process-potomok vedet razgovor s klientom i za- vershaetsya posle vyhoda iz funkcii read. Process-server vozvrashcha- etsya k nachalu cikla i zhdet postupleniya sleduyushchego zaprosa na podklyuchenie. Na Risunke 11.21 pokazan primer processa-klienta, vedushchego obshchenie s serverom. Klient sozdaet gnezdo v tom zhe domene, chto i server, i posylaet zapros na podklyuchenie k gnezdu s imenem sockname. V rezul'tate podklyucheniya 358 +------------------------------------------------------------+ | #include | | #include | | | | main() | | { | | int sd,ns; | | char buf[256]; | | struct sockaddr sockaddr; | | int fromlen; | | | | sd = socket(AF_UNIX,SOCK_STREAM,0); | | | | /* imya gnezda - ne mozhet vklyuchat' pustoj simvol */ | | bind(sd,"sockname",sizeof("sockname") - 1); | | listen(sd,1); | | | | for (;;) | | { | | | | ns = accept(sd,&sockaddr,&fromlen); | | if (fork() == 0) | | { | | /* potomok */ | | close(sd); | | read(ns,buf,sizeof(buf)); | | printf("server chitaet '%s'\n",buf); | | exit(); | | } | | close(ns); | | } | | } | +------------------------------------------------------------+ Risunok 11.20. Process-server v domene "UNIX system" +------------------------------------------------------------+ | #include | | #include | | | | main() | | { | | int sd,ns; | | char buf[256]; | | struct sockaddr sockaddr; | | int fromlen; | | | | sd = socket(AF_UNIX,SOCK_STREAM,0); | | | | /* imya v zaprose na podklyuchenie ne mozhet vklyuchat' | | /* pustoj simvol */ | | if (connect(sd,"sockname",sizeof("sockname") - 1) == -1)| | exit(); | | | | write(sd,"hi guy",6); | | } | +------------------------------------------------------------+ Risunok 11.21. Process-klient v domene "UNIX system" 359 process-klient poluchaet virtual'nyj kanal svyazi s serverom. V rassmatrivae- mom primere klient peredaet odno soobshchenie i zavershaetsya. Esli server obsluzhivaet processy v seti, ukazanie o tom, chto gnezdo pri- nadlezhit domenu "Internet", mozhno sdelat' sleduyushchim obrazom: socket(AF_INET,SOCK_STREAM,0); i svyazat'sya s setevym adresom, poluchennym ot servera. V sisteme BSD imeyutsya bibliotechnye funkcii, vypolnyayushchie eti dejstviya. Vtoroj parametr vyzyvaemoj klientom funkcii connect soderzhit adresnuyu informaciyu, neobhodimuyu dlya iden- tifikacii mashiny v seti (ili adresa marshrutov posylki soobshchenij cherez prome- zhutochnye mashiny), a takzhe dopolnitel'nuyu informaciyu, identificiruyushchuyu priem- noe gnezdo mashiny-adresata. Esli serveru nuzhno odnovremenno sledit' za sos- toyaniem seti i vypolneniem lokal'nyh processov, on ispol'zuet dva gnezda i s pomoshch'yu funkcii select opredelyaet, s kakim klientom ustanavlivaetsya svyaz' v dannyj moment.

    11.5 VYVODY

My rassmotreli neskol'ko form vzaimodejstviya processov. Pervoj formoj, polozhivshej nachalo obsuzhdeniyu, yavilas' trassirovka processov - vzaimodejstvie dvuh processov, vystupayushchee v kachestve poleznogo sredstva otladki programm. Pri vseh svoih preimushchestvah trassirovka processov s pomoshch'yu funkcii ptrace vse zhe dostatochno dorogostoyashchee i primitivnoe meropriyatie, poskol'ku za odin seans funkciya sposobna peredat' strogo ogranichennyj ob容m dannyh, trebuetsya bol'shoe kolichestvo pereklyuchenij konteksta, vzaimodejstvie ogranichivaetsya tol'ko formoj otnoshenij roditel'-potomok, i nakonec, sama trassirovka proiz- voditsya tol'ko po oboyudnomu soglasiyu uchastvuyushchih v nej processov. V versii V sistemy UNIX imeetsya paket vzaimodejstviya processov (IPC), vklyuchayushchij v sebya mehanizmy obmena soobshcheniyami, raboty s semaforami i razdeleniya pamyati. K so- zhaleniyu, vse eti mehanizmy imeyut uzkospecial'noe naznachenie, ne imeyut horo- shej stykovki s drugimi elementami operacionnoj sistemy i ne dejstvuyut v se- ti. Tem ne menee, oni ispol'zuyutsya vo mnogih prilozheniyah i po sravneniyu s drugimi shemami otlichayutsya bolee vysokoj effektivnost'yu. Sistema UNIX podderzhivaet shirokij spektr vychislitel'nyh setej. Tradici- onnye metody soglasovaniya protokolov v sil'noj stepeni polagayutsya na pomoshch' sistemnoj funkcii ioctl, odnako v raznyh tipah setej oni realizuyutsya po-raz- nomu. V sisteme BSD imeyutsya sistemnye funkcii dlya raboty s gnezdami, podder- zhivayushchie bolee universal'nuyu strukturu setevogo vzaimodejstviya. V budushchem v versiyu V predpolagaetsya vklyuchit' opisannyj v glave 10 potokovyj mehanizm, povyshayushchij soglasovannost' raboty v seti.

    11.6 UPRAZHNENIYA

1. CHto proizojdet v tom sluchae, esli v programme debug budet otsutstvovat' vyzov funkcii wait (Risunok 11.3) ? (Namek: vozmozhny dva ishoda.) 2. S pomoshch'yu funkcii ptrace otladchik schityvaet dannye iz prostranstva trassiruemogo processa po odnomu slovu za odnu operaciyu. Kakie izmene- niya sleduet proizvesti v yadre operacionnoj sistemy dlya togo, chtoby uve- lichit' kolichestvo schityvaemyh slov ? Kakie izmeneniya pri etom neobhodi- mo sdelat' v samoj funkcii ptrace ? 3. Rasshir'te oblast' dejstviya funkcii ptrace tak, chtoby v kachestve para- metra pid mozhno bylo ukazyvat' identifikator processa, ne yavlyayushchegosya potomkom tekushchego processa. Podumajte nad voprosami, svyazannymi s zashchi- toj informacii: Pri kakih obstoyatel'stvah processu mozhet byt' pozvoleno 360 chitat' dannye iz adresnogo prostranstva drugogo, proizvol'nogo processa ? Pri kakih obstoyatel'stvah razreshaetsya vesti zapis' v adresnoe prost- ranstvo drugogo processa ? 4. Organizujte iz funkcij raboty s soobshcheniyami biblioteku pol'zovatel'sko- go urovnya s ispol'zovaniem obychnyh fajlov, poimenovannyh kanalov i ele- mentov blokirovki. Sozdavaya ochered' soobshchenij, otkrojte upravlyayushchij fajl dlya zapisi v nego informacii o sostoyanii ocheredi; zashchitite fajl s pomoshch'yu sredstv zahvata fajlov i drugih udobnyh dlya vas mehanizmov. Po- sylaya soobshchenie dannogo tipa, sozdavajte poimenovannyj kanal dlya vseh soobshchenij etogo tipa, esli takogo kanala eshche ne bylo, i peredavajte so- obshchenie cherez nego (s podschetom peredannyh bajt). Upravlyayushchij fajl dol- zhen sootnosit' tip soobshcheniya s imenem poimenovannogo kanala. Pri chtenii soobshchenij upravlyayushchij fajl napravlyaet process k sootvetstvuyushchemu poime- novannomu kanalu. Sravnite etu shemu s mehanizmom, opisannym v nastoya- shchej glave, po effektivnosti, slozhnosti realizacii i funkcional'nym voz- mozhnostyam. 5. Kakie dejstviya pytaetsya vypolnit' programma, predstavlennaya na Risunke 11.22 ? *6. Napishite programmu, kotoraya podklyuchala by oblast' razdelyaemoj pamyati slishkom blizko k vershine steka zadachi i pozvolyala by steku pri uveliche- nii peresekat' granicu razdelyaemoj oblasti. V kakoj moment proizojdet fatal'naya oshibka pamyati ? 7. Ispol'zujte v programme, predstavlennoj na Risunke 11.14, flag IPC_NOWAIT, realizuya uslovnyj tip semafora. Prodemonstrirujte, kak za schet etogo mozhno izbezhat' vozniknoveniya vzaimnyh blokirovok. 8. Pokazhite, kak operacii nad semaforami tipa P i V realizuyutsya pri rabote s poimenovannymi kanalami. Kak by vy realizovali operaciyu P uslovnogo tipa ? 9. Sostav'te programmy zahvata resursov, ispol'zuyushchie (a) poimenovannye kanaly, (b) sistemnye funkcii creat i unlink, (v) funkcii obmena soob- shcheniyami. Provedite sravnitel'nyj analiz ih effektivnosti. 10. Na prakticheskih primerah raboty s poimenovannymi kanalami sravnite ef- fektivnost' ispol'zovaniya funkcij obmena soobshcheniyami, s odnoj storony, s funkciyami read i write, s drugoj. 11. Sravnite na konkretnyh programmah skorost' peredachi dannyh pri rabote s razdelyaemoj pamyat'yu i pri ispol'zovanii mehanizma obmena soobshcheniyami. Programmy, ispol'zuyushchie razdelyaemuyu pamyat', dlya sinhronizacii zavershe- niya operacij chteniya-zapisi dolzhny opirat'sya na semafory. +------------------------------------------------------------+ | #include | | #include | | #include | | #define ALLTYPES 0 | | | | main() | | { | | struct msgform | | { | | long mtype; | | char mtext[1024]; | | } msg; | | register unsigned int id; | | | | for (id = 0; ; id++) | | while (msgrcv(id,&msg,1024,ALLTYPES,IPC_NOWAIT) > 0)| | ; | | } | +------------------------------------------------------------+ 361

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