apusku ta- | 4 +----------------------->| 3 | v pamyati nov-| | | | len +---+---+ ++------+ v pa- | | ^ ^ myati | | | | Dostatochno | | | | pamyati | | | +---+ | Vy- Vy- | | | | gruzka gruzka | | | Sozdan | | |Za- ++------+ | | |gruz-| | fork | | |ka | 8 |<----- | | | | | | | | ++------+ | | | | | | | | Nedosta- | | | +---+ tochno | | | | pamyati | | | | (tol'ko sistema | | | | podkachki) v v | v +-------+ +---+---+ | | Vozobnovlenie | | | 6 +----------------------->| 5 | | | | | +-------+ +-------+ Priostanovlen, Gotov k zapusku, vygruzhen vygruzhen Risunok 7.6. Diagramma perehodov processa iz sostoyanie v sostoyanie s ukazaniem momentov proverki i obrabotki signalov 189 poluchil li process signal ili net. Usloviya, v kotoryh formiruyutsya signaly tipa "gibel' potomka", budut rassmotreny pozzhe. My takzhe uvidim, chto process mozhet ignorirovat' otdel'nye signaly, esli vospol'zuetsya funkciej signal. V algoritme issig yadro prosto gasit indikaciyu teh signalov, na kotorye process ne zhelaet obrashchat' vnimanie, i privlekaet vnimanie processa ko vsem ostal'- nym signalam. +------------------------------------------------------------+ | algoritm issig /* proverka polucheniya signalov */ | | vhodnaya informaciya: otsutstvuet | | vyhodnaya informaciya: "istina", esli process poluchil signa- | | ly, kotorye ego interesuyut | | "lozh'" - v protivnom sluchae | | { | | vypolnit' poka (pole v zapisi tablicy processov, soder- | | zhashchee indikaciyu o poluchenii signala, hranit nenulevoe | | znachenie) | | { | | najti nomer signala, poslannogo processu; | | esli (signal tipa "gibel' potomka") | | { | | esli (signaly dannogo tipa ignoriruyutsya) | | osvobodit' zapisi tablicy processov, kotorye | | sootvetstvuyut potomkam, prekrativshim sushchestvo-| | vanie; | | v protivnom sluchae esli (signaly dannogo tipa pri-| | nimayutsya) | | vozvratit' (istinu); | | } | | v protivnom sluchae esli (signal ne ignoriruetsya) | | vozvratit' (istinu); | | sbrosit' (pogasit') signal'nyj razryad, ustanovlennyj | | v sootvetstvuyushchem pole tablicy processov, hranyashchem | | indikaciyu polucheniya signala; | | } | | vozvratit' (lozh'); | | } | +------------------------------------------------------------+ Risunok 7.7. Algoritm opoznaniya signalov 7.2.1 Obrabotka signalov YAdro obrabatyvaet signaly v kontekste togo processa, kotoryj poluchaet ih, poetomu chtoby obrabotat' signaly, nuzhno zapustit' process. Sushchestvuet tri sposoba obrabotki signalov: process zavershaetsya po poluchenii signala, ne obrashchaet vnimanie na signal ili vypolnyaet osobuyu (pol'zovatel'skuyu) funkciyu po ego poluchenii. Reakciej po umolchaniyu so storony processa, ispolnyaemogo v rezhime yadra, yavlyaetsya vyzov funkcii exit, odnako s pomoshch'yu funkcii signal process mozhet ukazat' drugie special'nye dejstviya, prinimaemye po poluchenii teh ili inyh signalov. Sintaksis vyzova sistemnoj funkcii signal: oldfunction = signal(signum,function); gde signum - nomer signala, pri poluchenii kotorogo budet vypolneno dejstvie, svyazannoe s zapuskom pol'zovatel'skoj funkcii, function - adres funkcii, oldfunction - vozvrashchaemoe funkciej znachenie. Vmesto adresa funkcii process mozhet peredavat' vyzyvaemoj procedure signal chisla 1 i 0: esli function = 1, process budet ignorirovat' vse posleduyushchie postupleniya signala s nomerom 190 signum (osobyj sluchaj, svyazannyj s ignorirovaniem signala "gibel' potomka", rassmatrivaetsya v razdele 7.4), esli = 0 (znachenie po umolchaniyu), process po poluchenii signala v rezhime yadra zavershaetsya. V prostranstve processa podder- zhivaetsya massiv polej dlya obrabotki signalov, po odnomu polyu na kazhdyj opre- delennyj v sisteme signal. V pole, sootvetstvuyushchem signalu s ukazannym nome- rom, yadro sohranyaet adres pol'zovatel'skoj funkcii, vyzyvaemoj po poluchenii signala processom. Sposob obrabotki signalov odnogo tipa ne vliyaet na obra- botku signalov drugih tipov. +------------------------------------------------------------+ | algoritm psig /* obrabotka signalov posle proverki ih | | sushchestvovaniya */ | | vhodnaya informaciya: otsutstvuet | | vyhodnaya informaciya: otsutstvuet | | { | | vybrat' nomer signala iz zapisi tablicy processov; | | ochistit' pole s nomerom signala; | | esli (pol'zovatel' ranee vyzyval funkciyu signal, s po- | | moshch'yu kotoroj sdelal ukazanie ignorirovat' signal dan- | | nogo tipa) | | vozvratit' upravlenie; | | esli (pol'zovatel' ukazal funkciyu, kotoruyu nuzhno vypol- | | nit' po poluchenii signala) | | { | | iz prostranstva processa vybrat' pol'zovatel'skij | | virtual'nyj adres funkcii obrabotki signala; | | /* sleduyushchij operator imeet nezhelatel'nye pobochnye | | effekty */ | | ochistit' pole v prostranstve processa, soderzhashchee | | adres funkcii obrabotki signala; | | vnesti izmeneniya v pol'zovatel'skij kontekst: | | iskusstvenno sozdat' v steke zadachi zapis', imi- | | tiruyushchuyu obrashchenie k funkcii obrabotki signala; | | vnesti izmeneniya v sistemnyj kontekst: | | zapisat' adres funkcii obrabotki signala v pole | | schetchika komand, prinadlezhashchee sohranennomu re- | | gistrovomu kontekstu zadachi; | | vozvratit' upravlenie; | | } | | esli (signal trebuet dampirovaniya obraza processa v pa- | | myati) | | { | | sozdat' v tekushchem kataloge fajl s imenem "core"; | | perepisat' v fajl "core" soderzhimoe pol'zovatel'sko-| | go konteksta; | | } | | nemedlenno zapustit' algoritm exit; | | } | +------------------------------------------------------------+ Risunok 7.8. Algoritm obrabotki signalov Obrabatyvaya signal (Risunok 7.8), yadro opredelyaet tip signala i ochishchaet (gasit) razryad v zapisi tablicy processov, sootvetstvuyushchij dannomu tipu sig- nala i ustanovlennyj v moment polucheniya signala processom. Esli funkcii ob- rabotki signala prisvoeno znachenie po umolchaniyu, yadro v otdel'nyh sluchayah pered zaversheniem processa sbrasyvaet na vneshnij nositel' (dampiruet) obraz processa v pamyati (sm. uprazhnenie 7.7). Dampirovanie udobno dlya programmis- 191 tov tem, chto pozvolyaet ustanovit' prichinu zaversheniya processa i posredstvom etogo vesti otladku programm. YAdro dampiruet sostoyanie pamyati pri postuple- nii signalov, kotorye soobshchayut o kakih-nibud' oshibkah v vypolnenii proces- sov, kak naprimer, popytka ispolneniya zapreshchennoj komandy ili obrashchenie k adresu, nahodyashchemusya za predelami virtual'nogo adresnogo prostranstva pro- cessa. YAdro ne dampiruet sostoyanie pamyati, esli signal ne svyazan s programm- noj oshibkoj. Naprimer, preryvanie, vyzvannoe nazhatiem klavish "delete" ili "break" na terminale, imeet svoim rezul'tatom posylku signala, kotoryj soob- shchaet o tom, chto pol'zovatel' hochet ran'she vremeni zavershit' process, v to vremya kak signal o "zavisanii" yavlyaetsya svidetel'stvom narusheniya svyazi s re- gistracionnym terminalom. |ti signaly ne svyazany s oshibkami v protekanii processa. Signal o vyhode (quit), odnako, vyzyvaet sbros sostoyaniya pamyati, nesmotrya na to, chto on voznikaet za predelami vypolnyaemogo processa. |tot signal, obychno vyzyvaemyj odnovremennym nazhatiem klavish , daet prog- rammistu vozmozhnost' poluchat' damp sostoyaniya pamyati v lyuboj moment posle za- puska processa, chto byvaet neobhodimo, esli process popadaet v beskonechnyj cikl vypolneniya odnih i teh zhe komand (zaciklivaetsya). Esli process poluchaet signal, na kotoryj bylo resheno ne obrashchat' vnima- nie, vypolnenie processa prodolzhaetsya tak, slovno signala i ne bylo. Pos- kol'ku yadro ne sbrasyvaet znachenie sootvetstvuyushchego polya, svidetel'stvuyushchego o neobhodimosti ignorirovaniya signala dannogo tipa, to kogda signal postupit vnov', process opyat' ne obratit na nego vnimanie. Esli process poluchaet sig- nal, reagirovanie na kotoryj bylo priznano neobhodimym, srazu po vozvrashchenii processa v rezhim zadachi vypolnyaetsya zaranee uslovlennoe dejstvie, odnako prezhde chem perevesti process v rezhim zadachi, yadro eshche dolzhno predprinyat' sleduyushchie shagi: 1. YAdro obrashchaetsya k sohranennomu registrovomu kontekstu zadachi i vybiraet znacheniya schetchika komand i ukazatelya vershiny steka, kotorye budut vozv- rashcheny pol'zovatel'skomu processu. 2. Sbrasyvaet v prostranstve processa prezhnee znachenie polya funkcii obra- botki signala i prisvaivaet emu znachenie po umolchaniyu. 3. Sozdaet novuyu zapis' v steke zadachi, v kotoruyu, pri neobhodimosti vyde- lyaya dopolnitel'nuyu pamyat', perepisyvaet znacheniya schetchika komand i uka- zatelya vershiny steka, vybrannye ranee iz sohranennogo registrovogo kon- teksta zadachi. Stek zadachi budet vyglyadet' tak, kak budto process proiz- vel obrashchenie k pol'zovatel'skoj funkcii (obrabotki signala) v toj toch- ke, gde on vyzyval sistemnuyu funkciyu ili gde yadro prervalo ego vypolne- nie (pered opoznaniem signala). 4. Vnosit izmeneniya v sohranennyj registrovyj kontekst zadachi: ustanavliva- et znachenie schetchika komand ravnym adresu funkcii obrabotki signala, a znachenie ukazatelya vershiny steka ravnym glubine steka zadachi. Takim obrazom, po vozvrashchenii iz rezhima yadra v rezhim zadachi process pristupit k vypolneniyu funkcii obrabotki signala; posle ee zaversheniya uprav- lenie budet peredano na to mesto v programme pol'zovatelya, gde bylo proizve- deno obrashchenie k sistemnoj funkcii ili proizoshlo preryvanie, tem samym kak by imitiruetsya vyhod iz sistemnoj funkcii ili preryvaniya. V kachestve primera mozhno privesti programmu (Risunok 7.9), kotoraya pri- nimaet signaly o preryvanii (SIGINT) i sama posylaet ih (v rezul'tate vypol- neniya funkcii kill). Na Risunke 7.10 predstavleny fragmenty programmnogo ko- da, poluchennye v rezul'tate disassemblirovaniya zagruzochnogo modulya v opera- cionnoj srede VAX 11/780. Pri vypolnenii processa obrashchenie k bibliotechnoj procedure kill imeet adres (shestnadcatirichnyj) ee; eta procedura v svoyu oche- red', prezhde chem vyzvat' sistemnuyu funkciyu kill, ispolnyaet komandu chmk (pe- revesti process v rezhim yadra) po adresu 10a. Adres vozvrata iz sistemnoj funkcii - 10c. Vo vremya ispolneniya sistemnoj funkcii yadro posylaet processu signal o preryvanii. YAdro obrashchaet vnimanie na etot signal togda, kogda pro- cess sobiraetsya vernut'sya v rezhim zadachi, vybiraya iz sohranennogo registro- vogo konteksta adres vozvrata 10c i pomeshchaya ego v stek zadachi. Pri etom ad- 192 res funkcii obrabotki signala, 104, yadro pomeshchaet v sohranennyj registrovyj kontekst zadachi. Na Risunke 7.11 pokazany razlichnye sostoyaniya steka zadachi i sohranennogo registrovogo konteksta. V rassmotrennom algoritme obrabotki signalov imeyutsya nekotorye nesoot- vetstviya. Pervoe iz nih i naibolee vazhnoe svyazano s ochistkoj pered vozvrashche- niem processa v rezhim zadachi togo polya v prostranstve processa, kotoroe so- derzhit adres pol'zovatel'skoj funkcii obrabotki signala. Esli processu snova ponadobitsya obrabotat' signal, emu opyat' pridetsya pribegnut' k pomoshchi sis- temnoj funkcii signal. Pri etom mogut vozniknut' nezhelatel'nye posleds- +-------------------------------------------+ | #include | | main() | | { | | extern catcher(); | | signal(SIGINT,catcher); | | kill(0,SIGINT); | | } | | | | catcher() | | { | | } | +-------------------------------------------+ Risunok 7.9. Ishodnyj tekst programmy priema signalov +--------------------------------------------------------+ | **** VAX DISASSEMBLER **** | | | | _main() | | e4: | | e6: pushab Ox18(pc) | | ec: pushl $Ox2 | | # v sleduyushchej stroke vyzyvaetsya funkciya signal | | ee: calls $Ox2,Ox23(pc) | | f5: pushl $Ox2 | | f7: clrl -(sp) | | # v sleduyushchej stroke vyzyvaetsya bibliotechnaya procedu-| | ra kill | | f9: calls $Ox2,Ox8(pc) | | 100: ret | | 101: halt | | 102: halt | | 103: halt | | _catcher() | | 104: | | 106: ret | | 107: halt | | _kill() | | 108: | | # v sleduyushchej stroke vyzyvaetsya vnutrennee preryvanie| | operacionnoj sistemy | | 10a: chmk $Ox25 | | 10c: bgequ Ox6 | | 10e: jmp Ox14(pc) | | 114: clrl r0 | | 116: ret | +--------------------------------------------------------+ Risunok 7.10. Rezul'tat disassemblirovaniya programmy priema signalov 193 Do Posle | | | | | | +-->+--------------------+ | | Vershina | | Novaya zapis' s vy- | | | +-- steka --+ | zovom funkcii | | | | zadachi | | | | | ---->|Adres vozvrata (10c)| +--------------------+<--+ - +--------------------+ | Stek zadachi | - | Stek zadachi | | do | - | do | | polucheniya signala | - | polucheniya signala | +--------------------+ - +--------------------+ Stek zadachi - Stek zadachi - +--------------------+ - +--------------------+ | Adres vozvrata | - | Adres vozvrata | | v processe (10c) -|---------------- | v processe (104) | +--------------------+ +--------------------+ | Sohranennyj regist-| | Sohranennyj regist-| | rovyj kontekst za- | | rovyj kontekst za- | | dachi | | dachi | +--------------------+ +--------------------+ Sistemnyj kontekstnyj Sistemnyj kontekstnyj uroven' 1 uroven' 1 Oblast' sohraneniya Oblast' sohraneniya registrov registrov Risunok 7.11. Stek zadachi i oblast' sohraneniya struktur yadra do i posle polucheniya signala tviya: naprimer, mogut sozdast'sya usloviya dlya konkurencii, esli vtoroj raz signal postupit do togo, kak process poluchit vozmozhnost' zapustit' sistemnuyu funkciyu. Poskol'ku process vypolnyaetsya v rezhime zadachi, yadru sledovalo by proizvesti pereklyuchenie konteksta, chtoby uvelichit' tem samym shansy processa na poluchenie signala do momenta sbrosa znacheniya polya funkcii obrabotki sig- nala. |tu situaciyu mozhno razobrat' na primere programmy, predstavlennoj na Ri- sunke 7.12. Process obrashchaetsya k sistemnoj funkcii signal dlya togo, chtoby dat' ukazanie prinimat' signaly o preryvaniyah i ispolnyat' po ih poluchenii funkciyu sigcatcher. Zatem on porozhdaet novyj process, zapuskaet sistemnuyu funkciyu nice, pozvolyayushchuyu sdelat' prioritet zapuska processa-roditelya nizhe prioriteta ego potomka (sm. glavu 8), i vhodit v beskonechnyj cikl. Porozhden- nyj process zaderzhivaet svoe vypolnenie na 5 sekund, chtoby dat' roditel'sko- mu processu vremya ispolnit' sistemnuyu funkciyu nice i snizit' svoj prioritet. Posle etogo porozhdennyj process vhodit v cikl, v kazhdoj iteracii kotorogo on posylaet roditel'skomu processu signal o preryvanii (posredstvom obrashcheniya k funkcii kill). Esli v rezul'tate oshibki, naprimer, iz-za togo, chto roditel'- skij process bol'she ne sushchestvuet, kill zavershaetsya, to zavershaetsya i porozh- dennyj process. Vsya ideya sostoit v tom, chto roditel'skomu processu sleduet zapuskat' funkciyu obrabotki signala pri kazhdom poluchenii signala o preryva- nii. Funkciya obrabotki signala vyvodit soobshchenie i snova obrashchaetsya k funk- cii signal pri ocherednom poyavlenii signala o preryvanii, roditel'skij zhe process prodolzhaet 194 +------------------------------------------------------------+ | #include | | sigcatcher() | | { | | printf("PID %d prinyal signal\n",getpid()); /* pechat' | | PID */ | | signal(SIGINT,sigcatcher); | | } | | | | main() | | { | | int ppid; | | | | signal(SIGINT,sigcatcher); | | | | if (fork() == 0) | | { | | /* dat' processam vremya dlya vypolneniya ustanovok */ | | sleep(5); /* bibliotechnaya funkciya priostanova na| | 5 sekund */ | | ppid = getppid(); /* poluchit' identifikator rodite- | | lya */ | | for (;;) | | if (kill(ppid,SIGINT) == -1) | | exit(); | | } | | | | /* chem nizhe prioritet, tem vyshe shansy vozniknoveniya kon-| | kurencii */ | | nice(10); | | for (;;) | | ; | | } | +------------------------------------------------------------+ Risunok 7.12. Programma, demonstriruyushchaya vozniknovenie sopernichestva mezhdu processami v hode obrabotki signalov ispolnyat' ciklicheskij nabor komand. Odnako, vozmozhna i sleduyushchaya ocherednost' nastupleniya sobytij: 1. Porozhdennyj process posylaet roditel'skomu processu signal o preryvanii. 2. Roditel'skij process prinimaet signal i vyzyvaet funkciyu obrabotki sig- nala, no rezerviruetsya yadrom, kotoroe proizvodit pereklyuchenie konteksta do togo, kak funkciya signal budet vyzvana povtorno. 3. Snova zapuskaetsya porozhdennyj process, kotoryj posylaet roditel'skomu processu eshche odin signal o preryvanii. 4. Roditel'skij process poluchaet vtoroj signal o preryvanii, no pered tem on ne uspel sdelat' nikakih rasporyazhenij otnositel'no sposoba obrabotki signala. Kogda vypolnenie roditel'skogo processa budet vozobnovleno, on zavershitsya. V programme opisyvaetsya imenno takoe povedenie processov, poskol'ku vy- zov roditel'skim processom funkcii nice privodit k tomu, chto yadro budet chashche zapuskat' na vypolnenie porozhdennyj process. Po slovam Richi (eti svedeniya byli polucheny v chastnoj besede), signaly byli zadumany kak sobytiya, kotorye mogut byt' kak fatal'nymi, tak i prohodya- shchimi nezametno, kotorye ne vsegda obrabatyvayutsya, poetomu v rannih versiyah sistemy konkurenciya processov, svyazannaya s posylkoj signalov, ne fiksirova- las'. Tem ne menee, ona predstavlyaet ser'eznuyu problemu v teh programmah, gde osushchestvlyaetsya priem signalov. |ta problema byla by ustranena, esli by 195 pole opisaniya signala ne ochishchalos' po ego poluchenii. Odnako, takoe reshenie porodilo by novuyu problemu: esli postupayushchij signal prinimaetsya, a pole ochi- shcheno, vlozhennye obrashcheniya k funkcii obrabotki signala mogut perepolnit' stek. S drugoj storony, yadro moglo by sbrosit' znachenie funkcii obrabotki signala, tem samym delaya rasporyazhenie ignorirovat' signaly dannogo tipa do teh por, poka pol'zovatel' vnov' ne ukazhet, chto nuzhno delat' po poluchenii podobnyh signalov. Takoe reshenie predpolagaet poteryu informacii, tak kak process ne v sostoyanii uznat', skol'ko signalov im bylo polucheno. Odnako, informacii pri etom teryaetsya ne bol'she, chem v tom sluchae, kogda process po- luchaet bol'shoe kolichestvo signalov odnogo tipa do togo, kak poluchaet vozmozh- nost' ih obrabotat'. V sisteme BSD, nakonec, process imeet vozmozhnost' blo- kirovat' poluchenie signalov i snimat' blokirovku pri novom obrashchenii k sis- temnoj funkcii; kogda process snimaet blokirovku signalov, yadro posylaet processu vse signaly, otlozhennye (povisshie) s momenta ustanovki blokirovki. Kogda process poluchaet signal, yadro avtomaticheski blokiruet poluchenie sledu- yushchego signala do teh por, poka funkciya obrabotki signala ne zakonchit rabotu. V etih dejstviyah yadra nablyudaetsya analogiya s tem, kak yadro reagiruet na ap- paratnye preryvaniya: ono blokiruet poyavlenie novyh preryvanij na vremya obra- botki predydushchih. Vtoroe nesootvetstvie v obrabotke signalov svyazano s priemom signalov, postupayushchih vo vremya ispolneniya sistemnoj funkcii, kogda process priostanov- len s dopuskayushchim preryvaniya prioritetom. Signal pobuzhdaet process vyjti iz priostanova (s pomoshch'yu longjump), vernut'sya v rezhim zadachi i vyzvat' funkciyu obrabotki signala. Kogda funkciya obrabotki signala zavershaet rabotu, prois- hodit to, chto process vyhodit iz sistemnoj funkcii s oshibkoj, soobshchayushchej o preryvanii ee vypolneniya. Uznav ob oshibke, pol'zovatel' zapuskaet sistemnuyu funkciyu povtorno, odnako bolee udobno bylo by, esli by eto dejstvie avtoma- ticheski vypolnyalos' yadrom, kak v sisteme BSD. Tret'e nesootvetstvie proyavlyaetsya v tom sluchae, kogda process ignoriruet postupivshij signal. Esli signal postupaet v to vremya, kogda process nahodit- sya v sostoyanii priostanova s dopuskayushchim preryvaniya prioritetom, process vo- zobnovlyaetsya, no ne vypolnyaet longjump. Drugimi slovami, yadro uznaet o tom, chto process proignoriroval postupivshij signal tol'ko posle vozobnovleniya ego vypolneniya. Logichnee bylo by ostavit' process v sostoyanii priostanova. Odna- ko, v moment posylki signala k prostranstvu processa, v kotorom yadro hranit adres funkcii obrabotki signala, mozhet otsutstvovat' dostup. |ta problema mozhet byt' reshena putem zapominaniya adresa funkcii obrabotki signala v zapi- si tablicy processov, obrashchayas' k kotoroj, yadro poluchalo by vozmozhnost' re- shat' vopros o neobhodimosti vozobnovleniya processa po poluchenii signala. S drugoj storony, process mozhet nemedlenno vernut'sya v sostoyanie priostanova (po algoritmu sleep), esli obnaruzhit, chto v ego vozobnovlenii ne bylo neob- hodimosti. Odnako, pol'zovatel'skie processy ne imeyut vozmozhnosti osoznavat' sobstvennoe vozobnovlenie, poskol'ku yadro raspolagaet tochku vhoda v algoritm sleep vnutri cikla s usloviem prodolzheniya (sm. glavu 2), perevodya process vnov' v sostoyanie priostanova, esli ozhidaemoe processom sobytie v dejstvi- tel'nosti ne imelo mesta. Ko vsemu skazannomu vyshe sleduet dobavit', chto yadro obrabatyvaet signaly tipa "gibel' potomka" ne tak, kak drugie signaly. V chastnosti, kogda process uznaet o poluchenii signala "gibel' potomka", on vyklyuchaet indikaciyu signala v sootvetstvuyushchem pole zapisi tablicy processov i po umolchaniyu dejstvuet tak, slovno nikakogo signala i ne postupalo. Naznachenie signala "gibel' po- tomka" sostoit v vozobnovlenii vypolneniya processa, priostanovlennogo s do- puskayushchim preryvaniya prioritetom. Esli process prinimaet takoj signal, on, kak i vo vseh ostal'nyh sluchayah, zapuskaet funkciyu obrabotki signala. Dejst- viya, predprinimaemye yadrom v tom sluchae, kogda process ignoriruet postupiv- shij signal etogo tipa, budut opisany v razdele 7.4. Nakonec, kogda process vyzval funkciyu signal s parametrom "gibel' potomka" (death of child), yadro posylaet emu sootvetstvuyushchij signal, esli on imeet potomkov, prekrativshih sushchestvovanie. V razdele 7.4 na etom momente my ostanovimsya bolee podrobno. 196 7.2.2 Gruppy processov Nesmotrya na to, chto v sisteme UNIX processy identificiruyutsya unikal'nym kodom (PID), sisteme inogda prihoditsya ispol'zovat' dlya identifikacii pro- cessov nomer "gruppy", v kotoruyu oni vhodyat. Naprimer, processy, imeyushchie ob- shchego predka v lice registracionnogo shell'a, vzaimosvyazany, i poetomu kogda pol'zovatel' nazhimaet klavishi "delete" ili "break", ili kogda terminal'naya liniya "zavisaet", vse eti processy poluchayut sootvetstvuyushchie signaly. YAdro ispol'zuet kod gruppy processov dlya identifikacii gruppy vzaimosvyazannyh processov, kotorye pri nastuplenii opredelennyh sobytij dolzhny poluchat' ob- shchij signal. Kod gruppy zapominaetsya v tablice processov; processy iz odnoj gruppy imeyut odin i tot zhe kod gruppy. Dlya togo, chtoby prisvoit' kodu gruppy processov nachal'noe znachenie, pri- ravnyav ego kodu identifikacii processa, sleduet vospol'zovat'sya sistemnoj funkciej setpgrp. Sintaksis vyzova funkcii: grp = setpgrp(); gde grp - novyj kod gruppy processov. Pri vypolnenii funkcii fork pro- cess-potomok nasleduet kod gruppy svoego roditelya. Ispol'zovanie funkcii setpgrp pri naznachenii dlya processa operatorskogo terminala imeet vazhnye osobennosti, na kotorye stoit obratit' vnimanie (sm. razdel 10.3.5). 7.2.3 Posylka signalov processami Dlya posylki signalov processy ispol'zuyut sistemnuyu funkciyu kill. Sintak- sis vyzova funkcii: kill(pid,signum) gde v pid ukazyvaetsya adresat posylaemogo signala (oblast' dejstviya signa- la), a v signum - nomer posylaemogo signala. Svyaz' mezhdu znacheniem pid i so- vokupnost'yu vypolnyayushchihsya processov sleduyushchaya: * Esli pid - polozhitel'noe celoe chislo, yadro posylaet signal processu s identifikatorom pid. * Esli znachenie pid ravno 0, signal posylaetsya vsem processam, vhodyashchim v odnu gruppu s processom, vyzvavshim funkciyu kill. * Esli znachenie pid ravno -1, signal posylaetsya vsem processam, u kotoryh real'nyj kod identifikacii pol'zovatelya sovpadaet s tem, pod kotorym is- polnyaetsya process, vyzvavshij funkciyu kill (ob etih kodah bolee podrobno sm. v razdele 7.6). Esli process, poslavshij signal, ispolnyaetsya pod ko- dom identifikacii superpol'zovatelya, signal rassylaetsya vsem processam, krome processov s identifikatorami 0 i 1. * Esli pid - otricatel'noe celoe chislo, no ne -1, signal posylaetsya vsem processam, vhodyashchim v gruppu s nomerom, ravnym absolyutnomu znacheniyu pid. Vo vseh sluchayah, esli process, poslavshij signal, ispolnyaetsya pod kodom identifikacii pol'zovatelya, ne yavlyayushchegosya superpol'zovatelem, ili esli kody identifikacii pol'zovatelya (real'nyj i ispolnitel'nyj) u etogo processa ne sovpadayut s sootvetstvuyushchimi kodami processa, prinimayushchego signal, kill za- vershaetsya neudachno. V programme, privedennoj na Risunke 7.13, glavnyj process sbrasyvaet us- tanovlennoe ranee znachenie nomera gruppy i porozhdaet 10 novyh processov. Pri rozhdenii kazhdyj process-potomok nasleduet nomer gruppy processov svoego ro- ditelya, odnako, processy, sozdannye v nechetnyh iteraciyah cikla, sbrasyvayut eto znachenie. Sistemnye funkcii getpid i getpgrp vozvrashchayut znacheniya koda identifikacii vypolnyaemogo processa i nomera gruppy, v kotoruyu on vhodit, a funkciya pause priostanavlivaet vypolnenie processa do momenta polucheniya sig- nala. V konechnom itoge roditel'skij process zapuskaet funkciyu kill i posyla- et signal o preryvanii vsem processam, vhodyashchim v odnu s nim gruppu. YAdro 197 +------------------------------------------------------------+ | #include | | main() | | { | | register int i; | | | | setpgrp(); | | for (i = 0; i < 10; i++) | | { | | if (fork() == 0) | | { | | /* porozhdennyj process */ | | if (i & 1) | | setpgrp(); | | printf("pid = %d pgrp = %d\n",getpid(),getpgrp());| | pause(); /* sistemnaya funkciya priostanova vy- | | polneniya */ | | } | | } | | kill(0,SIGINT); | | } | +------------------------------------------------------------+ Risunok 7.13. Primer ispol'zovaniya funkcii setpgrp posylaet signal pyati "chetnym" processam, ne sbrosivshim unasledovannoe znache- nie nomera gruppy, pri etom pyat' "nechetnyh" processov prodolzhayut svoe vypol- nenie. 7.3 ZAVERSHENIE VYPOLNENIYA PROCESSA V sisteme UNIX process zavershaet svoe vypolnenie, zapuskaya sistemnuyu funkciyu exit. Posle etogo process perehodit v sostoyanie "prekrashcheniya sushchest- vovaniya" (sm. Risunok 6.1), osvobozhdaet resursy i likvidiruet svoj kontekst. Sintaksis vyzova funkcii: exit(status); gde status - znachenie, vozvrashchaemoe funkciej roditel'skomu processu. Proces- sy mogut vyzyvat' funkciyu exit kak v yavnom, tak i v neyavnom vide (po okoncha- nii vypolneniya programmy: nachal'naya procedura (startup), komponuemaya so vse- mi programmami na yazyke Si, vyzyvaet funkciyu exit na vyhode programmy iz funkcii main, yavlyayushchejsya obshchej tochkoj vhoda dlya vseh programm). S drugoj storony, yadro mozhet vyzyvat' funkciyu exit po svoej iniciative, esli process ne prinyal poslannyj emu signal (ob etom my uzhe govorili vyshe). V etom sluchae znachenie parametra status ravno nomeru signala. Sistema ne nakladyvaet nikakogo ogranicheniya na prodolzhitel'nost' vypol- neniya processa, i zachastuyu processy sushchestvuyut v techenie dovol'no dlitel'no- go vremeni. Nulevoj process (programma podkachki) i process 1 (init), k pri- meru, sushchestvuyut na protyazhenii vsego vremeni zhizni sistemy. Prodolzhitel'nymi processami yavlyayutsya takzhe getty-processy, kontroliruyushchie rabotu terminal'noj linii, ozhidaya registracii pol'zovatelej, i processy obshchego naznacheniya, vy- polnyaemye pod rukovodstvom administratora. Na Risunke 7.14 priveden algoritm funkcii exit. Snachala yadro otmenyaet obrabotku vseh signalov, posylaemyh processu, poskol'ku ee prodolzhenie sta- novitsya bessmyslennym. Esli process, vyzyvayushchij funkciyu exit, vozglavlyaet 198 +------------------------------------------------------------+ | algoritm exit | | vhodnaya informaciya: kod, vozvrashchaemyj roditel'skomu pro- | | cessu | | vyhodnaya informaciya: otsutstvuet | | { | | ignorirovat' vse signaly; | | esli (process vozglavlyaet gruppu processov, associiro- | | vannuyu s operatorskim terminalom) | | { | | poslat' vsem processam, vhodyashchim v gruppu, signal o | | "zavisanii"; | | sbrosit' v nol' kod gruppy processov; | | } | | zakryt' vse otkrytye fajly (vnutrennyaya modifikaciya algo-| | ritma close); | | osvobodit' tekushchij katalog (algoritm iput); | | osvobodit' oblasti i pamyat', associirovannuyu s processom| | (algoritm freereg); | | sozdat' zapis' s uchetnoj informaciej; | | prekratit' sushchestvovanie processa (perevesti ego v soot-| | vetstvuyushchee sostoyanie); | | naznachit' vsem processam-potomkam v kachestve roditelya | | process init (1); | | esli kto-libo iz potomkov prekratil sushchestvovanie, | | poslat' processu init signal "gibel' potomka"; | | poslat' signal "gibel' potomka" roditelyu dannogo proces-| | sa; | | pereklyuchit' kontekst; | | } | +------------------------------------------------------------+ Risunok 7.14. Algoritm funkcii exit gruppu processov, associirovannuyu s operatorskim terminalom (sm. razdel 10.3.5), yadro delaet predpolozhenie o tom, chto pol'zovatel' prekrashchaet rabo- tu, i posylaet vsem processam v gruppe signal o "zavisanii". Takim obrazom, esli pol'zovatel' v registracionnom shell'e nazhmet posledovatel'nost' kla- vish, oznachayushchuyu "konec fajla" (Ctrl-d), pri etom s terminalom ostalis' svya- zannymi nekotorye iz sushchestvuyushchih processov, process, vypolnyayushchij funkciyu exit, poshlet im vsem signal o "zavisanii". Krome togo, yadro sbrasyvaet v nol' znachenie koda gruppy processov dlya vseh processov, vhodyashchih v dannuyu gruppu, poskol'ku ne isklyuchena vozmozhnost' togo, chto pozdnee tekushchij kod identifikacii processa (processa, kotoryj vyzval funkciyu exit) budet prisvo- en drugomu processu i togda poslednij vozglavit gruppu s ukazannym kodom. Processy, vhodivshie v staruyu gruppu, v novuyu gruppu vhodit' ne budut. Posle etogo yadro prosmatrivaet deskriptory otkrytyh fajlov, zakryvaet kazhdyj iz etih fajlov po algoritmu close i osvobozhdaet po algoritmu iput indeksy teku- shchego kataloga i kornya (esli on izmenyalsya). Nakonec, yadro osvobozhdaet vsyu vydelennuyu zadache pamyat' vmeste s sootvet- stvuyushchimi oblastyami (po algoritmu detachreg) i perevodit process v sostoyanie prekrashcheniya sushchestvovaniya. YAdro sohranyaet v tablice processov kod vozvrata funkcii exit (status), a takzhe summarnoe vremya ispolneniya processa i ego po- tomkov v rezhime yadra i rezhime zadachi. V razdele 7.4 pri rassmotrenii funkcii wait budet pokazano, kakim obrazom process poluchaet informaciyu o vremeni vy- polneniya svoih potomkov. YAdro takzhe sozdaet v global'nom uchetnom fajle za- pis', kotoraya soderzhit razlichnuyu statisticheskuyu informaciyu o vypolnenii pro- cessa, takuyu kak kod identifikacii pol'zovatelya, ispol'zovanie resursov cen- tral'nogo processora i pamyati, ob®em potokov vvoda-vyvoda, svyazannyh s pro- 199 cessom. Pol'zovatel'skie programmy mogut v lyuboj moment obratit'sya k uchetno- mu fajlu za statisticheskimi dannymi, predstavlyayushchimi interes s tochki zreniya slezheniya za funkcionirovaniem sistemy i organizacii raschetov s pol'zovatelya- mi. YAdro udalyaet process iz dereva processov, a ego potomkov peredaet pro- cessu 1 (init). Takim obrazom, process 1 stanovitsya zakonnym roditelem vseh prodolzhayushchih sushchestvovanie potomkov zavershayushchegosya processa. Esli kto-libo iz potomkov prekrashchaet sushchestvovanie, zavershayushchijsya process posylaet proces- su init signal "gibel' potomka" dlya togo, chtoby process nachal'noj zagruzki mog udalit' zapis' o potomke iz tablicy processov (sm. razdel 7.9); krome togo, zavershayushchijsya process posylaet etot signal svoemu roditelyu. V tipichnoj situacii roditel'skij process sinhroniziruet svoe vypolnenie s zavershayushchimsya potomkom s pomoshch'yu sistemnoj funkcii wait. Prekrashchaya sushchestvovanie, process pereklyuchaet kontekst i yadro mozhet teper' vybirat' dlya ispolneniya sleduyushchij process; yadro s etih por uzhe ne budet ispolnyat' process, prekrativshij sushches- tvov