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. 11.2.1 Soobshcheniya 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®em 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®em 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®em 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®em 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);