| | 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®em 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®em oblasti razdelyaemoj pamyati); on zhdet momenta, kogda pervyj process zapishet v pervoe prinadlezhashchee oblasti slovo lyuboe otlichnoe ot nulya znachenie, i zatem prinimaetsya schityvat' dannye iz oblasti. Pervyj process delaet "pauzu" (pause), predostavlyaya vtoromu processu vozmozhnost' vypolne- niya; kogda pervyj process prinimaet signal, on udalyaet oblast' razdelyaemoj pamyati iz sistemy. Process zaprashivaet informaciyu o sostoyanii oblasti razdelyaemoj pamyati i proizvodit ustanovku parametrov dlya nee s pomoshch'yu sistemnoj funkcii shmctl: shmctl(id,cmd,shmstatbuf); Znachenie id identificiruet zapis' tablicy razdelyaemoj pamyati, cmd opredelyaet tip operacii, a shmstatbuf yavlyaetsya adresom pol'zovatel'skoj struktury, v kotoruyu pomeshchaetsya informaciya o sostoyanii oblasti. YAdro traktuet tip opera- cii tochno tak zhe, kak i pri upravlenii soobshcheniyami. Udalyaya oblast' razdelyae- moj pamyati, yadro osvobozhdaet sootvetstvuyushchuyu ej zapis' v tablice razdelyaemoj pamyati i prosmatrivaet tablicu oblastej: esli oblast' ne byla prisoedinena ni k odnomu iz processov, yadro osvobozhdaet zapis' tablicy i vse vydelennye oblasti resursy, ispol'zuya dlya etogo algoritm freereg (razdel 6.5.6). Esli zhe oblast' po-prezhnemu podklyuchena k kakim-to processam (znachenie schetchika ssylok na nee bol'she 0), yadro tol'ko sbrasyvaet flag, govoryashchij o tom, chto po zavershenii poslednego svyazannogo s neyu processa oblast' ne dolzhna osvo- bozhdat'sya. Processy, uzhe ispol'zuyushchie oblast' razdelyaemoj pamyati, prodolzhayut rabotat' s nej, novye zhe processy ne mogut prisoedinit' ee. Kogda vse pro- cessy otklyuchat oblast', yadro osvobodit ee. |to pohozhe na to, kak v fajlovoj sisteme posle razryva svyazi s fajlom process mozhet vnov' otkryt' ego i pro- dolzhat' s nim rabotu. 11.2.3 Semafory Sistemnye funkcii raboty s semaforami obespechivayut sinhronizaciyu vypol- neniya parallel'nyh processov, proizvodya nabor dejstvij edinstvenno nad grup- poj semaforov (sredstvami nizkogo urovnya). Do ispol'zovaniya semaforov, esli processu nuzhno bylo zablokirovat' nekij resurs, on pribegal k sozdaniyu s po- moshch'yu sistemnoj funkcii creat special'nogo blokiruyushchego fajla. Esli fajl uzhe sushchestvoval, funkciya creat zavershalas' neudachno, i process delal vyvod o tom, chto resurs uzhe zablokirovan drugim processom. Glavnye nedostatki takogo podhoda zaklyuchalis' v tom, chto process ne znal, v kakoj moment emu sleduet predprinyat' sleduyushchuyu popytku, a takzhe v tom, chto blokiruyushchie fajly sluchajno ostavalis' v sisteme v sluchae ee avarijnogo zaversheniya ili perezagruzki. Dijkstroj byl opublikovan algoritm Dekkera, opisyvayushchij realizaciyu sema- forov kak celochislennyh ob®ektov, 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 fun