GLAVA 11. VZAIMODEJSTVIE PROCESSOV
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.
11.1 TRASSIROVKA PROCESSOV
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.
11.2 VZAIMODEJSTVIE PROCESSOV V VERSII V SISTEMY
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.
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.
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.
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.
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