anie. V programme, privedennoj na Risunke 7.15, process sozdaet novyj process, kotoryj pechataet svoj kod identifikacii i vyzyvaet sistemnuyu funkciyu pause, priostanavlivayas' do polucheniya signala. Process-roditel' pechataet PID svoego potomka i zavershaetsya, vozvrashchaya tol'ko chto vyvedennoe znachenie cherez para- metr status. Esli by vyzov funkcii exit otsutstvoval, nachal'naya procedura sdelala by ego po vyhode processa iz funkcii main. Porozhdennyj process pro- dolzhaet ozhidat' polucheniya signala, dazhe esli ego roditel' uzhe zavershilsya. 7.4 OZHIDANIE ZAVERSHENIYA VYPOLNENIYA PROCESSA Process mozhet sinhronizirovat' prodolzhenie svoego vypolneniya s momentom zaversheniya potomka, esli vospol'zuetsya sistemnoj funkciej wait. Sintaksis vyzova funkcii: +------------------------------------------------------------+ | main() | | { | | int child; | | | | if ((child = fork()) == 0) | | { | | printf("PID potomka %d\n",getpid()); | | pause(); /* priostanov vypolneniya do polucheniya | | signala */ | | } | | /* roditel' */ | | printf("PID potomka %d\n",child); | | exit(child); | | } | +------------------------------------------------------------+ Risunok 7.15. Primer ispol'zovaniya funkcii exit pid = wait(stat_addr); gde pid - znachenie koda identifikacii (PID) prekrativshego svoe sushchestvovanie potomka, stat_addr - adres peremennoj celogo tipa, v kotoruyu budet pomeshcheno vozvrashchaemoe funkciej exit znachenie, v prostranstve zadachi. Algoritm funkcii wait priveden na Risunke 7.16. YAdro vedet poisk potom- kov processa, prekrativshih sushchestvovanie, i v sluchae ih otsutstviya vozvrashcha- et oshibku. Esli potomok, prekrativshij sushchestvovanie, obnaruzhen, yadro pereda- et ego kod identifikacii i znachenie, vozvrashchaemoe cherez parametr funkcii exit, processu, vyzvavshemu funkciyu wait. Takim obrazom, cherez parametr funk- 200 cii exit (status) zavershayushchijsya process mozhet peredavat' razlichnye znacheniya, v zakodirovannom vide soderzhashchie informaciyu o prichine zaversheniya processa, odnako na praktike etot parametr ispol'zuetsya po naznacheniyu dovol'no redko. YAdro peredaet v sootvetstvuyushchie polya, prinadlezhashchie prostranstvu roditel'- skogo processa, nakoplennye znacheniya prodolzhitel'nosti ispolneniya proces- sa-potomka v rezhime yadra i v rezhime zadachi i, nakonec, osvobozhdaet v tablice processov mesto, kotoroe v nej zanimal prezhde prekrativshij sushchestvovanie process. |to mesto budet predostavleno novomu processu. Esli process, vypolnyayushchij funkciyu wait, imeet potomkov, prodolzhayushchih su- shchestvovanie, on priostanavlivaetsya do polucheniya ozhidaemogo signala. YAdro ne vozobnovlyaet po svoej iniciative process, priostanovivshijsya s pomoshch'yu funk- cii wait: takoj process mozhet vozobnovit'sya tol'ko v sluchae polucheniya signa- la. Na vse signaly, krome signala "gibel' potomka", process reagiruet ranee rassmotrennym obrazom. Reakciya processa na signal "gibel' potomka" proyavlya- etsya po-raznomu v zavisimosti ot obstoyatel'stv: * Po umolchaniyu (to est' esli special'no ne ogovoreny nikakie drugie dejst- viya) process vyhodit iz sostoyaniya ostanova, v kotoroe on voshel s pomoshch'yu funkcii wait, i zapuskaet algoritm issig dlya opoznaniya tipa postupivshego signala. Algoritm issig (Risunok 7.7) rassmatrivaet osobyj sluchaj pos- tupleniya signala tipa "gibel' potomka" i vozvrashchaet "lozh'". Poetomu yadro ne vypolnyaet longjump iz funkcii sleep, a vozvrashchaet upravlenie funkcii wait. Ono perezapuskaet funkciyu wait, nahodit potomkov, prekrativshih su- shchestvovanie (po krajnej mere, odnogo), osvobozhdaet mesto v tablice pro- cessov, zanimaemoe etimi potomkami, i vyhodit iz funkcii wait, vozvrashchaya +------------------------------------------------------------+ | algoritm wait | | vhodnaya informaciya: adres peremennoj dlya hraneniya znacheniya| | status, vozvrashchaemogo zavershayushchimsya | | processom | | vyhodnaya informaciya: identifikator potomka i kod vozvrata | | funkcii exit | | { | | esli (process, vyzvavshij funkciyu wait, ne imeet potom- | | kov) | | vozvratit' (oshibku); | | | | dlya (;;) /* cikl s vnutrennim ciklom */ | | { | | esli (process, vyzvavshij funkciyu wait, imeet potom-| | kov, prekrativshih sushchestvovanie) | | { | | vybrat' proizvol'nogo potomka; | | peredat' ego roditelyu informaciyu ob ispol'zova-| | nii potomkom resursov central'nogo processora;| | osvobodit' v tablice processov mesto, zanimae- | | moe potomkom; | | vozvratit' (identifikator potomka, kod vozvrata| | funkcii exit, vyzvannoj potomkom); | | } | | esli (u processa net potomkov) | | vozvratit' oshibku; | | priostanovit'sya s prioritetom, dopuskayushchim preryva-| | niya (do zaversheniya potomka); | | } | | } | +------------------------------------------------------------+ Risunok 7.16. Algoritm funkcii wait 201 upravlenie processu, vyzvavshemu ee. * Esli processy prinimaet signaly dannogo tipa, yadro delaet vse neobhodi- mye ustanovki dlya zapuska pol'zovatel'skoj funkcii obrabotki signala, kak i v sluchae postupleniya signala lyubogo drugogo tipa. * Esli process ignoriruet signaly dannogo tipa, yadro perezapuskaet funkciyu wait, osvobozhdaet v tablice processov mesto, zanimaemoe potomkami, prek- rativshimi sushchestvovanie, i issleduet ostavshihsya potomkov. Naprimer, esli pol'zovatel' zapuskaet programmu, privedennuyu na Risunke 7.17, s parametrom i bez parametra, on poluchit raznye rezul'taty. Snachala rassmotrim sluchaj, kogda pol'zovatel' zapuskaet programmu bez parametra (edinstvennyj parametr - imya programmy, to est' argc ravno 1). Roditel'skij process porozhdaet 15 potomkov, kotorye v konechnom itoge zavershayut svoe vy- polnenie s kodom vozvrata i, nomerom processa v poryadke ocherednosti sozda- niya. YAdro, ispolnyaya funkciyu wait dlya roditelya, nahodit potomka, prekrativshe- go sushchestvovanie, i peredaet roditelyu ego identifikator i kod vozvrata funk- cii exit. Pri etom zaranee ne izvestno, kakoj iz potomkov budet obnaruzhen. Iz teksta programmy, realizuyushchej sistemnuyu funkciyu exit, napisannoj na yazyke Si i vklyuchennoj v biblioteku standartnyh podprogramm, vidno, chto programma zapominaet kod vozvrata funkcii exit v bitah 8-15 polya ret_code i vozvrashchaet funkcii wait identifikator processa-potomka. Takim obrazom, v ret_code hra- nitsya znachenie, ravnoe 256*i, gde i - nomer potomka, a v ret_val zanositsya znachenie identifikatora potomka. Esli pol'zovatel' zapuskaet programmu s parametrom (to est' argc > 1), roditel'skij process s pomoshch'yu funkcii signal delaet rasporyazhenie ignoriro- vat' signaly tipa "gibel' potomka". Predpolozhim, chto roditel'skij process, vypolnyaya funkciyu wait, priostanovilsya eshche do togo, kak ego potomok proizvel obrashchenie k funkcii exit: kogda process-potomok perehodit k vypolneniyu funk- cii exit, on posylaet svoemu roditelyu signal "gibel' potomka"; roditel'skij process vozobnovlyaetsya, poskol'ku on byl priostanovlen s prioritetom, dopus- kayushchim preryvaniya. Kogda tak ili inache roditel'skij process prodolzhit svoe +------------------------------------------------------------+ | #include | | main(argc,argv) | | int argc; | | char *argv[]; | | { | | int i,ret_val,ret_code; | | | | if (argc >= 1) | | signal(SIGCLD,SIG_IGN); /* ignorirovat' gibel' | | potomkov */ | | for (i = 0; i < 15; i++) | | if (fork() == 0) | | { | | /* process-potomok */ | | printf("process-potomok %x\n",getpid()); | | exit(i); | | } | | ret_val = wait(&ret_code); | | printf("wait ret_val %x ret_code %x\n",ret_val,ret_code);| | } | +------------------------------------------------------------+ Risunok 7.17. Primer ispol'zovaniya funkcii wait i ignorirova- niya signala "gibel' potomka" 202 vypolnenie, on obnaruzhit, chto signal soobshchal o "gibeli" potomka; odnako, poskol'ku on ignoriruet signaly etogo tipa i ne obrabatyvaet ih, yadro udalyaet iz tablicy processov zapis', sootvetstvuyushchuyu prekrativshemu sushchestvovanie potomku, i prodolzhaet vypolnenie funkcii wait tak, slovno signala i ne bylo. YAdro vypolnyaet eti dejstviya vsya- kij raz, kogda roditel'skij process poluchaet signal tipa "gibel' potomka", do teh por, poka cikl vypolneniya funkcii wait ne budet zavershen i poka ne budet ustanovleno, chto u processa bol'she potomkov net. Togda funkciya wait vozvrashchaet znachenie, ravnoe -1. Raznica mezhdu dvumya sposobami zapuska prog- rammy sostoit v tom, chto v pervom sluchae process-roditel' zhdet zaversheniya lyubogo iz potomkov, v to vremya kak vo vtorom sluchae on zhdet, poka zavershatsya vse ego potomki. V rannih versiyah sistemy UNIX funkcii exit i wait ne ispol'zovali i ne rassmatrivali signal tipa "gibel' potomka". Vmesto posylki signala funkciya exit vozobnovlyala vypolnenie roditel'skogo processa. Esli roditel'skij pro- cess pri vypolnenii funkcii wait priostanovilsya, on vozobnovlyaetsya, nahodit potomka, prekrativshego sushchestvovanie, i vozvrashchaet upravlenie. V protivnom sluchae vozobnovleniya ne proishodit; process-roditel' obnaruzhit "pogibshego" potomka pri sleduyushchem obrashchenii k funkcii wait. Tochno tak zhe i process na- chal'noj zagruzki (init) mozhet priostanovit'sya, ispol'zuya funkciyu wait, i za- vershayushchiesya po exit processy budut vozobnovlyat' ego, esli on imeet usynov- lennyh potomkov, prekrashchayushchih sushchestvovanie. V takoj realizacii funkcij exit i wait imeetsya odna nereshennaya problema, svyazannaya s tem, chto processy, prekrativshie sushchestvovanie, nel'zya ubirat' iz sistemy do teh por, poka ih roditel' ne ispolnit funkciyu wait. Esli process sozdal mnozhestvo potomkov, no tak i ne ispolnil funkciyu wait, mozhet proizoj- ti perepolnenie tablicy processov iz-za nalichiya potomkov, prekrativshih su- shchestvovanie s pomoshch'yu funkcii exit. V kachestve primera rassmotrim tekst programmy planirovshchika processov, privedennyj na Risunke 7.18. Process pro- izvodit schityvanie dannyh iz fajla standartnogo vvoda do teh por, poka ne budet obnaruzhen konec fajla, sozdavaya pri kazhdom ispolnenii funkcii read no- vogo potomka. Odnako, process-roditel' ne dozhidaetsya zaversheniya kazhdogo po- tomka, poskol'ku on stremitsya zapuskat' processy na vypolnenie kak mozhno bystree, tem bolee, chto mozhet projti dovol'no mnogo vremeni, prezhde chem pro- cess-potomok zavershit svoe vypolnenie. Esli, obrativshis' k +------------------------------------------------------------+ | #include | | main(argc,argv) | | { | | char buf[256]; | | | | if (argc != 1) | | signal(SIGCLD,SIG_IGN); /* ignorirovat' gibel' | | potomkov */ | | while (read(0,buf,256)) | | if (fork() == 0) | | { | | /* zdes' process-potomok obychno vypolnyaet | | kakie-to operacii nad buferom (buf) */ | | exit(0); | | } | | } | +------------------------------------------------------------+ Risunok 7.18. Primer ukazaniya prichiny poyavleniya signala "gi- bel' potomkov" 203 funkcii signal, process rasporyadilsya ignorirovat' signaly tipa "gibel' po- tomka", yadro budet ochishchat' zapisi, sootvetstvuyushchie prekrativshim sushchestvova- nie processam, avtomaticheski. Inache v konechnom itoge iz-za takih processov mozhet proizojti perepolnenie tablicy. 7.5 VYZOV DRUGIH PROGRAMM Sistemnaya funkciya exec daet vozmozhnost' processu zapuskat' druguyu prog- rammu, pri etom sootvetstvuyushchij etoj programme ispolnyaemyj fajl budet raspo- lagat'sya v prostranstve pamyati processa. Soderzhimoe pol'zovatel'skogo kon- teksta posle vyzova funkcii stanovitsya nedostupnym, za isklyucheniem peredava- emyh funkcii parametrov, kotorye perepisyvayutsya yadrom iz starogo adresnogo prostranstva v novoe. Sintaksis vyzova funkcii: execve(filename,argv,envp) gde filename - imya ispolnyaemogo fajla, argv - ukazatel' na massiv paramet- rov, kotorye peredayutsya vyzyvaemoj programme, a envp - ukazatel' na massiv parametrov, sostavlyayushchih sredu vypolneniya vyzyvaemoj programmy. Vyzov sis- temnoj funkcii exec osushchestvlyayut neskol'ko bibliotechnyh funkcij, takih kak execl, execv, execle i t.d. V tom sluchae, kogda programma ispol'zuet para- metry komandnoj stroki main(argc,argv) , +------------------------------------------------------------+ | algoritm exec | | vhodnaya informaciya: (1) imya fajla | | (2) spisok parametrov | | (3) spisok peremennyh sredy | | vyhodnaya informaciya: otsutstvuet | | { | | poluchit' indeks fajla (algoritm namei); | | proverit', yavlyaetsya li fajl ispolnimym i imeet li pol'- | | zovatel' pravo na ego ispolnenie; | | prochitat' informaciyu iz zagolovkov fajla i proverit', | | yavlyaetsya li on zagruzochnym modulem; | | skopirovat' parametry, peredannye funkcii, iz starogo | | adresnogo prostranstva v sistemnoe prostranstvo; | | dlya (kazhdoj oblasti, prisoedinennoj k processu) | | otsoedinit' vse starye oblasti (algoritm detachreg);| | dlya (kazhdoj oblasti, opredelennoj v zagruzochnom module) | | { | | vydelit' novye oblasti (algoritm allocreg); | | prisoedinit' oblasti (algoritm attachreg); | | zagruzit' oblast' v pamyat' po gotovnosti (algoritm | | loadreg); | | } | | skopirovat' parametry, peredannye funkcii, v novuyu ob- | | last' steka zadachi; | | special'naya obrabotka dlya setuid-programm, trassirovka; | | proinicializirovat' oblast' sohraneniya registrov zadachi | | (v ramkah podgotovki k vozvrashcheniyu v rezhim zadachi); | | osvobodit' indeks fajla (algoritm iput); | | } | +------------------------------------------------------------+ Risunok 7.19. Algoritm funkcii exec 204 massiv argv yavlyaetsya kopiej odnoimennogo parametra, peredavaemogo funkcii exec. Simvol'nye stroki, opisyvayushchie sredu vypolneniya vyzyvaemoj programmy, imeyut vid "imya=znachenie" i soderzhat poleznuyu dlya programm informaciyu, takuyu kak nachal'nyj katalog pol'zovatelya i put' poiska ispolnyaemyh programm. Pro- cessy mogut obrashchat'sya k parametram opisaniya sredy vypolneniya, ispol'zuya global'nuyu pere- mennuyu environ, kotoruyu zavodit nachal'naya procedura Si-interpretatora. Na Risunke 7.19 predstavlen algoritm vypolneniya sistemnoj funkcii exec. Snachala funkciya obrashchaetsya k fajlu po algoritmu namei, proveryaya, yavlyaetsya li fajl ispolnimym i otlichnym ot kataloga, a takzhe proveryaya nalichie u pol'zova- telya prava ispolnyat' programmu. Zatem yadro, schityvaya zagolovok fajla, opre- delyaet razmeshchenie informacii v fajle (format fajla). Na Risunke 7.20 izobrazhen logicheskij format ispolnyaemogo fajla v fajlo- voj sisteme, obychno generiruemyj translyatorom ili zagruzchikom. On razbivaet- sya na chetyre chasti: 1. Glavnyj zagolovok, soderzhashchij informaciyu o tom, na skol'ko razdelov de- litsya fajl, a takzhe soderzhashchij nachal'nyj adres ispolneniya processa i ne- kotoroe "magicheskoe chislo", opisyvayushchee tip ispolnyaemogo fajla. 2. Zagolovki razdelov, soderzhashchie informaciyu, opisyvayushchuyu kazhdyj razdel v fajle: ego razmer, virtual'nye adresa, v kotoryh on raspolagaetsya, i dr. 3. Razdely, soderzhashchie sobstvenno "dannye" fajla (naprimer, tekstovye), ko- torye zagruzhayutsya v adresnoe prostranstvo processa. 4. Razdely, soderzhashchie smeshannuyu informaciyu, takuyu kak tablicy identifika- torov i drugie dannye, ispol'zuemye v processe otladki. +---------------------------+ | Tip fajla | Glavnyj zagolovok | Kolichestvo razdelov | | Nachal'noe sostoyanie regis-| | trov | +---------------------------+ | Tip razdela | Zagolovok 1-go razdela | Razmer razdela | | Virtual'nyj adres | +---------------------------+ | Tip razdela | Zagolovok 2-go razdela | Razmer razdela | - | Virtual'nyj adres | - +---------------------------+ - | - | - | - | - +---------------------------+ - | Tip razdela | Zagolovok n-go razdela | Razmer razdela | | Virtual'nyj adres | +---------------------------+ Razdel 1 | Dannye (naprimer, tekst) | +---------------------------+ Razdel 2 | Dannye | - +---------------------------+ - | - | - | - | - +---------------------------+ Razdel n | Dannye | +---------------------------+ | Drugaya informaciya | +---------------------------+ Risunok 7.20. Obraz ispolnyaemogo fajla 205 Ukazannye sostavlyayushchie s razvitiem samoj sistemy vidoizmenyayutsya, odnako vo vseh ispolnyaemyh fajlah obyazatel'no prisutstvuet glavnyj zagolovok s po- lem tipa fajla. Tip fajla oboznachaetsya korotkim celym chislom (predstavlyaetsya v mashine poluslovom), kotoroe identificiruet fajl kak zagruzochnyj modul', davaya tem samym yadru vozmozhnost' otslezhivat' dinamicheskie harakteristiki ego vypolne- niya. Naprimer, v mashine PDP 11/70 opredelenie tipa fajla kak zagruzochnogo modulya svidetel'stvuet o tom, chto process, ispolnyayushchij fajl, mozhet ispol'zo- vat' do 128 Kbajt pamyati vmesto 64 Kbajt (**), tem ne menee v sistemah s za- meshcheniem stranic tip fajla vse eshche igraet sushchestvennuyu rol', v chem nam pred- stoit ubedit'sya vo vremya znakomstva s glavoj 9. Vernemsya k algoritmu. My ostanovilis' na tom, chto yadro obratilos' k in- deksu fajla i ustanovilo, chto fajl yavlyaetsya ispolnimym. YAdru sledovalo by osvobodit' pamyat', zanimaemuyu pol'zovatel'skim kontekstom processa. Odnako, poskol'ku v pamyati, podlezhashchej osvobozhdeniyu, raspolagayutsya peredavaemye no- voj programme parametry, yadro pervym delom kopiruet ih iz adresnogo prost- ranstva v promezhutochnyj bufer na vremya, poka ne budut otvedeny oblasti dlya novogo prostranstva pamyati. Poskol'ku parametrami funkcii exec vystupayut pol'zovatel'skie adresa massivov simvol'nyh strok, yadro po kazhdoj stroke snachala kopiruet v sistem- nuyu pamyat' adres stroki, a zatem samu stroku. Dlya hraneniya stroki v raznyh versiyah sistemy mogut byt' vybrany razlichnye mesta. CHashche prinyato hranit' stroki v steke yadra (lokal'naya struktura dannyh, prinadlezhashchaya programme yad- ra), na neraspredelyaemyh uchastkah pamyati (takih kak stranicy), kotorye mozhno zanimat' tol'ko vremenno, a takzhe vo vneshnej pamyati (na ustrojstve vygruz- ki). S tochki zreniya realizacii proshche vsego dlya kopirovaniya parametrov v novyj pol'zovatel'skij kontekst obratit'sya k steku yadra. Odnako, poskol'ku razmer steka yadra, kak pravilo, ogranichivaetsya sistemoj, a takzhe poskol'ku paramet- ry funkcii exec mogut imet' proizvol'nuyu dlinu, etot podhod sleduet sochetat' s drugimi podhodami. Pri rassmotrenii drugih variantov obychno ostanavlivayut- sya na sposobe hraneniya, obespechivayushchem naibolee bystryj dostup k strokam. Esli dostup k stranicam pamyati v sisteme realizuetsya dovol'no prosto, stroki sleduet razmeshchat' na stranicah, poskol'ku obrashchenie k operativnoj pamyati osushchestvlyaetsya bystree, chem k vneshnej (ustrojstvu vygruzki). Posle kopirovaniya parametrov funkcii exec v sistemnuyu pamyat' yadro otsoe- dinyaet oblasti, ranee prisoedinennye k processu, ispol'zuya algoritm detachreg. Neskol'ko pozzhe my eshche pogovorim o special'nyh dejstviyah, vypol- nyaemyh v otnoshenii oblastej komand. K rassmatrivaemomu momentu process uzhe lishen pol'zovatel'skogo konteksta i poetomu vozniknovenie v dal'nejshem lyuboj oshibki neizbezhno budet privodit' k zaversheniyu processa po signalu. Takimi oshibkami mogut byt' obrashchenie k prostranstvu, ne opisannomu v tablice oblas- tej yadra, popytka zagruzit' programmu, imeyushchuyu nedopustimo bol'shoj razmer ili ispol'zuyushchuyu oblasti s peresekayushchimisya adresami, i dr. YAdro vydelyaet i prisoedinyaet k processu oblasti komand i dannyh, zagruzhaet v operativnuyu pa- myat' soderzhimoe ispolnyaemogo fajla (algoritmy allocreg, attachreg i loadreg, sootvetstvenno). Oblast' dannyh processa iznachal'no podelena na dve chasti: --------------------------------------- (**) V PDP 11 "magicheskie chisla" imeyut znacheniya, sootvetstvuyushchie komandam perehoda; pri vypolnenii etih komand v rannih versiyah sistemy upravle- nie peredavalos' v raznye mesta programmy v zavisimosti ot razmera za- golovka i ot tipa ispolnyaemogo fajla. |ta osobennost' bol'she ne ispol'- zuetsya s teh por, kak sistema stala razrabatyvat'sya na yazyke Si. 206 dannye, inicializaciya kotoryh byla vypolnena vo vremya kompilyacii, i dannye, ne opredelennye kompilyatorom ("bss"). Oblast' pamyati pervonachal'no vydelyaet- sya dlya proinicializirovannyh dannyh. Zatem yadro uvelichivaet razmer oblasti dannyh dlya razmeshcheniya dannyh tipa "bss" (algoritm growreg) i obnulyaet ih znacheniya. Naposledok yadro vydelyaet i prisoedinyaet k processu oblast' steka i otvodit prostranstvo pamyati dlya hraneniya parametrov funkcii exec. Esli para- metry funkcii razmeshchayutsya na stranicah, te zhe stranicy mogut byt' ispol'zo- vany pod stek. V protivnom sluchae parametry funkcii razmeshchayutsya v steke za- dachi. V prostranstve processa yadro stiraet adresa pol'zovatel'skih funkcij ob- rabotki signalov, poskol'ku v novom pol'zovatel'skom kontekste oni teryayut svoe znachenie. Odnako i v novom kontekste rekomendacii po ignorirovaniyu teh ili inyh signalov ostayutsya v sile. YAdro ustanavlivaet v registrah dlya rezhima zadachi znacheniya iz sohranennogo registrovogo konteksta, v chastnosti pervona- chal'noe znachenie ukazatelya vershiny steka (sp) i schetchika komand (pc): pervo- nachal'noe znachenie schetchika komand bylo zaneseno zagruzchikom v zagolovok fajla. Dlya setuid-programm i dlya trassirovki processa yadro predprinimaet osobye dejstviya, na kotoryh my eshche ostanovimsya vo vremya rassmotreniya glav 8 i 11, sootvetstvenno. Nakonec, yadro zapuskaet algoritm iput, osvobozhdaya in- deks, vydelennyj po algoritmu namei v samom nachale vypolneniya funkcii exec. Algoritmy namei i iput v funkcii exec vypolnyayut rol', podobnuyu toj, kotoruyu oni vypolnyayut pri otkrytii i zakrytii fajla; sostoyanie fajla vo vremya vypol- neniya funkcii exec pohozhe na sostoyanie otkrytogo fajla, esli ne prinimat' vo vnimanie otsutstvie zapisi o fajle v tablice fajlov. Po vyhode iz funkcii process ispolnyaet tekst novoj programmy. Tem ne menee, process ostaetsya tem zhe, chto i do vypolneniya funkcii; ego identifikator ne izmenilsya, kak ne iz- menilos' i ego mesto v ierarhii processov. Izmeneniyu podvergsya tol'ko pol'- zovatel'skij kontekst processa. +-------------------------------------------------------+ | main() | | { | | int status; | | if (fork() == 0) | | execl("/bin/date","date",0); | | wait(&status); | | } | +-------------------------------------------------------+ Risunok 7.21. Primer ispol'zovaniya funkcii exec V kachestve primera mozhno privesti programmu (Risunok 7.21), v kotoroj sozdaetsya process-potomok, zapuskayushchij funkciyu exec. Srazu po zavershenii funkcii fork process-roditel' i process-potomok nachinayut ispolnyat' nezavisi- mo drug ot druga kopii odnoj i toj zhe programmy. K momentu vyzova proces- som-potomkom funkcii exec v ego oblasti komand nahodyatsya instrukcii etoj programmy, v oblasti dannyh raspolagayutsya stroki "/bin/date" i "date", a v steke - zapisi, kotorye budut izvlecheny po vyhode iz exec. YAdro ishchet fajl "/bin/date" v fajlovoj sisteme, obnaruzhiv ego, uznaet, chto ego mozhet ispol- nit' lyuboj pol'zovatel', a takzhe to, chto on predstavlyaet soboj zagruzochnyj modul', gotovyj dlya ispolneniya. Po usloviyu pervym parametrom funkcii exec, vklyuchaemym v spisok parametrov argv, yavlyaetsya imya ispolnyaemogo fajla (pos- lednyaya komponenta imeni puti poiska fajla). Takim obrazom, process imeet dostup k imeni programmy na pol'zovatel'skom urovne, chto inogda mozhet oka- zat'sya poleznym (***). Zatem yadro kopiruet stroki "/bin/date" i "date" vo vnutrennyuyu strukturu hraneniya i osvobozhdaet oblasti komand, dannyh i steka, zanimaemye processom. Processu vydelyayutsya novye oblasti komand, dannyh i steka, v oblast' komand perepisyvaetsya komandnaya sekciya fajla "/bin/date", v 207 --------------------------------------- (***) Naprimer, v versii V standartnye programmy pereimenovaniya fajla (mv), kopirovaniya fajla (cp) i komponovki fajla (ln), poskol'ku ispolnyayut pohozhie dejstviya, vyzyvayut odin i tot zhe ispolnyaemyj fajl. Po imeni vyzyvaemoj programmy process uznaet, kakie dejstviya v nastoyashchij moment trebuyutsya pol'zovatelyu. oblast' dannyh - sekciya dannyh fajla. YAdro vosstanavlivaet pervonachal'nyj spisok parametrov (v dannom sluchae eto stroka simvolov "date") i pomeshchaet ego v oblast' steka. Vyzvav funkciyu exec, process-potomok prekrashchaet vypol- nenie staroj programmy i perehodit k vypolneniyu programmy "date"; kogda programma "date" zavershitsya, process-roditel', ozhidayushchij etogo momenta, poluchit kod zaversheniya funkcii exit. Vplot' do nastoyashchego momenta my predpolagali, chto komandy i dannye raz- meshchayutsya v raznyh sekciyah ispolnyaemoj programmy i, sledovatel'no, v raznyh oblastyah tekushchego processa. Takoe razmeshchenie imeet dva osnovnyh preimushchest- va: prostota organizacii zashchity ot nesankcionirovannogo dostupa i vozmozh- nost' razdeleniya oblastej razlichnymi processami. Esli by komandy i dannye nahodilis' v odnoj oblasti, sistema ne smogla by predotvratit' zatiranie ko- mand, poskol'ku ej ne byli by izvestny adresa, po kotorym oni raspolagayutsya. Esli zhe komandy i dannye nahodyatsya v raznyh oblastyah, sistema imeet vozmozh- nost' pol'zovat'sya mehanizmami apparatnoj zashchity oblasti komand processa. Kogda process sluchajno popytaetsya chto-to zapisat' v oblast', zanyatuyu koman- dami, on poluchit otkaz, porozhdennyj sistemoj zashchity i privodyashchij obychno k avarijnomu zaversheniyu processa. +------------------------------------------------------------+ | #include | | main() | | { | | int i,*ip; | | extern f(),sigcatch(); | | | | ip = (int *)f; /* prisvoenie peremennoj ip znacheniya ad-| | resa funkcii f */ | | for (i = 0; i < 20; i++) | | signal(i,sigcatch); | | *ip = 1; /* popytka zateret' adres funkcii f */ | | printf("posle prisvoeniya znacheniya ip\n"); | | f(); | | } | | | | f() | | { | | } | | | | sigcatch(n) | | int n; | | { | | printf("prinyat signal %d\n",n); | | exit(1); | | } | +------------------------------------------------------------+ Risunok 7.22. Primer programmy, vedushchej zapis' v oblast' komand V kachestve primera mozhno privesti programmu (Risunok 7.22), kotoraya prisvaivaet peremennoj ip znachenie adresa funkcii f i zatem delaet rasporya- 208 zhenie prinimat' vse signaly. Esli programma skompilirovana tak, chto komandy i dannye raspolagayutsya v raznyh oblastyah, process, ispolnyayushchij programmu, pri popytke zapisat' chto-to po adresu v ip vstretit porozhdennyj sistemoj za- shchity otkaz, poskol'ku oblast' komand zashchishchena ot zapisi. Pri rabote na komp'yutere AT&T 3B20 yadro posylaet processu signal SIGBUS, v drugih sistemah vozmozhna posylka drugih signalov. Process prinimaet signal i zavershaetsya, ne dojdya do vypolneniya komandy vyvoda na pechat' v procedure main. Odnako, esli programma skompilirovana tak, chto komandy i dannye raspolagayutsya v odnoj ob- lasti (v oblasti dannyh), yadro ne pojmet, chto process pytaetsya zateret' ad- res funkcii f. Adres f stanet ravnym 1. Process ispolnit komandu vyvoda na pechat' v procedure main, no kogda zapustit funkciyu f, proizojdet oshibka, svyazannaya s popytkoj vypolneniya zapreshchennoj komandy. YAdro poshlet processu signal SIGILL i process zavershitsya. Raspolozhenie komand i dannyh v raznyh oblastyah oblegchaet poisk i predot- vrashchenie oshibok adresacii. Tem ne menee, v rannih versiyah sistemy UNIX ko- mandy i dannye razreshalos' raspolagat' v odnoj oblasti, poskol'ku na mashinah PDP razmer processa byl sil'no ogranichen: programmy imeli men'shij razmer i sushchestvenno men'shuyu segmentaciyu, esli komandy i dannye zanimali odnu i tu zhe oblast'. V poslednih versiyah sistemy takih strogih ogranichenij na razmer processa net i v dal'nejshem vozmozhnost' zagruzki komand i dannyh v odnu ob- last' kompilyatorami ne budet podderzhivat'sya. Vtoroe preimushchestvo razdel'nogo hraneniya komand i dannyh sostoit v voz- mozhnosti sovmestnogo ispol'zovaniya oblastej processami. Esli process ne mo- zhet vesti zapis' v oblast' komand, komandy processa ne preterpevayut nikakih izmenenij s togo momenta, kak yadro zagruzilo ih v oblast' komand iz komand- noj sekcii ispolnyaemogo fajla. Esli odin i tot zhe fajl ispolnyaetsya neskol'- kimi processami, v celyah ekonomii pamyati oni mogut imet' odnu oblast' komand na vseh. Takim obrazom, kogda yadro pri vypolnenii funkcii exec otvodit ob- last' pod komandy processa, ono proveryaet, imeetsya li vozmozhnost' sovmestno- go ispol'zovaniya processami komand ispolnyaemogo fajla, chto opredelyaetsya "ma- gicheskim chislom" v zagolovke fajla. Esli da, to s pomoshch'yu algoritma xalloc yadro ishchet sushchestvuyushchuyu oblast' s komandami fajla ili naznachaet novuyu v slu- chae ee otsutstviya (sm. Risunok 7.23). Ispolnyaya algoritm xalloc, yadro prosmatrivaet spisok aktivnyh oblastej v poiskah oblasti s komandami fajla, indeks kotorogo sovpadaet s indeksom is- polnyaemogo fajla. V sluchae ee otsutstviya yadro vydelyaet novuyu oblast' (algo- ritm allocreg), prisoedinyaet ee k processu (algoritm attachreg), zagruzhaet ee v pamyat' (algoritm loadreg) i zashchishchaet ot zapisi (read-only). Poslednij shag predpolagaet, chto pri popytke processa zapisat' chto-libo v oblast' ko- mand budet poluchen otkaz, vyzvannyj sistemoj zashchity pamyati. V sluchae obnaru- zheniya oblasti s komandami fajla v spiske aktivnyh oblastej osushchestvlyaetsya proverka ee nalichiya v pamyati (ona mozhet byt' libo zagruzhena v pamyat', libo vygruzhena iz pamyati) i prisoedinenie ee k processu. V zavershenie vypolneniya algoritma xalloc yadro snimaet s oblasti blokirovku, a pozdnee, sleduya algo- ritmu detachreg pri vypolnenii funkcij exit ili exec, umen'shaet znachenie schetchika oblastej. V tradicionnyh realizaciyah sistemy podderzhivaetsya tablica komand, k kotoroj yadro obrashchaetsya v sluchayah, podobnyh opisannomu. Takim ob- razom, sovokupnost' oblastej komand mozhno rassmatrivat' kak novuyu versiyu etoj tablicy. Napomnim, chto esli oblast' pri vypolnenii algoritma allocreg (Razdel 6.5.2) vydelyaetsya vpervye, yadro uvelichivaet znachenie schetchika ssylok na in- deks, associirovannyj s oblast'yu, pri etom znachenie schetchika ssylok nami uzhe bylo uvelicheno v samom nachale vypolneniya funkcii exec (algoritm namei). Pos- kol'ku yadro umen'shaet znachenie schetchika tol'ko odin raz v zavershenie vypol- neniya funkcii exec (po algoritmu iput), znachenie schetchika ssylok na indeks fajla, associirovannogo s razdelyaemoj oblast'yu komand i ispolnyaemogo v nas- toyashchij moment, ravno po men'shej mere 1. Poetomu kogda process razryvaet svyaz' s fajlom (funkciya unlink), soderzhimoe fajla ostaetsya netronutym (ne preterpevaet izmenenij). Posle zagruzki v pamyat' sam fajl yadru stanovitsya 209 nenuzhen, yadro interesuet tol'ko ukazatel' na kopiyu indeksa fajla v pamyati, soderzhashchijsya v tablice oblastej; etot ukazatel' i budet identificirovat' +------------------------------------------------------------+ | algoritm xalloc /* vydelenie i inicializaciya oblasti | | komand */ | | vhodnaya informaciya: indeks ispolnyaemogo fajla | | vyhodnaya informaciya: otsutstvuet | | { | | esli (ispolnyaemyj fajl ne imeet otdel'noj oblasti komand)| | vernut' upravlenie; | | esli (uzhe imeetsya oblast' komand, associirovannaya s in- | | deksom ispolnyaemogo fajla) | | { | | /* oblast' komand uzhe sushchestvuet ... podklyuchit'sya k | | nej */ | | zablokirovat' oblast'; | | vypolnit' poka (soderzhimoe oblasti eshche ne dostupno) | | { | | /* operacii nad schetchikom ssylok, predohranyayushchie | | ot global'nogo udaleniya oblasti | | */ | | uvelichit' znachenie schetchika ssylok na oblast'; | | snyat' s oblasti blokirovku; | | priostanovit'sya (poka soderzhimoe oblasti ne stanet| | dostupnym); | | zablokirovat' oblast'; | | umen'shit' znachenie schetchika ssylok na oblast'; | | } | | prisoedinit' oblast' k processu (algoritm attachreg);| | snyat' s oblasti blokirovku; | | vernut' upravlenie; | | } | | /* interesuyushchaya nas oblast' komand ne sushchestvuet -- soz- | | dat' novuyu */ | | vydelit' oblast' komand (algoritm allocreg); /* oblast' | | zabloki- | | rovana */| | esli (oblast' pomechena kak "neot®emlemaya") | | otklyuchit' sootvetstvuyushchij flag; | | podklyuchit' oblast' k virtual'nomu adresu, ukazannomu v | | zagolovke fajla (algoritm attachreg); | | esli (fajl imeet special'nyj format dlya sistemy s zameshche-| | niem stranic) | | /* etot sluchaj budet rassmotren v glave 9 */ | | v protivnom sluchae /* fajl ne imeet special'nogo for-| | mata */ | | schitat' komandy iz fajla v oblast' (algoritm | | loadreg); | | izmenit' rezhim zashchity oblasti v zapisi chastnoj tablicy | | oblastej processa na "read-only"; | | snyat' s oblasti blokirovku; | | } | +-----------------------------------------