Programov´an´ıv UNIXu
(NSWI015)
verze: 24. ˇr´ıjna2017
(c) 2011 – 2017 Vladim´ırKotal (c) 2005 – 2011, 2016 – 2017 Jan Pechanec (c) 1999 – 2004 Martin Beran
SISAL MFF UK, Malostransk´en´am.25, 118 00 Praha 1
• Toto jsou ofici´aln´ımateri´alypro v´yuku pˇredmˇetu Programov´an´ıv UNIXu (k´odpˇredmˇetuNSWI015) na Matematicko-fyzik´aln´ıfakultˇeUniverzity Kar- lovy. • Tyto materi´alyjsou uveˇrejnˇeny pod licenc´ı Creative Commons BY-NC-SA 3.0. Soubory k uk´azkov´ympˇr´ıklad˚umuveden´ev´yˇsejsou Public Domain, po- kud v nich nen´ıuvedeno jinak. • Tento pˇredmˇetje 2/1, cviˇcen´ıbude jednou za dva t´ydny. • Vˇsechny informace, kter´ebudete potˇrebovat, a materi´alyk pˇredn´aˇscejsou na http://mff.devnull.cz/, vˇcetnˇeaktu´aln´ıverze tˇechto pozn´amkov´ych slajd˚u (http://mff.devnull.cz/pvu/slides/). Dˇr´ıve, neˇzzaˇcnetemateri´alypou- ˇz´ıvat, pˇresvˇedˇctese, ˇzenen´ınovˇejˇs´ıverze! • Uk´azkov´epˇr´ıkladyjsou na http://mff.devnull.cz/pvu/src/, pokud se budu v pozn´amk´ach odkazovat na konkr´etn´ıpˇr´ıklad,link zde uveden´yslouˇz´ıjako koˇrenov´yadres´aˇr.
• Je potˇrebase zapsat na cviˇcen´ıv SISu. • Z´apoˇcetje za z´apoˇctov´yprogram. • Zkouˇska m´ap´ısemnoua ´ustn´ıˇc´ast. • Zkouˇsetse bude to, co bude odpˇredneseno(kromˇet´ematna vyplnˇen´ıpˇr´ıpadnˇe zbyl´ehoˇcasu).Vˇetˇsinainformac´ıje ve slajdech, ale ˇradad˚uleˇzit´ych podrob- nost´ım˚uˇzechybˇet.
1 • Pˇredpoklady: – Uˇzivatelsk´aznalost UNIXu, programov´an´ıv shellu na ´urovni pˇredn´aˇsky ,,Uvod´ do UNIXu” (NSWI095) – Znalost jazyka C – Znalost z´akladn´ıch pojm˚uteorie operaˇcn´ıch syst´em˚u • Tento text je pr˚ubˇeˇznˇedoplˇnov´an,ChangeLog zaˇc´ın´ana stranˇe 242. Upo- zornˇen´ına chyby pros´ımpos´ılejtena kontakty, kter´enajdete na v´yˇseuveden´e str´ance.
Obsah
• ´uvod, v´yvoj UNIXu a C, program´atorsk´en´astroje • z´akladn´ıpojmy a konvence UNIXu a jeho API • pˇr´ıstupov´apr´ava, perifern´ızaˇr´ızen´ı,syst´emsoubor˚u • manipulace s procesy, spouˇstˇen´ıprogram˚u • sign´aly • synchronizace a komunikace proces˚u • s´ıt’ov´akomunikace • vl´akna,synchronizace vl´aken • ??? - bude definov´anopozdˇeji,podle toho kolik zbyde ˇcasu
• Budeme se zab´yvat hlavnˇeprincipy UNIXu a programov´an´ım pro UNIX pouze v jazyce C. • Pˇredn´aˇska je pˇrev´aˇznˇeo syst´emov´ych vol´an´ıch, tj. rozhran´ımmezi uˇzivatelsk´ymprostorem a j´adrem.
• Pˇripopisu API se budeme drˇzetnormy Single UNIX Specification, version 4 (SUSv4). Syst´emy, kter´etuto specifikaci podporuj´ı,mohou pouˇz´ıvat oznaˇcen´ı UNIX V7. Pˇredchoz´ıverzi SUSv3 splˇnuj´ıposledn´ıverze syst´em˚uSolaris, AIX, HP-UX a Mac OS X na r˚uzn´ych architektur´ach (http://www.opengroup.org/ openbrand/register/xy.htm).
• Pro konkr´etn´ıpˇr´ıklady budu pouˇz´ıvat vˇetˇsinou syst´emy FreeBSD a Linux.
2 Obsah
• ´uvod, v´yvoj UNIXu a C, program´atorsk´en´astroje • z´akladn´ıpojmy a konvence UNIXu a jeho API • pˇr´ıstupov´apr´ava, perifern´ızaˇr´ızen´ı,syst´emsoubor˚u • manipulace s procesy, spouˇstˇen´ıprogram˚u • sign´aly • synchronizace a komunikace proces˚u • s´ıt’ov´akomunikace • vl´akna,synchronizace vl´aken • ??? - bude definov´anopozdˇeji,podle toho kolik zbyde ˇcasu
Literatura v ˇceˇstinˇe
1. Skoˇcovsk´y,L.: Principy a probl´emy operaˇcn´ıhosyst´emu UNIX. Science, 1993 2. Skoˇcovsk´y,Ludˇek: UNIX, POSIX, Plan9. L. Skoˇcovsk´y, Brno, 1998 3. Jelen, Milan: UNIX V - programov´an´ıv syst´emu. Grada, Praha 1993 4. Linux - Dokumentaˇcn´ıprojekt. Computer Press, 1998; http://www.cpress.cz/knihy/linux 5. Herout, Pavel: Uˇcebnicejazyka C. 2 d´ıly. Kopp, Cesk´eˇ Budˇejovice, 2004 (4., respektive 2. pˇrepracovan´evyd´an´ı)
3 Ohlednˇeunixu doporuˇcujisp´ıˇseliteraturu v anglick´emjazyce.
1. Vˇsestrann´y´uvod do UNIXu, ale dost struˇcn´a;Skoˇcovsk´yje autorem v´ıce ˇcesk´ych knih o unixu, ale dnes jsou jiˇzv´ıcenebo m´enˇezastaral´e. 2. Pokroˇcilejˇs´ıpohled, ale pˇredpokl´ad´apˇredbˇeˇzn´eznalosti, m´ısty tˇeˇzko stravi- teln´a. 3. Programov´an´ıv C pro UNIX System V, pr´acese soubory a s procesy, Sys- tem V IPC, nepopisuje napˇr.vl´aknaa s´ıtˇe. 4. O Linuxu bylo samozˇrejmˇev ˇceˇstinˇevyd´anomnoho dalˇs´ıch knih.
5. Vynikaj´ıc´ıknihy o jazyce C.
Literatura - design a principy syst´emu
1. Uresh Vahalia: UNIX Internals: The New Frontiers. Prentice Hall; 1st edition, 1995 2. Bach, Maurice J.: The Design of the UNIX Operating System. Prentice Hall, 1986 3. McKusick, M. K., Neville-Neil, G. V.: The Design and Implementation of the FreeBSD Operating System. Addison-Wesley, 2004 4. McDougall, R.; Mauro, J.: Solaris Internals. Prentice Hall; 2nd edition, 2006. 5. Linux Documentation Project. http://tldp.org/
Tyto knihy se zab´yvaj´ıstavbou unixu, pouˇzit´ymialgoritmy, strukturami apod., nejsou to kniho o programov´an´ıpod t´ımto syst´emem.
1. Skvˇel´akniha, zab´yv´ase obecn´ymimyˇslenkami UNIXu a porovn´av´asyst´emy SVR4.2, 4.4BSD, Solarix 2.x a Mach. 12/2005 mˇelovyj´ıtdruh´e,doplnˇen´e vyd´an´ı.Po nˇekolika letech ˇcek´an´ıpˇrestalodruh´evyd´an´ıfigurovat v listingu na amazon.com, a tedy se budeme muset zˇrejmˇesm´ıˇrits t´ım,ˇzenevyjde. 2. Klasick´akniha o UNIXu, popis struktury a funkc´ıj´adraUNIX System V Rel. 2, ˇc´asteˇcnˇei 3; pˇrestoˇzeje to kniha z dneˇsn´ıhopohledu jiˇzzastaral´a, lze ji poˇr´adjednoznaˇcnˇedoporuˇcit,protoˇzeto je jedna z nejlepˇs´ıch knih, co byla kdy o UNIXu naps´ana.V roce 1993 vyˇselˇcesk´ypˇreklad, Principy operaˇcn´ıhosyst´emu UNIX, SAS.
4 3. Popis struktury a funkc´ıj´adraFreeBSD 5.2; tato kniha navazuje na klasickou knihu The Design and Implementation of the 4.4 BSD Operating System od stejn´ehoautora (resp. jeden ze ˇctyˇr,uveden´yjako prvn´ı). 4. Nejlepˇs´ıkniha o operaˇcn´ımsyst´emu Solaris. Obsahuje podrobn´einformace o tom, jak tento syst´emfunguje vˇcetnˇenejnovˇejˇs´ıch vˇec´ız verze 10 jako jsou z´ony, Crypto Framework, DTrace, Least Privilege model a dalˇs´ı. 5. Domovsk´astrana Linux dokumentaˇcn´ıhoprojektu.
Literatura - programov´an´ı
1. Stevens, W. R., Rago, S. A.: Advanced Programming in UNIX(r) Environment. Addison-Wesley, 2nd edition, 2005. 2. Rochkind, M. J.: Advanced UNIX Programming, Addison-Wesley; 2nd edition, 2004 3. Stevens, W. R., Fenner B., Rudoff, A. M.: UNIX Network Programming, Vol. 1 – The Sockets Networking API. Prentice Hall, 3rd edition, 2004 4. Butenhof, D. R.: Programming with POSIX Threads, Addison-Wesley; 1st edition, 1997 5. UNIXov´especifikace, viz http://www.unix.org 6. manu´alov´estr´anky(zejm. sekce 2, 3)
1. Pravdˇepodobnˇenen´ı lepˇs´ı knihy o programov´an´ı pod unixem (neobsahuje s´ıt’ov´eprogramov´an´ı,to je v knize 3). 2. Aktualizovan´evyd´an´ıdalˇs´ız klasick´ych knih o programov´an´ıpod unixem. Obsahuje i s´ıt’ov´eprogramov´an´ıa aˇcsamozˇrejmˇenen´ıtak podrobn´ajako spo- jen´ıknih 1 a 3, m˚uˇzeto b´ytnˇekdynaopak v´yhodou. Tuto knihu jednoznaˇcnˇe doporuˇcuji,pokud chcete nˇecokupovat a chcete m´ıtpro zaˇc´atekjen jednu knihu. Pokud bych ji mˇelcharakterizovat jednou vˇetou,bylo by to, ˇzeautor vid´ıa dok´aˇze uk´azatsouvislosti, coˇzje velmi vz´acn´avlastnost. 3. Klasick´akniha o s´ıt’ov´emprogramov´an´ı,jedna z nejlepˇs´ıch k tomuto t´ematu; existuje i druh´yd´ıl UNIX Network Programming, Volume 2: In- terprocess Communications, kter´ase zab´yv´akomunikac´ımezi procesy (roury, POSIX IPC, System V IPC, synchronizace vl´aken, RPC). 4. Velmi dobr´aa podrobn´akniha o programov´an´ıs vl´akny. 5. Domovsk´astr´anka posledn´ıch specifikac´ırozhran´ıUNIXu.
5 6. Podrobn´ypopis jednotliv´ych funkc´ı (v Linuxu bˇeˇznˇene zcela dostaˇcuj´ıc´ı; manu´alov´estr´ankyv tomto syst´emu jsou ˇcastohorˇs´ıkvality neˇzu syst´em˚u ostatn´ıch).
7. Kniha, kter´ase neveˇslana slajd a kter´apˇrekraˇcujeobsah t´etopˇredn´aˇsky: Gallmeister, B. R.: POSIX.4 Programmers Guide: Programming for the Real World, O’Reilly; 1st edition, 1995. V´yborn´akniha s kr´asnou ob´alkou o real-time rozˇs´ıˇren´ıch POSIXu. Viz tak´estrany 155a 159.
... a spousta dalˇs´ıch knih, online dokumentac´ıa internetov´ych zdroj˚u,posledn´ı dobou vych´az´ıpomˇernˇehodnˇeknih o Linuxu, zamˇeˇren´ych na pouˇz´ıv´an´ıi programov´an´ı. ... jdˇetena http://www.amazon.com/ a zadejte kl´ıˇcov´eslovo “unix”. Pokud byste z Amazonu nˇecokupovali, dejte pozor na to, ˇzemnoho knih m´aaktu- alizovan´avyd´an´ıi po nˇekolika m´aloletech, nˇekdyi levnˇejˇs´ıneˇzta p˚uvodn´ı, kter´ajsou vˇsakst´alena skladu a v on-line nab´ıdce;tak at’ zbyteˇcnˇenekoup´ıte starˇs´ıvyd´an´ıneˇzto aktu´aln´ı.Nav´ıcse vyplat´ızkontrolovat i u pˇr´ısluˇsn´eho vydavatelstv´ı,ˇzenen´ıv brzk´edobˇenapl´anov´anovyd´an´ınov´e– tato informace nˇekdyna Amazonu je, nˇekdyne.
... na Amazonu se m˚uˇzevyplatit nakoupit knihy z druh´eruky, protoˇzejsou ˇcasto v´yraznˇelevnˇejˇs´ıneˇzknihy nov´e.Probl´emje, ˇzevˇetˇsinounen´ımoˇzn´eje poslat pˇr´ımodo CR,ˇ ale mus´ıv´amje nˇekdopˇriv´ezt.
Literatura - historie UNIXu
• Peter Salus: A Quarter Century of UNIX, Addison-Wesley; 1st edition (1994) • Libes D., Ressler, S.: Life With Unix: A Guide for Everyone, Prentice Hall (1989) • Open Sources: Voices from the Open Source Revolution, kapitola Twenty Years of Berkeley Unix From AT&T-Owned to Freely Redistributable; O’Reilly (1999); on-line na webu: http://oreilly.com/openbook/opensources/book/index.html ... mnoho materi´al˚una webu; ˇcastovˇsakobsahuj´ıc´ıne zcela pˇresn´einformace
• Kapitola o BSD Unixu z Open Sources napsan´aMarshallem Kirk McKusic- kem je opravdu v´yborn´a.
6 (Pre)historie UNIXu
• 1925 – Bell Telephone Laboratories – v´yzkumv komunikac´ıch (napˇr.1947: transistor) v r´amci AT&T • 1965 – BTL s General Electric a MIT v´yvoj OS Multics (MULTIplexed Information and Computing System) • 1969 – Bell Labs opouˇst´ıprojekt, Ken Thompson p´ıˇse assembler, z´akladn´ıOS a syst´emsoubor˚upro PDP-7 • 1970 – Multi-cs ⇒ Uni-cs ⇒ Uni-x • 1971 – UNIX V1, a portov´anna PDP-11 • prosinec 1971 – prvn´ıedice UNIX Programmer’s Manual
• AT&T = American Telephone and Telegraph Company • Multics byl syst´em,kter´yv´yznamnˇeovlivnil dalˇs´ıv´yvoj operaˇcn´ıch syst´em˚u. Obsahoval mnoho v t´edobˇeinovativn´ıch myˇslenek,z nichˇzale ne vˇsechny byly pˇrij´ım´any kladnˇe. V´yznamnˇeovlivnil pr´avˇeUNIX, kter´ymnoho myˇslenek pˇrevzala jeho nedostatky se naopak snaˇzil napravit. Hlavn´ırozd´ılbyl asi ten, ˇzeUNIX byl navrˇzenjako mnohem jednoduˇsˇs´ısyst´em,neˇzMultics.
• po odchodu BTL z projektu Multics prodala GE svoji poˇc´ıtaˇcovou divizi firmˇeHoneywell vˇcetnˇeprojektu Multics, kter´yse pak pod jej´ı patronac´ı d´aleaktivnˇevyv´ıjel(virtu´aln´ıpamˇet’, multiprocesory, . . . ), aˇzdo roku 1985. Posledn´ı instalace Multics-u fungovala na kanadsk´emMinisterstvu obrany (Canadian Department of National Defence) a syst´embyl napˇr´ıklad jeˇstˇe aktivnˇepouˇz´ıv´anpro vojensk´eoperace bˇehemv´alky v Persk´em z´alivu.Defi- nitivn´ıshutdown byl proveden 31. ˇr´ıjna2000. V´ıceinformac´ıje moˇzn´enal´ezt na http://www.multicians.org. • pˇredpoˇc´atkem pr´acena v´yvojov´emprostˇred´ıpro PDP-7 napsal Thompson program Space Travel, kter´ybyl vyvinut na jin´emprostˇred´ı(Honeywell 635) a na p´ascepˇrenesenna PDP-7. • celkem bylo 10 edic´ıtohoto manu´alu,koresponduj´ıc´ıdeseti verz´ımUNIXu vznikl´ych v BTL.
• UNIX V1 nemˇelvol´an´ı pipe !!!
7 • manu´alpro verzi 1: http://man.cat-v.org/unix-1st/ Stoj´ıza to nahl´ednout, jak jeho struktura ovlivnila vzhled dneˇsn´ıch manu´alov´ych str´anek.
• za povˇsimnut´ıstoj´ı,ˇzeUNIX je zhruba o 10 let starˇs´ıneˇzDOS • syst´emMultics mˇel9 hlavn´ıch c´ıl˚u,jak pops´anov ˇcl´anku Introduction and Overview of the Multics System z roku 1965. Za nejzaj´ımavˇejˇs´ı c´ıl bych povaˇzoval poˇzadavek na nepˇreruˇsovan´ybˇehsyst´emu. • Multics byl napsan´yv jazyce PL/I (Programming Language #1), tedy dˇr´ıve neˇzbyl UNIX pˇrepsan´ydo C ! • Multicsu byl v roce 1980 udˇelenjako prvn´ımu syst´emu level B2. Po nˇekolik let to byl jedin´ysyst´ems t´ımto bezpeˇcnost´ımlevelem. • GE byla zaloˇzenav roce 1892 slouˇcen´ım dvou spoleˇcnost´ı, z nichˇzjedna byla Edison General Electric Company zaloˇzen´aroku 1879 Thomasem Al- vou Edisonem (vyn´alezceˇz´arovky, filmov´ekamery, . . . ); v souˇcasn´edobˇejej´ı dceˇrinn´espoleˇcnostipokr´yvaj´ı mnoho oblast´ı, vˇcetnˇedod´avkyjednoho ze dvou typ˚umotor˚upro Airbus 380 nebo bankovnictv´ı. • PDP = Programmed Data Processor. Prvn´ı typ, PDP-1, se prod´avala za $120.000 v dobˇe, kdy se jin´epoˇc´ıtaˇceprod´avaly za ceny pˇresmili´on.To byla tak´estrategie fy DEC - pojem computer tehdy znamenal drahou vˇec, potˇrebuj´ıc´ıs´ala t´ymlid´ı,kter´yse o to vˇsechno bude starat. Proto DEC sv´e maˇsiny nenaz´yval poˇc´ıtaˇci,ale pravˇeslovem PDPs. • PDP-11 je legend´arn´ımaˇsinaod firmy DEC, postupnˇevznikaly verze PDP- 1 az PDP-16, kromˇePDP-2, PDP-13. Existuj´ıPDP-11 syst´emy, kter´ejeˇstˇe dnes bˇeˇz´ı,a tak´efirmy, kter´epro nˇevyr´abˇej´ın´ahradn´ıd´ıly.
8 Historie UNIXu, pokraˇcov´an´ı
• ´unor1973 – UNIX V3 obsahoval cc pˇrekladaˇc(jazyk C byl vytvoˇren Dennisem Ritchiem pro potˇreby UNIXu) • ˇr´ıjen1973 – UNIX byl pˇredstaven veˇrejnostiˇcl´ankem The UNIX Timesharing System na konferenci ACM • listopad 1973 – UNIX V4 pˇreps´ando jazyka C • 1975 – UNIX V6 byl prvn´ıverz´ıUNIXu bˇeˇznˇek dost´an´ımimo BTL • 1979 – UNIX V7, pro mnoh´e“the last true UNIX”, obsahoval uucp, Bourne shell; velikost kernelu byla pouze 40KB !!! • 1979 – UNIX V7 portov´anna 32-bitov´yVAX-11 • 1980 – Microsoft pˇr´ıch´az´ıs XENIXem, kter´yje zaloˇzen´yna UNIXu V7
• ACM = Association for Computing Machinery, zaloˇzena1947. UNIX pˇredstavili Ken Thompson a Dennis Ritchie. • akt pˇreps´an´ıUNIXu do jazyka C byl moˇzn´anejv´yznamnˇejˇs´ımmo- mentem v historii tohoto syst´emu ⇒ UNIX mohl b´ytmnohem jed- noduˇsejiportov´anna jin´earchitektury • na verzi 6 je zaloˇzenalegend´arn´ıkniha A commentary on the Unix Operating System, jej´ıˇzautorem je John Lions. • Microsoft neprod´aval XENIX pˇr´ımo,ale licencoval ho OEM v´yrobc˚um(Ori- ginal Equipment Manufacturer) jako byl Intel, SCO a jin´ı.Jin´efirmy pak XENIX d´aleportovaly na 286 (Intel) a 386 (SCO, 1987). Na webu je moˇzn´e naj´ıtzaj´ımav´einformace popisuj´ıc´ıtuto dobu a tehdy kladn´yvztah Micro- softu k UNIXu. • UNIX V7 mˇelcca 188 tis´ıcˇr´adekzdrojov´ehok´oduv cca 1100 souborech (zjiˇstˇenopomoc´ı find, wc a awk pˇressoubory se jm´enem *.[cshy]). • pokud v´asv´ıce zaj´ım´ahistorie unixu, pod´ıvejte se na Wikipedii na heslo “unix” a skrz odkazy m´atena dlouho co ˇc´ıst. • V roce 1973 byl UNIX v´ıceuˇzivatelsk´ysyst´em(konta s hesly) s podporou pro multiprocessing s ochranou proces˚ua str´ankov´an´ım.Mˇelsign´aly, roury, hie- rarchick´ysyst´emsoubor˚us mount pointy, souborov´apr´ava (User/group/other r/w/x), hard linky, zaˇr´ızen´ı pˇr´ıstupn´ajako soubory. Kernel byl naps´anv jazyku C a v pamˇeti zab´ıral jeho obraz 26 Kilobyt˚u.Pro pr´acise sou- bory slouˇzilysyst´emov´avol´an´ı open(), close(), read(), write(), seek(),
9 pipe(). K manipulaci s procesy vol´an´ı fork(), exec(), wait(), exit(). Celkem bylo 48 syscall˚u, z nich existuje 35 do dneˇsn´ıdoby.
Divergence UNIXu
• pol. 70. let – uvolˇnov´an´ıUNIXu na univerzity: pˇredevˇs´ım University of California v Berkeley • 1979 – z UNIX/32V (zm´ınˇen´yport na VAX) poskytnut´ehodo Berkeley se vyv´ıj´ı BSD Unix (Berkeley Software Distribution) verze 3.0; posledn´ıverze 4.4 v roce 1993 • 1982 AT&T, vlastn´ıkBTL, m˚uˇzevstoupit na trh poˇc´ıtaˇc˚u (zak´az´anood roku 1956) a pˇr´ıch´az´ıs verz´ı System III (1982) aˇz V.4 (1988) – tzv. SVR4 • vznikaj´ıUNIX International, OSF (Open Software Foundation), X/OPEN, . . . • 1991 – Linus Torvalds zah´ajilv´yvoj OS Linux, verze j´adra1.0 byla dokonˇcenav r. 1994
• UNIX je univerz´aln´ıoperaˇcn´ısyst´emfunguj´ıc´ına ˇsirok´eˇsk´alepoˇc´ıtaˇc˚uod embedded a handheld syst´em˚u(Linux), pˇres osobn´ı poˇc´ıtaˇceaˇzpo velk´e servery a superpoˇc´ıtaˇce. • UNIX V3 = UNIX verze 3, UNIX V.4 = system 5 release 4 atd., tj. UNIX V3 != SVR3. • UNIX System III tedy nen´ıUNIX V3; v t´etodobˇe(pozdn´ı70. l´eta)bylo v BTL nˇekolik skupin, kter´epˇr´ısp´ıvaly do v´yvoje UNIXu. Vx verze byly vyv´ıjeny v r´amci Computer Research Group, dalˇs´ıskupiny byly Unix System Group (USG), Programmer’s WorkBench (PWB). Dalˇs´ı vˇetv´ı UNIXu byl Columbus UNIX t´eˇzv r´amciBT. Na tˇechto r˚uzn´ych verz´ıch je pr´avˇezaloˇzena verze System III. Z´ajemceo v´ıceinformac´ıodkazuji na web. • UNIX se rozˇstˇepilna dvˇehlavn´ı vˇetve: AT&T a BSD, jednotliv´ı v´yrobci pˇrich´azelis vlastn´ımimodifikacemi. Jednotliv´eklony od sebe navz´ajem pˇreb´ıralyvlastnosti. • System V R4 mˇelcca 1.5 milionu ˇr´adekzdrojov´ehok´oduv cca 5700 souborech (zjiˇstˇenopomoc´ı find, wc a awk pˇressoubory se jm´enem *.[cshy]). • Univerzita v Berkeley z´ıskala jako jedna z prvn´ıch licenci UNIXu v roce 1974. Bˇehemnˇekolika let studenti (jedn´ımz nich byl Bill Joy, pozdˇejˇs´ızakladatel firmy Sun Microsystems a autor C-shellu) vytvoˇriliSW bal´ık Berkeley Soft- ware Distribution (BSD) a prod´avali ho v roce 1978 za $50. Tyto poˇc´ateˇcn´ı
10 verze BSD obsahovaly pouze SW a utility (prvn´ı verze: Pascal pˇrekladaˇc, editor ex), ne syst´emani ˇz´adn´ejeho zmˇeny. To pˇriˇsloaˇzs verz´ı3BSD. verze 4BSD vznik´aroku 1980 jiˇzjako projekt financovan´yagenturou DARPA a veden´yBillem Joyem. Trp´ıprobl´emy spojen´ymis nedostateˇcn´ymv´ykonem a vznik´atak vyladˇen´ysyst´em4.1BSD dod´avan´yod roku 1981. • 4.1BSD mˇelob´ytp˚uvodnˇe5BSD, ale pot´e,co AT&T vzneslo n´amitky, ˇzeby si z´akazn´ıcimohli pl´est5BSD se syst´ememSystem V, pˇreˇsloBSD na ˇc´ıslov´an´ı 4.xBSD. Bˇeˇznouvˇec´ıbylo, ˇzeneˇzps´atvlastn´ık´od,v´yvoj´aˇriz Berkeley se radˇejinejdˇr´ıve pod´ıvali kolem, co je jiˇzhotov´e.Tak BSD napˇr´ıkladpˇrevzalo virtu´aln´ıpamˇet’ z Machu a nebo NFS-kompatibiln´ık´odvyvinut´yna jedn´e kanadsk´euniverzitˇe. • v´yrobci hardware dod´avali varianty UNIXu pro sv´epoˇc´ıtaˇcea komercializace tak jeˇstˇezhorˇsilasituaci co t´yˇcediverzifikace totoho syst´emu
• v 80-t´ych letech se proto zaˇcalyobjevovat snahy o standardizaci. Standard ˇr´ık´a,jak m´avypadat syst´emnavenek (pro uˇzivatele, program´atora a spr´avce), nezab´yv´ase implementac´ı.C´ılemje pˇrenositelnostaplikac´ıi uˇzivatel˚u.Vˇsech- ny syst´emy totiˇzz d´alkyvypadaly jako UNIX, ale pˇribliˇzˇs´ımprozkoum´an´ı se liˇsilyv mnoha d˚uleˇzit´ych vlastnostech. System V a BSD se napˇr.liˇsilyv pouˇzit´emfilesyst´emu, s´ıt’ov´earchitektuˇrei v architektuˇrevirtu´aln´ıpamˇeti. • kdyˇzv roce 1987 firmy AT&T a Sun (jehoˇztehdejˇs´ıSunOS byl zaloˇzen´yna BSD) spojily svoje ´usil´ına vyvinut´ıjednoho syst´emu, kter´yby obsahoval to nejlepˇs´ız obou vˇetv´ı,kromˇenadˇsen´ych reakc´ıto vzbudilo i strach u mnoha dalˇs´ıch v´yrobc˚uunixov´ych syst´em˚u,kteˇr´ı se b´ali,ˇzeby to pro obˇefirmy znamenalo obrovskou komerˇcn´ıv´yhodu. Vznik´aproto Open Software Foun- dation (nezamˇeˇnovat za FSF), a zakl´adaj´ıc´ımiˇcleny byly mimo jin´efirmy Hewlett-Packard, IBM a Digital. Z toho vzeˇsl´ysyst´emOSF/1 ale nebyl pˇr´ıliˇs ´uspˇeˇsn´y,a dod´aval ho pouze Digital, kter´yho pˇrejmenoval na Digital UNIX. Zaj´ımavost´ıje, ˇze syst´emje postaven´yna mikroj´adruMach. Po akvizici Digi- talu Compaqem byl syst´empˇrejmenov´anna Tru64 a s t´ımto jm´enemje d´ale podporov´anfirmou Hewlett-Packard, kter´ase v roce 2002 s Compaqem spo- jila. Mezit´ımfirmy AT&T a Sun kontrovaly zaloˇzen´ımUNIX International. Toto obdob´ıpˇrelomu 80-t´ych a 90-t´ych let se naz´yv´a Unix Wars – boj o to, co bude “standardn´ımunixem”. • OSF a UI se staly velk´ymirivaly, ale velmi rychle se stˇretlys neˇcekan´ym protivn´ıkem - s firmou Microsoft. • (1992) 386BSD zaloˇzen´e na Networking Release 2 ; Bill Jolitz vytvoˇril 6 chybˇej´ıc´ıch soubor˚ua dal tak dohromady funkˇcn´ıBSD syst´empro i386. Tento syst´emse stal z´aklademsyst´em˚u NetBSD a FreeBSD (a dalˇs´ıch, z tˇechto dvou syst´em˚uvych´azej´ıc´ıch).
• (1995) 4.4BSD-Lite Release 2, po kter´en´asledujerozpuˇstˇen´ıCSRG, kter´a skoro 20 let pilotovala v´yvoj BSD vˇetve. V´ıce jiˇzzm´ınˇen´akapitola o BSD Unixu.
11 Souˇcasn´eUNIXy
Hlavn´ıkomerˇcn´ıunixov´esyst´emy: • Sun Microsystems: SunOS (nen´ıjiˇzd´alevyv´ıjen), Solaris • Apple: macOS (dˇr´ıve Mac OS X) • SGI: IRIX (nen´ıjiˇzd´alevyv´ıjen) • IBM: AIX • HP: HP-UX, Tru64 UNIX (Compaq) • SCO: SCO Unix • Xinuos (kdysi Novell): UNIXware Open source: • FreeBSD, NetBSD, OpenBSD • Linux distribuce
• Striktnˇetechnicky vzato se jako UNIX m˚uˇzeoznaˇcovat pouze syst´em,kter´y proˇselcertifikac´ıSingle Unix Specification. Z v´yˇseuveden´ehoseznamu by to byly 4 operaˇcn´ısyst´emy, kter´ebyly registrov´any jako UNIX 03 na r˚uzn´ych ar- chitektur´ach (http://www.opengroup.org/openbrand/register/). Ostatn´ısys- t´emy, kter´enebyly certifikov´any, se oznaˇcuj´ıjako Unix-like, aˇckoliv v mnoha pˇr´ıpadech splˇnuj´ıvˇetˇsin˚upoˇzadavk˚ustandardu. Bˇeˇznˇese nicm´enˇepouˇz´ıv´a oznaˇcen´ıUnix pro obˇedvˇeskupiny. • kdyˇzjsem cca v roce 1998 projel nmapem vˇsechny DNS root servery, abych zjistil na kter´ych syst´emech bˇeˇz´ı,bylo 80% z nich na SunOS/Solaris. IRIX je zase syst´em,kter´ypo mnoho let ovl´adaltelevizn´ı/filmov´ypr˚umysl (napˇr. Pixar studio kde na IRIXu vznikly filmy jako A Bug’s Life, Toy Story a dalˇs´ı). A na AIX napˇr´ıkladbˇeˇzel Deep Blue, paraleln´ısuperpoˇc´ıtaˇc,kter´yv roce 1997 porazil v ˇsestifascinuj´ıc´ıch z´apasech 3.5 ku 2.5 ´uˇraduj´ıc´ıhovelmistra ˇsachu Garriho Kasparova. Jin´ymislovy – kaˇzd´ysyst´emm´asvoje ´uspˇechy. • jak jiˇzbylo zm´ınˇeno,Tru64 UNIX vych´az´ız OSF/1 firmy DEC. Ta pˇredt´ım dod´avala Ultrix, zaloˇzen´yna BSD unixu.
• OpenSolaris byl projekt vznikl´yv ˇcervnu 2005 a byl zaloˇzenna podmnoˇzinˇe zdrojov´ych text˚uv´yvojov´everze Solarisu (kernel, knihovny, pˇr´ıkazy). Distri- buce vzeˇsl´ez komunity jsou napˇr´ıkladLiveCD BeleniX, SchilliX a Nexenta. Pˇrestoˇzeprojekt OpenSolaris jiˇzd´alenepokraˇcuje,existuje open source fork Illumos a na nˇemzaloˇzen´edistribuce SmartOS a OpenIndiana.
• pozor na to, ˇzeLinux je pouze j´adro,ne syst´em,na rozd´ıl tˇrebaod Fre- eBSD. Illumos je nˇecomezi t´ım,j´adro+ drivery, z´akladn´ıpˇr´ıkazy a knihovny,
12 a v bin´arn´ı podobˇeto m´anˇecopˇres 100MB. V obou pˇr´ıpadech je tedy spr´avn´epouˇz´ıvat spojen´ı “Linux (Illumos) distribuce”, kdyˇzse bav´ıme o cel´emsyst´emu.
• kaˇzd´akomerˇcn´ı varianta vych´azelaz jednoho ze dvou hlavn´ıch syst´em˚u– UNIX V nebo BSD, a pˇrid´avala si sv´evlastnosti. D´ıkymnoha verz´ımUNIXu tak vznik´avelk´ypoˇcetr˚uzn´ych standard˚u(strana 14). Nakonec se vˇetˇsina v´yrobc˚ushodla na nˇekolika z´akladn´ıch.
• graf zn´azorˇnuj´ıc´ıhistorii unixov´ych syst´em˚ua z´avislostimezi nimi na 19-ti A4 listech ve form´atuPS/PDF je k nalezen´ına http://www.levenez.com/unix/
13 Standardy UNIXu
• SVID (System V Interface Definition) – ,,fialov´akniha”, kterou AT&T vydala poprv´ev roce 1985 – dnes ve verzi SVID3 (odpov´ıd´aSVR4) • POSIX (Portable Operating System based on UNIX) – s´eriestandard˚uorganizace IEEE znaˇcen´aP1003.xx, postupnˇeje pˇrej´ım´avrcholov´ynadn´arodn´ıorg´anISO • XPG (X/Open Portability Guide) – doporuˇcen´ıkonsorcia X/Open, kter´ebylo zaloˇzenov r. 1984 pˇredn´ımiv´yrobci platforem typu UNIX • Single UNIX Specification – standard organizace The Open Group, vznikl´ev roce 1996 slouˇcen´ımX/Open a OSF – dnes Version 4 (SUSv4) – splnˇen´ıje nutnou podm´ınkou pro uˇzit´ıobchodn´ıhon´azvuUNIX
• z´akladn´ıinformace je, ˇzeoblast standard˚ut´ykaj´ıc´ıse unixov´ych syst´em˚uje vˇecznaˇcnˇesloˇzit´aa na prvn´ıpohled velmi nepˇrehledn´a. • AT&T dovolila v´yrobc˚umnaz´yvat svoji komerˇcn´ıUNIX variantu “System V” pouze pokud splˇnovala podm´ınkystandardu SVID. AT&T tak´epublikovala System V Verification Suite (SVVS), kter´eovˇeˇrilo,zda dan´ysyst´emodpov´ıd´a standardu. • POSIX (Portable Operating System Interface) je standardizaˇcn´ısnaha orga- nizace IEEE (Institute of Electrical and Electronics Engineers). • SUSv4 je spoleˇcn´ystandard The Open Group, IEEE (Std. 1003.1, 2008 Edi- tion) a ISO (ISO/IEC 9945-2008). • Pro certifikaci operaˇcn´ıhosyst´emu na Single Unix Specification je nutn´eaby syst´em(na dan´earchitektuˇre, napˇr.64-bit x86) proˇselsadou test˚u.V´ysledky test˚ujsou pak vyhodnoceny. Testy samotn´ejsou sdruˇzeny do tzv. test suites, coˇzjsou sady automatick´ych test˚u,kter´eprojdou syst´ema zjist´ıjestli splˇnuje rozhran´ıdan´enormou. Pro SUSv3 je takov´ych test suites cca 10. • Rozhran´ıspecifikovan´enormou POSIX.1-2008 se dˇel´ına 4 z´akladn´ıskupiny: XSH (System Interfaces), XCU (Shell and Utilities), XBD (Base definitions). Z nich je co do poˇcturozhran´ınejobs´ahlejˇs´ıXSH, kter´apopisuje v´ıceneˇz 1000 rozhran´ı. • Skupiny rozhran´ıPOSIXu spolu se skupinou Xcurses, kter´aje souˇc´ast´ıSingle Unix Specification (ale nikoliv souˇc´astPOSIX b´azev normˇeIEEE Std 1003.1- 2001) zahrnuj´ıcelkem 1742 rozhran´ı,kter´etvoˇr´ıSingle Unix Specification
14 (2003). Tabulky rozhran´ı SUS je moˇzn´ez´ıskat zde: http://www.unix.org/ version3/inttables.pdf • komerˇcn´ı UNIXy vˇetˇsinousleduj´ı Single UNIX Specification, splnˇen´ı t´eto normy je pr´avˇepodm´ınkou pro uˇzit´ın´azvuUNIX (znaˇcka UNIX 98 odpov´ıd´a SUSv2, znaˇcka UNIX 03 odpov´ıd´aSUSv3, SUSv4 je UNIX V7 - nepl´ests historick´ymV7 UNIX). Je postavena na b´aziPOSIXu. My se budeme drˇzet SUSv4. Popis datov´ych struktur a algoritm˚uj´adrav tomto materi´alubude vˇetˇsinouvych´azet ze System V Rel. 4.
• na Solarisu je obs´ahl´amanu´alov´astr´anka standards(5), kde m˚uˇzetena jed- nom m´ıstˇenal´eztmnoho informac´ıt´ykaj´ıc´ıse standard˚u.Jednotliv´epˇr´ıkazy splˇnuj´ıc´ıdanou normu jsou nav´ıcum´ıstˇeny do vyhrazen´ych adres´aˇr˚u.Napˇr. program tr je v adres´aˇr´ıch /usr/xpg4/bin/ a /usr/xpg6/bin/, v kaˇzd´emje verze pˇr´ıkazu splˇnuj´ıc´ıdanou normu. Na pˇrep´ınaˇcea chov´an´ıdan´enormou se pak lze spolehnout napˇr.pˇripsan´ıshellov´ych skript˚u.
• opˇetna Solarisu, pod´ıvejte se na hlaviˇckov´ysoubor /usr/include/sys/fea- ture tests.h
POSIX
• tvrzen´ı“tento syst´emje POSIX kompatibiln´ı”ned´av´aˇz´adnou konkr´etn´ıinformaci – asi podporuje POSIX1990 a moˇzn´ai nˇecodalˇs´ıho (co?) • dotyˇcn´ybud’ nev´ıco je POSIX nebo si mysl´ı,ˇzeto nev´ıtevy • jedin´arozumn´areakce je ot´azka “jak´yPOSIX?” • POSIX je rodina standard˚u • prvn´ımdokumentem je IEEE Std POSIX1003.1-1988, pozdˇeji po vzniku dalˇs´ıch rozˇs´ıˇren´ıneform´alnˇeodkazovan´yjako POSIX.1 • posledn´ıverze POSIX.1 je IEEE Std 1003.1, 2004 Edition – obsahuje v sobˇejiˇzi to, co dˇr´ıve definoval POSIX.2 (Shell and Utilities) a r˚uzn´a,dˇr´ıve samostatn´arozˇs´ıˇren´ı
• prvn´ımdokumentem je IEEE Std POSIX1003.1-1988, dˇr´ıve oznaˇcovan´ypros- tˇejako POSIX, pak odkazovan´yjako POSIX.1, protoˇzePOSIXem se nyn´ı m´ın´ı sada vz´ajemnˇesouvisej´ıc´ıch standard˚u. POSIX.1 v t´edobˇeobsaho- val programovac´ı API, tj. pr´aces procesy, sign´aly, soubory, ˇcasovaˇciatd. S mal´ymizmˇenamibyl pˇrevzatorganizac´ıISO (ISO 9945-1:1990 ), a je ozna- ˇcovan´yi jako POSIX1990. IEEE oznaˇcen´ıje IEEE Std POSIX1003.1-1990. Tento standard byl s´amo sobˇevelk´y´uspˇech, ale st´alejeˇstˇenespojoval t´abory
15 System V a BSD, protoˇzev sobˇenapˇr´ıkladnezahrnoval BSD sockety nebo IPC (semafory, zpr´avy, sd´ılen´apamˇet’) ze System V. Souˇc´ast´ıstandardu je i “POSIX conformance test suite (PCTS)”, kter´yje volnˇek dispozici. • oznaˇcen´ıPOSIX vymyslel Richard Stallman, tedy ˇclovˇek,kter´yv roce 1983 zaloˇzilGNU projekt. • d˚uleˇzit´aroˇzˇs´ıˇren´ık IEEE Std 1003.1-1990 (jsou souˇc´ast´ıIEEE Std 1003.1, 2004 Edition): – IEEE Std 1003.1b-1993 Realtime Extension, neform´alnˇezn´am´yjako POSIX.4, protoˇzeto bylo jeho p˚uvodn´ı oznaˇcen´ı pˇredpˇreˇc´ıslov´an´ım; j´abudu toto rozˇs´ıˇren´ı nˇekdytak´enaz´yvat POSIX.4. Vˇetˇsinatohoto rozˇs´ıˇren´ıje nepovinn´a,takˇzetvrzen´ı“syst´empodporuje POSIX.1b” m´a jeˇstˇehorˇs´ıvypov´ıdac´ıhodnotu neˇz“syst´emje POSIX kompatibiln´ı”,a to prakticky nulovou. Jedin´apovinn´aˇc´astPOSIX.4 je mal´edoplnˇen´ık sign´al˚umoproti POSIX1990. Je proto nutn´evˇzdyuv´est, co z POSIX.4 je implementov´ano– napˇr.sd´ılen´apamˇet’, semafory, real-time sign´aly, zamyk´an´ıpamˇeti,asynchronn´ıI/O, ˇcasovaˇceatd. – IEEE Std 1003.1c-1995 Threads, viz strana 213. – IEEE Std 1003.1d-1999 Additional Realtime Extensions – IEEE Std 1003.1j-2000 Advanced Realtime Extensions, viz strana 233. – ... • standardy POSIX je moˇzn´enal´eztna http://www.open-std.org/. HTML verze je volnˇek prohl´ıˇzen´ı,za PDF verzi se plat´ı.
Jazyk C
• t´emˇeˇrcel´yUNIX je napsan´yv C, pouze nejniˇzˇs´ıstrojovˇe z´avisl´aˇc´astv assembleru ⇒ pomˇernˇesnadn´apˇrenositelnost • navrhl Dennis Ritchie z Bell Laboratories v roce 1972. • n´asledn´ıkjazyka B od Kena Thomsona z Bell Laboratories. • vytvoˇrenjako prostˇredekpro pˇrenosOS UNIX na jin´epoˇc´ıtaˇce – siln´avazba na UNIX. • varianty jazyka: – p˚uvodn´ıK&R C – standard ANSI/ISO C • ´uspˇech jazyka C daleko pˇres´ahl´uspˇech samotn´eho UNIXu
16 • CPL ⇒ BCPL ⇒ B (Thompson, interpret) ⇒ C • K&R C – jazyk C tak, jak je popsan´yv klasick´eknize Brian W. Kernighan, Dennis M. Ritchie: The C Programming Language (Prentice-Hall, 1978). • v roce 1983 ANSI (American National Standards Institute) zformoval v´ybor pro vytvoˇren´ıC standardu. Po dlouh´ema pracn´emprocesu byl v roce 1989 standard koneˇcnˇehotov, a je zn´am´ynejˇcastˇejijako “ANSI C”, pˇr´ıpadnˇejako C89 (napˇr´ıkladpˇrekladaˇcpro tuto normu se v Sun Studiu jmenuje c89, jelikoˇz i to samotn´ejm´enoprogramu mus´ıb´ytpodle normy). Druh´evyd´an´ıK&R knihy (1988) je jiˇzupraven´epr´avˇepro nadch´azej´ıc´ıANSI C. V roce 1990 bylo ANSI C adoptov´ano organizac´ıISO jako ISO/IEC 9899:1990; tento C standard tak m˚uˇzeb´ytnˇekdyoznaˇcov´ani jako C90. • se C standardem se pak nˇejakou dobu neh´ybalo,aˇzna konci 90-t´ych let proˇsel dalˇs´ıreviz´ıv r´amciISO a vznik´aISO 9899:1999, ˇcastˇejioznaˇcovan´yjako C99. V roce 2000 pak naopak tento standard pˇrevzalANSI. • rozd´ılymezi C89 a C99 jsou mimo jin´ezahrnut´ıinline funkc´ı,definic´ıpro- mˇenn´ych napˇr´ıkladi do for konstrukce, jednoˇr´adkov´ych koment´aˇr˚upomoc´ı //, nov´ych funkc´ıjako snprintf apod. • specifikaci C standardu a mnoho dalˇs´ıch otevˇren´ych standard˚uje moˇzn´e nal´eztna http://www.open-std.org/.
Form´aty dat
• poˇrad´ıbajt˚u– z´avis´ına architektuˇrepoˇc´ıtaˇce big endian: 0x11223344 = 11 22 33 44 – addr + 0 1 2 3
little endian: 0x11223344 = 44 33 22 11 – addr + 0 1 2 3 • ˇr´adkytextov´ych soubor˚ukonˇc´ıv UNIXu znakem LF (nikoliv CRLF). Vol´an´ı putc(’\n’) tedy p´ıˇsepouze jeden znak. • big endian – SPARC, MIPS, s´ıt’ov´epoˇrad´ıbajt˚u • little endian – Intel
17 • velk´ypozor na v´ystupy program˚utypu hexdump, kter´edefaultnˇevypisuj´ısou- bor v 16-ti bitov´ych ˇc´ıslech, coˇzsv´ad´ıvidˇetsoubor jinak, neˇzjak je opravdu zapsan´yna disku; viz pˇr´ıklad(i386, FreeBSD). Prvn´ıˇc´ıslov souboru je znak ’i’, kter´yale reprezentuje niˇzˇs´ıch 8 bit˚u16-ti bitov´ehoˇc´ısla, takˇzepokud vyp´ıˇsemeprvn´ı2 bajty jako short integer, mus´ıb´ytreprezentace znaku ’i’ (tj. ˇc´ıslo69) aˇzza 6a. Obdobnˇepro ’kl’.
$ echo -n ijkl > test $ hexdump test 0000000 6a69 6c6b 0000004
je samozˇrejmˇemoˇzn´epouˇz´ıtjin´yform´atv´ystupu:
$ hexdump -C test 00000000 69 6a 6b 6c 00000004
• UNIX norma pˇr´ıkaz hexdump nem´a,ale definuje od (octal dump), takˇzezde je jeho hexdumpu ekvivalentn´ıform´atv´ypisuna SPARCu (Solaris); vˇsimnˇete si zmˇeny oproti v´ypisuna i386 !
$ od -tx2 test 0000000 696a 6b6c 0000004
Deklarace a definice funkce
• K&R – deklarace n´avratov´y_typindentifik´ator(); – definice n´avratov´y_typindentifik´ator(par[,par...]) typ par;... { /* tˇelofunkce */ }
• ANSI – deklarace n´avratov´y_typindentifik´ator(typpar [,typ par...]); – definice n´avratov´y_typindentifik´ator(typpar [,typ par...]) { /* tˇelofunkce */ }
18 • pouˇz´ıvejte pouze novˇejˇs´ı(ANSI) typ deklarac´ıa vˇzdydeklarujte prototypy funkc´ı,tj. inkludujte hlaviˇckov´esoubory. V´yjimkou m˚uˇzeasi jen to, pokud budete pracovat s k´odem,kter´ybyl napsan´ypodle K&R.
• r˚uzn´ymiz´apisydeklarac´ı se dost´av´amerovnou i k r˚uzn´ymstyl˚umpsan´ı zdrojov´ych text˚u.Nˇekter´e syst´emy to pˇr´ıliˇs neˇreˇs´ı (Linux), jin´e syst´emy maj´ıvelmi striktn´ıpravidla pro psan´ızdrojov´ych text˚u(napˇr.Solaris, viz on-line C Style and Coding Standards for SunOS: http://mff.devnull.cz/ pvu/common/cstyle.ms.pdf). Snad kaˇzd´yUNIXov´ysyst´emm´aprogram in- dent(1), kter´yv´ampomoc´ıpˇrep´ınaˇc˚upˇreform´atujejak´ykoli C zdrojov´ytext do poˇzadovan´ehov´ystupu.
C style
• vˇeczd´anlivˇepodˇradn´a,pˇritomextr´emnˇed˚uleˇzit´a– ´uprava zdrojov´ych k´od˚uprogramu • mnoho zp˚usob˚ujak ano: int main(void) { char c; int i = 0;
printf("%d\n", i); return (0); }
• u C stylu je nejd˚uleˇzitˇejˇs´ı to, aby byl konzistentn´ı. Pokud skupina pro- gram´ator˚upracuje na jednom projektu, nen´ızas aˇztak d˚uleˇzit´e,na jak´em stylu se dohodnou (pokud je alespoˇntrochu rozumn´y),ale aby se dohodli. Jednotn´ya dobˇrezvolen´ystyl ˇsetˇr´ıˇcasa br´an´ızbyteˇcn´ymchyb´am.
19 C style (cont.)
• mnoho zp˚usob˚ujak NE (tzv. assembler styl): int main(void) { int i = 0; char c; printf("%d\n", i); return (0); } • nebo (schizofrenn´ıstyl): int main(void) { int i = 0; char c; if (1) printf("%d\n", i);i=2; return (0); }
• pamatujte na to, ˇzedobr´ystyl zdrojov´ych k´od˚uje i vizitkou program´atora. Kdyˇzse v r´amcipˇrij´ımac´ıch pohovor˚uodevzd´avaj´ıi uk´azkov´ek´ody, tak hlavn´ı d˚uvod pˇrekvapivˇenen´ıten, aby se zjistilo, ˇzev´amdan´yprogram funguje. Uprava´ samotn´ehozdrojov´ehotextu je jedn´ımz kriteri´ı,protoˇzeto pˇrenesenˇe m˚uˇzesvˇedˇciti o dalˇs´ıch skuteˇcnostech – nˇekdonapˇr.bude odhadovat, ˇze pokud p´ıˇseteneˇcist´ya neupraven´yk´od,tak jste moˇzn´ajeˇstˇenepracovali na nˇeˇcemopravdu sloˇzit´emˇcinˇeˇcem zahrnuj´ıc´ımspolupr´aci s v´ıceprogram´atory, protoˇzev tom pˇr´ıpadˇeje rozumnˇeˇcist´yk´odjednou z podm´ınek´uspˇechu a jednou ze zkuˇsenost´ı,kter´ez takov´espolupr´acevych´azej´ı.Toto je samozˇrejmˇe zˇc´astisubjektivn´ın´azor,ale ˇcist´ymk´odemnic nezkaz´ıte,minim´alnˇenekaz´ıte oˇcisv´ymcviˇc´ıc´ım.
• informace o C stylu pouˇz´ıvan´empro zdrojov´ek´odySolarisu, vˇcetnˇeskriptu, kter´yv´amzdroj´akyzkontroluje a upozorn´ına pˇr´ıpadn´enedostatky, je moˇzn´e nal´eztna http://mff.devnull.cz/pvu/common/cstyle.html. Pokud budete do- drˇzovat tento styl pˇripsan´ızkouˇskov´ych pˇr´ıklad˚u,uˇsetˇr´ıtemi t´ımpr´acipˇri vyhodnocov´an´ı.Obecnˇeje dobr´e,abyste si zkusili, co je to ps´atk´odpodle nˇejak´ehokonkr´etn´ıhostylu, a ten pro dan´y,,projekt” dodrˇzet. • bohuˇzelani v´yˇseuveden´yskript nen´ı vˇsemocn´y.Je zaloˇzen´yna kontrole pomoc´ıregul´arn´ıch v´yraz˚u,takˇzetˇrebaten assembler styl ze slajdu projde bez chyby, protoˇzebez skuteˇcn´eanal´yzyk´odunen´ımoˇzn´e(?) kontrolovat spr´avn´eodsazov´an´ı.Vˇseostatn´ıje na nˇem,dle cstyle skriptu, korektn´ı.
20 Utility
cc, c99∗, gcc† pˇrekladaˇcC CC, g++† pˇrekladaˇcC++ ld spojovac´ıprogram (linker) ldd pro zjistˇen´ız´avislost´ıdynamick´ehoobjektu cxref ∗ kˇr´ıˇzov´eodkazy ve zdrojov´ych textech v C sccs∗, rcs,cvs spr´ava verz´ızdrojov´ehok´odu make∗ ˇr´ızen´ıpˇrekladupodle z´avislost´ı ar∗ spr´ava knihoven objektov´ych modul˚u dbx, gdb† debuggery prof, gprof † profilery ∗ SUSv3 † GNU
SUSv3
• standardn´ıpˇr´ıkaz vol´an´ıkompil´atorua linkeru C je c99 (podle ISO normy pro C z roku 1999)
• cb (C program beautifier) nen´ı • pro spr´avuverz´ıje sccs • debuggery a profilery nejsou
21 Konvence pro jm´enasoubor˚u
*.c jm´enazdrojov´ych soubor˚uprogram˚uv C *.cc jm´enazdrojov´ych soubor˚uprogram˚uv C++ *.h jm´enahlaviˇckov´ych soubor˚u(header˚u) *.o pˇreloˇzen´emoduly (object files) a.out jm´enospustiteln´ehosouboru (v´ysledek´uspˇeˇsn´ekompilace)
/usr/include koˇrenstromu syst´emov´ych header˚u /usr/lib/lib*.a statick´eknihovny objektov´ych modul˚u /usr/lib/lib*.so um´ıstˇen´ıdynamick´ych sd´ılen´ych knihoven objektov´ych modul˚u
statick´eknihovny – pˇri linkov´an´ı se k´odfunkc´ı pouˇzit´ych z knihovny stane souˇc´ast´ıv´ysledn´ehospustiteln´ehoprogramu. Dnes se uˇzmoc nepouˇz´ıv´a. sd´ılen´eknihovny – program obsahuje pouze odkaz na knihovnu, pˇrispuˇstˇen´ıpro- gramu se potˇrebn´eknihovny naˇctoudo pamˇetize soubor˚u *.so a pˇrilinkuj´ı.
• dnes se vˇetˇsinou pouˇz´ıvaj´ısd´ılen´eknihovny, protoˇzenezab´ıraj´ıtolik diskov´eho prostoru (knihovna je na disku jednou, nen´ısouˇc´ast´ıkaˇzd´ehospustiteln´eho souboru) a snadnˇejise upgraduj´ı(staˇc´ıinstalovat novou verzi knihovny, nen´ı tˇreba pˇrelinkovat programy). Posledn´ı verze Solarisu uˇznapˇr´ıklad v˚ubec neobsahuje libc.a, d´ıkyˇcemuˇzjiˇzprogram´atornem˚uˇzevytvoˇritstatickou bin´arku,aniˇzby mˇeldostateˇcn´eznalosti syst´emu. • nˇekdyse bez statick´ych knihoven neobejdeme. V nˇekter´ych situac´ıch nen´ı moˇzn´epouˇz´ıtknihovny dynamick´e,spustiteln´esoubory jsou takzvan´e standa- lone binaries a pouˇzit´ınaleznou napˇr´ıkladpˇribootov´an´ıoperaˇcn´ıhosyst´emu.
22 Princip pˇrekladu
zdrojov´emoduly objektov´emoduly program main.c main.o a.out main() { main msg(); msg ?? main } msg util.c util.o msg() { pˇrekladaˇc msg msg puts(); } puts ?? linker puts
syst´emov´a puts puts knihovna
• u sloˇzitˇejˇs´ıch program˚ub´yv´azvykem rozdˇelitzdrojov´ytext programu do nˇekolika modul˚u,kter´eobsahuj´ıpˇr´ıbuzn´efunkce a tyto moduly se pak mohou pˇrekl´adatzvl´aˇst’ (dokonce kaˇzd´ymodul m˚uˇzeb´ytv jin´emjazyce a pˇrekl´ad´an jin´ympˇrekladaˇcem).V´yhodou je jednak urychlen´ıpˇrekladu(pˇrekl´adaj´ıse vˇzdyjen moduly zmˇenˇen´eod posledn´ıhopˇrekladu)a jednak flexibilita (nˇek- ter´emoduly se mohou pouˇz´ıvat v r˚uzn´ych programech). Pro ˇr´ızen´ıpˇrekladu se obvykle pouˇz´ıv´autilita make. • pˇrekladaˇc jednotliv´ezdrojov´emoduly pˇreloˇz´ıdo tvaru tzv. objektov´ychmo- dul˚u, jeˇzobsahuj´ık´odprogramu (vˇcetnˇevol´an´ılok´aln´ıch funkc´ı),ale nam´ısto vol´an´ıextern´ıch funkc´ıobsahuj´ıjen tabulku jejich jmen.
• po f´azipˇrekladunastupuje spojovac´ıprogram (t´eˇz linker editor nebo loader), kter´yzkompletuje v´ysledn´yprogram vˇcetnˇevyˇreˇsen´ıextern´ıch odkaz˚umezi moduly a syst´emov´ymiknihovnami resp. mezi moduly navz´ajem. • pouˇzit´estatick´eknihovny jsou zkop´ırov´any do spustiteln´ehosouboru. Na sd´ılen´eknihovny jsou ve spustiteln´emsouboru pouze odkazy a linkuje je runtime linker pˇrikaˇzd´emspuˇstˇen´ıprogramu. V´ıceviz dynamick´ylinker na stranˇe 35. • pomoc´ı parametr˚ulinkeru lze urˇcit,zda se budou pouˇz´ıvat statick´enebo dynamick´eknihovny. Zdrojov´yk´odje v obou pˇr´ıpadech stejn´y.Existuje i mechanismus (dlopen, dlsym. . . ), pomoc´ıkter´ehose za bˇehu programu vy- bere sd´ılen´aknihovna a daj´ıse volat jej´ıfunkce. T´ımto zp˚usobem m˚uˇzete tak´ezjistit, zda v syst´emu je pˇr´ıtomnapˇr´ısluˇsn´afunkcionalita a pokud ne, zachovat se podle toho. V´ıcena stranˇe 144.
23 Pˇreklad jednoho modulu (preprocesor)
main.c #include
int puts(char *s); preprocesor { mydef.h puts("Ahoj"); #define MSG ”Ahoj” } extern int var a;
• preprocesor prov´ad´ıexpanzi maker, ˇcten´ıvloˇzen´ych (include) soubor˚ua vy- nech´av´akoment´aˇre.
• v´ystuppreprocesoru lze z´ıskat pomoc´ı cc -E pˇr´ıpadnˇepˇr´ımozavol´an´ım cpp, nemus´ıto b´yt ale vˇzdytot´eˇzprotoˇzenˇekter´epˇrekladaˇcemaj´ıpreprocesor integrov´anv sobˇe.Preprocesor m˚uˇzetesamozˇrejmˇepouˇz´ıvat i pro jin´epro- jekty, kter´es pˇreklademzdrojov´ych soubor˚uv jazyce C nemus´ım´ıtv˚ubec nic spoleˇcn´eho. • pouˇzit´ıpreprocesoru se m˚uˇzevelmi hodit v situaci, kdy potˇrebujetezas´ahnout do ciz´ıhok´odu,pln´ehopodm´ıneˇcn´ych vkl´ad´an´ır˚uzn´ych hlaviˇckov´ych sou- bor˚ua r˚uzn´ych definic z´avisl´ych na dan´ych podm´ınk´ach. Pˇrihled´an´ıp˚uvodce chyby v´ampr´avˇem˚uˇzehodnˇepomoci samostatn´ehozpracov´an´ıvstupn´ıho souboru pomoc´ıpreprocesuru, kde probl´emjiˇzvˇetˇsinourozpozn´atesnadno.
• cpp (nebo cc -E v´amdok´aˇzena standardn´ıchybov´yv´ystupzobrazit i cel´y strom vkl´adan´ych soubor˚u,coˇzopˇetpˇripodm´ıneˇcn´ych pˇrekladech m˚uˇzeb´yt velmi uˇziteˇcn´avˇec.Staˇc´ıpro to pouˇz´ıtvolbu -H a pˇresmˇerovat v´ystupdo /dev/null ˇc´ımˇzdostanete pouze hierarchii vkl´adan´ych hlaviˇckov´ych sou- bor˚u.
24 Pˇreklad jednoho modulu (kompil´ator)
main.s main.i .globl main int puts(char *s); .type main, @function main: extern int var a; pushhl %ebp movl %esp, %ebp main() pushl $.LC0 call puts { kompil´ator addl $4, %esp puts("Ahoj"); .L1: } leave ret
• obr´azekv´yˇseje pˇr´ıkladv´ystupupro i386 platformu (32-bit, AT&T syntax). • pˇrekladz C do assembleru
• v´ystupt´etof´azepˇrekladulze z´ıskat pomoc´ı cc -S.
25 Pˇrekladjednoho modulu (assembler)
main.s .globl main .type main, @function main.o main: 457f 464c 0101 0001 pushhl %ebp movl %esp, %ebp 0000 0000 0000 0000 pushl $.LC0 0001 0003 0001 0000 call puts 0000 0000 0000 0000 addl $4, %esp assembler 00ec 0000 0000 0000 .L1: 0034 0000 0000 0028 leave ret
• opˇetpˇr´ıkladv´ystupupro i386 platformu (32-bit). • pˇrekladz assembleru do strojov´ehok´odu
• objektov´ymodul je v´ysledkem pˇr´ıkazu cc -c.
26 Kompil´ator
• vol´an´ı: cc [options ] soubor ... • nejd˚uleˇzitˇejˇs´ıpˇrep´ınaˇce: -o soubor jm´enov´ysledn´ehosouboru -c pouze pˇreklad(nelinkovat) -E pouze preprocesor (nepˇrekl´adat) -l slinkuj s pˇr´ısluˇsnou knihovnou -Ljm´eno pˇridejadres´aˇrpro hled´an´ıknihoven z -l -Olevel nastaven´ı´urovnˇeoptimalizace -g pˇreklads ladic´ımiinformacemi -Djm´eno definuj makro pro preprocesor -Iadres´aˇr um´ıstˇen´ı #include soubor˚u
• -l/-L jsou pˇrep´ınaˇcelinker editoru, tj. kompil´atorpˇr´ısluˇsn´einformace pˇred´a, ale jsou pouˇz´ıv´any tak ˇcasto,ˇzejsou vloˇzeny i do tohoto slajdu. • kompil´atora linker maj´ımnoho dalˇs´ıch pˇrep´ınaˇc˚uovlivˇnuj´ıc´ıch generovan´y k´od,vypisov´an´ı varovn´ych hl´aˇsen´ı nebo variantu jazyka (K&R/ANSI). Je tˇrebanastudovat dokumentaci konkr´etn´ıhoproduktu.
27 Pˇreddefinovan´amakra
__FILE__, __LINE__, __DATE__, __TIME__, __cplusplus, apod. jsou standardn´ımakra kompil´atoruC/C++ unix vˇzdydefinov´anov Unixu mips, i386, sparc hardwarov´aarchitektura linux, sgi, sun, bsd klon operaˇcn´ıhosyst´emu _POSIX_SOURCE, _XOPEN_SOURCE pˇrekladpodle pˇr´ısluˇsn´enormy pro pˇrekladpodle urˇcit´enormy by pˇredprvn´ım #include mˇelb´yt ˇr´adeks definic´ın´asleduj´ıc´ıhomakra. Pak naˇctˇete unistd.h.
UNIX 98 #define _XOPEN_SOURCE 500 SUSv3 #define _XOPEN_SOURCE 600 SUSv4 #define _XOPEN_SOURCE 700 POSIX1990 #define _POSIX_SOURCE
28 • funguje to tak, ˇzepomoc´ı konkr´etn´ıch maker definujete co chcete (napˇr. POSIX SOURCE) a podle nastaven´ıjin´ych maker (napˇr. POSIX VERSION) pak zjist´ıte, co jste dostali. Mus´ıte ale vˇzdypo nastaven´ı maker nainkludovat unistd.h a pouˇz´ıtspr´avn´ypˇrekladaˇc. Napˇr´ıkladse pokus´ımepˇreloˇzitpro- gram basic-utils/standards.c , kter´yvyˇzaduje SUSv3, na syst´emu pod- poruj´ıc´ımSUSv3 (Solaris 10), ale pˇrekladaˇcem,kter´ypodporuje pouze SUSv2 (SUSv3 pˇrekladaˇcje c99). Pozor, ˇzedefaultn´ı chov´an´ı vaˇsehopˇrekladaˇce m˚uˇzeb´ytklidnˇepr´avˇeto z c89.
$ cat standards.c #define _XOPEN_SOURCE 600 /* you must #include at least one header !!! */ #include
• zdroj maker pro standard tedy m˚uˇzeb´ytjiˇzna stranˇe 14 zmiˇnovan´yhlaviˇc- kov´ysoubor feature tests.h na Solarisu. • v dokumentaci konkr´etn´ıhokompil´atoruje moˇzn´enaj´ıt,kter´adalˇs´ımakra se pouˇz´ıvaj´ı.Mnoˇzstv´ımaker je definov´anotak´ev syst´emov´ych hlaviˇckov´ych souborech. • POSIX.1 v sobˇezahrnuje ANSI C; tedy C89, ne C99 (o C standardech v´ıce na stranˇe 16).
• co se t´yˇcemaker k jednotliv´ym standard˚um,velmi dobr´aje kapitola 1.5 v [Rochkind]. Viz tak´e basic-tools/suvreq.c .
int main(void) { #ifdef unix printf("yeah\n"); #else printf("grr\n"); #endif return (0); }
• pˇr´ıkladna pouˇzit´ı LINE viz basic-tools/main LINE .c
29 Link editor (linker)
• Vol´an´ı: ld [options ] soubor ... cc [options ] soubor ... • Nejd˚uleˇzitˇejˇs´ıpˇrep´ınaˇce: -o soubor jm´enov´ysledn´ehosouboru (default a.out) -llib linkuj s knihovnou liblib.so nebo liblib.a -Lpath cesta pro knihovny (-llib ) -shared vytvoˇritsd´ılenouknihovnu -non shared vytvoˇritstatick´yprogram
• linker je program, kter´yvezme typicky v´ıceobjekt˚uvygenerovan´ych pˇrekla- daˇcema vytvoˇr´ız nich bin´arn´ıprogram, knihovnu nebo dalˇs´ıobjekt vhodn´y pro dalˇs´ıf´azi linkov´an´ı. • pozor na to, ˇzena r˚uzn´ych syst´emech se nˇekter´epˇrep´ınaˇcemohou liˇsit, napˇr´ıklad ld na Solarisu nezn´apˇrep´ınaˇce -shared a -non shared, je nutn´e pouˇz´ıtjin´e.
• existuje pˇrep´ınaˇc -R, kter´yumoˇzˇnujespecifikovat cestu pro hled´an´ıknihoven za bˇehu (runtime). Tato cesta se m˚uˇzeliˇsitod cesty specifikovan´epˇrep´ınaˇcem -L. • u mal´ych program˚u(v jednom souboru) lze prov´estpˇreklad a linkov´an´ı jedn´ımpˇr´ıkazem cc. U vˇetˇs´ıch program˚uskl´adaj´ıc´ıch se z mnoha zdrojov´ych soubor˚ua knihoven se obvykle oddˇelujepˇreklada linkov´an´ıa cel´yproces je ˇr´ızenutilitou make (strana 31).
30 R´ızen´ıpˇrekladuaˇ linkov´an´ı(make)
• zdrojov´etexty main.c util.h util.c #include "util.h" void msg(); #include "util.h" main() msg() { { msg(); puts(); } } • z´avislosti • soubor Makefile main.c prog : main.o util.o & cc -o prog main.o util.o main.o %& main.o : main.c util.h util.h prog cc -c main.c &% util.o util.o : util.c util.h % cc -c util.c util.c
.
• program je moˇzn´etak´epˇreloˇzita slinkovat jedn´ımvol´an´ımkompil´atoru,nebo definovat postup pˇrekladua linkov´an´ıpomoc´ıshellov´ehoskriptu. D˚uvodem pro pouˇzit´ı make je to, ˇzevyhodnocuje z´avislostimezi soubory a po zmˇenˇe nˇekter´ehozdrojov´ehosouboru pˇrekl´ad´ajenom to, co na nˇemz´avis´ı. Cast´yˇ zp˚usobpˇrekladusoftwaru po aplikov´an´ızmˇenzp˚usobem “make clean; make all” je v situaci, kdy cel´ypˇrekladtrv´aminuty (des´ıtkyminut, hodiny. . . ), trochu nevhodn´y– pr´avˇeproto je d˚uleˇzit´em´ıtdobˇrenapsan´y Makefile. • ˇr´adek“prog : main.o util.o” definuje, ˇzese m´anejprve rekurzivnˇezajistit existence a aktu´alnostsoubor˚u main.o a util.o. Pak se zkontroluje, zda soubor (c´ıl) prog existuje a je aktu´aln´ı(datum posledn´ımodifikace souboru je mladˇs´ıneˇz main.o a util.o). Pokud ano, nedˇel´ase nic. Kdyˇzne, provede se pˇr´ıkaz na n´asleduj´ıc´ımˇr´adku.
• make se spouˇst´ı typicky s parametrem urˇcuj´ıc´ı pˇr´ıˇsluˇsn´yc´ıl (target); pˇri spuˇstˇen´ıbez parametr˚use vezme prvn´ıtarget. To b´yv´a all, coˇzvˇetˇsinou podle unixov´ekonvence pˇreloˇz´ıvˇse,co se pˇreloˇzitm´a.N´asledujepak tˇreba spuˇstˇen´ı make s parametrem install apod. • make je samozˇrejmˇeuniverz´aln´ın´astroj, pouˇziteln´yi jinde neˇzu pˇreklad˚u zdrojov´ych k´od˚u
• pˇr´ıklad: basic-utils/Makefile01 . Pozor na to, ˇze pro nestandardn´ıjm´eno vstupn´ıhosouboru je nutn´epouˇz´ıtpˇrep´ınaˇc -f:“make -f Makefile01”.
31 Syntaxe vstupn´ıhosouboru (make)
• popis z´avislost´ıc´ıle: targets :[files ] • prov´adˇen´epˇr´ıkazy:
• Pozor na to, ˇzeˇr´adeks pˇr´ıkazem zaˇc´ın´atabul´atorem,nikoliv me- zerami. Kaˇzd´ypˇr´ıkazov´yˇr´adekse prov´ad´ısamostatn´ymshellem, pokud je potˇrebaprov´estv´ıceˇr´adk˚upomoc´ıjednoho shellu, mus´ıse vˇsechny aˇzna po- sledn´ıukonˇcitbackslashem (shell je dostane jako jeden ˇr´adek).Viz pˇr´ıklad, ve kter´em dva posledn´ı echo pˇr´ıkazy jsou souˇc´ast´ıjednoho if pˇr´ıkazu, kter´y je spuˇstˇensamostatn´ymshellem. D´alesi vˇsimnˇete,ˇzepokud m´atepˇr´ıkaz na v´ıceˇr´adk˚u,mus´ıtekaˇzd´yˇr´adekukonˇcitzpˇetn´ymlom´ıtkem.
$ cat basic-utils/Makefile02 all: @echo $$$$ @echo $$$$ @if true; then \ echo $$$$; \ echo $$$$; \ fi $ make -f Makefile02 5513 5514 5515 5515
• co se t´yk´apouˇzit´ızpˇetn´eholom´ıtka, tak to funguje jako oddˇelovaˇcslov, a make m´ıstonˇejvloˇz´ımezeru. Pˇr´ıklad: basic-utils/Makefile07 . • zdvojen´ım $ se potlaˇc´ıspeci´aln´ıv´yznamdolaru (viz n´asleduj´ıc´ıslajd)
32 • znak @ na zaˇc´atkuˇr´adkupotlaˇc´ıjeho v´ypis– make jinak standardnˇevypisuje nejdˇr´ıve to, co bude vykon´avat. • vyps´an´ıvˇsech pˇrikaz˚ukter´ebude make prov´adˇetbez toho aby je skuteˇcnˇe provedl lze dos´ahnoutpouˇzit´ımpˇrep´ınaˇce -n. • znak - na zaˇc´atkuˇr´adkuzp˚usob´ıignorov´an´ınenulov´en´avratov´ehodnoty; jinak make vˇzdyv takov´esituaci zahl´as´ıchyby a okamˇzitˇeskonˇc´ı.Pˇr´ıklad: basic-utils/Makefile04 . • test1: false echo "OK"
test2: -false echo "OK"
Makra (make)
• definice makra: name = string • pokraˇcov´an´ıvkl´ad´amezeru • nedefinovan´amakra jsou pr´azdn´a • nez´aleˇz´ına poˇrad´ıdefinic r˚uzn´ych maker • definice na pˇr´ıkazov´eˇr´adce: make target name =string • vyvol´an´ımakra: $name (pouze jednoznakov´e name ), ${name } nebo $(name ) • syst´emov´epromˇenn´ejsou pˇr´ıstupn´ejako makra
• kdyˇzje stejn´emakro definov´anov´ıcekr´at,plat´ıjeho posledn´ıdefinice, viz pˇr´ıklad basic-utils/Makefile03 .
• makra nen´ımoˇzn´edefinovat rekurzivnˇe,viz basic-utils/Makefile05 :
$ cat basic-utils/Makefile05 M=value1 M=$(M) value2 all:
33 echo $(M) $ make -f Makefile05 Variable M is recursive.
• ˇcastose pouˇz´ıvaj´ır˚uzn´erozˇs´ıˇren´everze make (napˇr.GNU, BSD), kter´eum´ı, podm´ınˇen´esekce v Makefile, redefinice promˇenn´ych, apod. • napsat Makefile kter´ybude fungovat najednou pro r˚uzn´everze make nemus´ı b´ytjednoduch´e,proto existuj´ıprojekty jako je napˇr.GNU automake. Pro jed- noduch´ypodm´ıneˇcn´ypˇrekladv z´avislostina syst´emu a kde se daj´ıoˇcek´avat r˚uzn´everze pˇr´ıkazu make, je moˇzn´epouˇz´ıtnapˇr´ıkladn´asleduj´ıc´ık´od,kter´y mi fungoval na vˇsech v nˇemzm´ınˇen´ych syst´emech (znak ‘ je zpˇetn´yapostrof, a ’ je norm´aln´ıapostrof):
CFLAGS=‘x=\‘uname\‘; \ if [ $${x} = FreeBSD ]; then \ echo ’-Wall’; \ elif [ $${x} = SunOS ]; then \ echo ’-v’; \ elif [ $${x} = Linux ]; then \ echo ’-Wall -g’; \ fi‘
all: @echo "$(CFLAGS)"
• v ostatn´ıch situac´ıch je vhodn´e,pˇr´ıpadnˇenezbytn´epouˇz´ıt programy typu autoconf nebo automake. Nˇekter´e make implementace maj´ı pˇr´ımo direk- tivy pro podm´ınˇen´ezpracov´an´ıvstupn´ıhosouboru, napˇr´ıkladmake na BSD. Pˇr´ıklad: basic-utils/Makefile08.bsd . • pˇrep´ınaˇcem -e m˚uˇzeme make donutit, aby ignoroval nastaven´ıpromˇenn´ych ve vstupn´ımsouboru v pˇr´ıpadˇe,ˇzeje definov´anapromˇenn´aprostˇred´ıstejn´eho jm´ena.Norm´alnˇe make pˇreb´ır´aaktu´aln´ınastaven´ıpromˇenn´ych prostˇred´ıjen v pˇr´ıpadˇe,ˇzedan´epromˇenn´enejsou nastaven´eve vstupn´ımsouboru. Pˇr´ıklad: basic-utils/Makefile06 . • make je velmi siln´yn´astroj, staˇc´ıse pod´ıvat do syst´emov´ych Makefile sou- bor˚ujak´ehokoli unix-like syst´emu (najdˇetesi na Wikipedii, co to znamen´a “unix-like”, pokud to nev´ıte).Typickou spoleˇcnouvlastnost´ıje to, ˇzeneexis- tuje dokumentace, jak je dan´ymakefile framework postaven.
34 Dynamick´ylinker (loader)
• pˇrekladvyˇzadujevˇsechny potˇrebn´edynamick´eknihovny pro kontrolu dosaˇzitelnostipouˇzit´ych symbol˚u • sestaven´ıkompletn´ıhoprogramu v pamˇetise ale provede aˇzpˇrispuˇstˇen´ı. To je ´ukol pro dynamick´ylinker (run-time linker, loader) • seznam dynamick´ych knihoven zjist´ıze sekce .dynamic • syst´emm´anastaveno nˇekolik cest, kde se automaticky tyto knihovny hledaj´ı • v sekci .dynamic je moˇzn´edalˇs´ıcesty ke knihovn´ampˇridat pomoc´ıtag˚u RUNPATH/RPATH • nalezen´eknihovny se pˇripoj´ıdo pamˇet’ov´ehoprocesu pomoc´ı vol´an´ı mmap() (bude pozdˇeji)
• proces spuˇstˇen´ıdynamicky slinkovan´ehoprogramu prob´ıh´atakto:
– kernel ve vol´an´ı exec namapuje program do pamˇetia zjist´ı,jak´ydyna- mick´ylinker se m´apouˇz´ıt(viz d´ale) – kernel namapuje linker do pamˇet’ov´ehoprostoru spouˇstˇen´eho programu a pak linkeru pˇred´akontrolu. Linker je program s´amo sobˇe– na Solarisu je ho moˇzn´enorm´alnˇespustit (m´atedy funkci main) a jako parametr mu d´atjm´enoprogramu. Moˇznostspouˇstˇetdynamick´ylinker z pˇr´ıkazov´eho ˇr´adkuje ale hlavnˇepro experimentovan´ıs linkerem pˇrijeho v´yvoji. – linker z hlaviˇckyprogramu zjist´ı, jak´edynamick´eknihovny program pouˇz´ıv´a,namapuje je do pamˇetia zavol´ajejich inicializaˇcn´ıfunkce, po- kud existuj´ı.Mapuj´ıse vˇsechny nalezen´ez´avislostikter´enejsou nasta- ven´ejako lazy (strana 144), rekurz´ıvnˇeprohled´av´an´ımdo ˇs´ıˇrky. V tomto poˇrad´ıse pak tak´eobjekty prohled´avaj´ıpˇrihled´an´ıjednotliv´ych sym- bol˚u. – linker programu pˇred´aˇr´ızen´ı(tj. zavol´afunkci main) – proces m˚uˇzei za bˇehu d´alevyuˇz´ıvat dynamick´ylinker pomoc´ıvol´an´ı dlopen a spol.; k tomu se dostaneme na stranˇe 144
• je potˇrebasi uvˇedomit,ˇzedynamick´ylinker zde nepracuje jako samostatn´y proces pˇrestoˇzem´asvoji vlastn´ı main funkci, jeho k´odse pouˇz´ıv´av r´amci pamˇet’ov´ehoprostoru procesu; program, linker a knihovny dohromady tvoˇr´ıjeden proces.
35 • n´asleduj´ıc´ıpˇr´ıkazy a pˇr´ıkladyse t´ykaj´ıSolarisu. Pokud to nebude fun- govat na jin´ych syst´emech, tak maj´ıekvivaletn´ın´astroje s podobnou funkci- onalitou.
– seznam sekc´ıse zjist´ıpomoc´ı elfdump -c (GNU m´apˇr´ıkazy objdump a readelf). O programov´ych sekc´ıch bude v´ıcena stranˇe 133. – to, jak´ydynamick´ylinker se pouˇzije,kernel zjist´ı ze sekce .interp, viz ”elfdump -i” a “ld -I”. To znamen´a,ˇzesi m˚uˇzetenapsat vlastn´ı linker a pomoc´ı -I pro ld ho pak nastavit jako dynamick´ylinker pro v´aˇsprogram. – dynamick´asekce se vyp´ıˇsepomoc´ı elfdump -d, dynamick´eknihovny jsou oznaˇcen´etagem NEEDED – z´avislostina dynamick´ych knihovn´ach je moˇzn´epohodlnˇezjistit pomoc´ı pˇr´ıkazu ldd (Solaris, Linux, BSD), kter´yzjist´ıkonkr´etn´ıcesty ke kni- hovn´am.Tento pˇr´ıkaz ˇreˇs´ız´avislostirekurz´ıvnˇea uvid´ıtetedy i nepˇr´ım´e z´avislosti- tj. takov´eknihovny, kter´ejsou pouˇzit´eknihovnami, kter´e pˇr´ısluˇsn´yprogram pouˇz´ıv´apˇr´ımo.Zjistit co je pˇresnˇez´avisl´ena ˇcemje moˇzn´epomoc´ıvolby -v. Na OS X je ekvivalentem ldd pˇr´ıkaz otool -L. – jak´eknihovny byly pˇrispuˇstˇen´ınakonec pouˇzity m˚uˇzeb´ytjin´eneˇzco uk´aˇzepˇr´ıkaz ldd, a to tˇrebad´ıkymechanismu LD PRELOAD. Na Solarisu proto existuje pˇr´ıkaz pldd, kter´ypomoc´ıˇc´ıslaprocesu uk´aˇzez´avislosti konkr´etn´ıhoprocesu. Pˇr´ıkladna LD PRELOAD: pouˇzijtejiˇzzm´ınˇen´y Ma- kefile01, a pˇreloˇzte basic-utils/preload.c takto: “cc -shared -o libpreload.so preload.c”. Pak spust’te program, kter´yzachyt´ı syst´emov´evol´an´ı close:“LD_PRELOAD=./libpreload.so ./a.out”. – vˇetˇsinu zde uveden´ych informac´ınaleznete v manu´alov´estr´ancepro dy- namick´ylinker v Solarisu, ld.so.1(1), a v´ıcepak v Linkers and Lib- raries Guide na docs.oracle.com. Na FreeBSD se dynamick´ylinker naz´yv´a ld-elf.so.1, v linuxov´ych distribuc´ıch vˇetˇsinou ld-linux.so.1, na IRIXu rld atd. – dynamick´ylinker se typicky d´akonfigurovat pomoc´ınastaven´ıpromˇen- n´ych, napˇr´ıkladsi zkuste na Solarisu spustit toto: LD_LIBRARY_PATH=/tmp LD_DEBUG=libs,detail date a pro zjiˇstˇen´ıvˇsech moˇznost´ıjak debugovat dynamick´ylinker pouˇzijte: LD_DEBUG=help date – pˇr´ıkladna to, kdy je potˇreba,aby linker hledal knihovny i jinde neˇzv de- faultn´ıch adres´aˇr´ıch (adres´aˇrespecifikovan´epromˇennou LD LIBRARY PA- TH se prohled´avaj´ıjako prvn´ı): $ cp /lib/libc.so.1 /tmp $ LD_LIBRARY_PATH=/tmp sleep 100 & [1] 104547 $ pldd 104547 104547: sleep 100 /tmp/libc.so.1 /usr/lib/locale/cs_CZ.ISO8859-2/cs_CZ.ISO8859-2.so.3 – Solaris m´avelmi zaj´ımav´ypˇr´ıkaz elfedit(1), pomoc´ıkter´ehom˚uˇzete editovat metadata ELF objektu, napˇr´ıkladpˇrepsatjm´enoz´avisl´ekni- hovny, zmˇenitnastaven´ı RUNPATH atd.
36 • Obecnˇeplat´ı,ˇzepouˇz´ıvat LD LIBRARY PATH k ovlivnˇen´ıbˇehu dynamick´eho linkeru pro nˇecojin´ehoneˇzladˇen´ı dynamick´ych knihoven pˇriv´yvoji nebo pˇresunech knihoven mezi adres´aˇrinen´ıdobr´yn´apad.Na internetu lze naj´ıt mnoˇzstv´ıˇcl´ank˚utypu ”why is LD LIBRARY PATH evil ?”apod., napˇr. http: //xahlee.org/UnixResource dir/ /ldpath.html. Tato promˇenn´aje typicky zneuˇz´ıvan´ave startovac´ıch skriptech program˚u, aby pˇredsunuly alternativn´ıseznam adres´aˇr˚ukde hledat dynamick´eknihovny na kter´ych program z´avis´ı. To vˇetˇsinouproto, ˇzebyl program nespr´avnˇe slinkov´ana dynamick´ylinker by podle informac´ı v ELFu nedok´azaljinak knihovny naj´ıt.Typick´ynechtˇen´yside effect je, ˇzeprogram d´alespust´ıjin´y program, kter´ypouˇz´ıv´aknihovnu stejn´ehojm´ena,ale ”d´ıky”tomu, ˇzese promˇenn´eprostˇred´ı dˇed´ı, tak dynamick´ylinker najde tuto knihovnu jako prvn´ıv ares´aˇrispecifikovan´empomoc´ı LD LIBRARY PATH. Tato knihovna m˚uˇze b´ytale jin´everze, neˇzten druh´yprogram oˇcek´av´a,a pak snadno m˚uˇzedoj´ıtk nˇeˇcemu, co se vˇetˇsinounaz´yv´a”nedefinovan´echov´an´ı”(vizpˇr´ıkladu dalˇs´ıho slide o ABI).
API versus ABI
API – Application Programming Interface • rozhran´ıpouˇzit´epouze ve zdrojov´emk´odu • rozhran´ı zdroj´aku v˚uˇcisyst´emu, knihovnˇeˇcivlastn´ımu k´odu, tj. napˇr. exit(1), printf("hello\n") nebo my function(1, 2) • . . . aby se stejn´y zdrojov´yk´od mohl pˇreloˇzitna vˇsech syst´emech podporuj´ıc´ıdan´eAPI ABI – Application Binary Interface • low-level rozhran´ı aplikace v˚uˇcisyst´emu, knihovnˇeˇcijin´eˇc´asti sama sebe • . . . aby se objektov´ymodul mohl pouˇz´ıtvˇsudetam, kde je podporov´anostejn´eABI
• Pˇr´ıklademAPI je tˇrebaAPI definovan´enormou POSIX.1.
• ABI definuje konvenci vol´an´ı(to jak program pˇred´aparametry funkci a jak od n´ıpˇrevezme n´avratovou hodnotu), jak´ajsou ˇc´ıslasyst´emov´ych vol´an´ı,jak se syst´emov´evol´an´ı provede ˇciform´atobjektov´ehomodulu a pˇrij´ıman´ych argument˚u,viz pˇr´ıkladdole. • API knihovny pak definuje mimo jin´emnoˇzinu vol´an´ıkter´ajsou knihovnou definov´ana,jejich parametry a typy tˇechto parametr˚u.
37 • n´asledn´auk´azka je pˇr´ıkladna to, kdy v´yvoj´aˇrzmˇen´ıvelikost argument˚uv bajtech (tj. zmˇen´ıABI knihovny), a nahrad´ınovou verz´ıtu starou. Vˇsimnˇete si, ˇzedynamick´ylinker toto nezjist´ı; nem´atotiˇzjak, ˇr´ıd´ı se podle jm´ena knihovny v dynamick´esekci programu, a to se nezmˇenilo.Uveden´azmˇena je sice i zmˇenav API a probl´emby se odstranil, kdybychom main.c znovu pˇreloˇzilise zmˇenˇen´ymˇr´adkem deklarace funkce add. To je ale ˇcastoprobl´em (pˇrekl´adejtecel´ysyst´emjen kv˚ulitomu), proto je tak d˚uleˇzit´edodrˇzovat zpˇetnoukompatibilitu v ABI u knihoven. V´ysledekn´asleduj´ıc´ıhopˇrekladu knihovny, programu a jeho spuˇstˇen´ıje jak bychom oˇcek´avali (pouˇzit cc ze SunStudio, pro gcc pouˇzijtem´ısto -G volbu -shared; novˇejˇs´ı gcc nav´ıcneznaj´ı -R a je m´ıstotoho nutn´epouˇz´ıt -Xlinker -R .:
$ cat main.c int my_add(int a, int b);
int main(void) { printf("%d\n", my_add(1, 2)); return (0); }
$ cat add.c int my_add(int a, int b) { return (a + b); }
$ cc -G -o libadd.so add.c $ cc -L. -ladd -R. main.c $ ./a.out 3
Nyn´ıale pˇriˇsladalˇs´ıverze knihovny se stejn´ymjm´enem, a ve funkci my add nastala zmˇena v typu argument˚u,kde m´ısto4-bajtov´ehointegeru se pouˇzije 64-bitov´yceloˇc´ıseln´ytyp. Program ale o niˇcemnev´ı,nech´ase spustit a vr´at´ı chybnou hodnotu:
$ cat add2.c int64_t my_add(int64_t a, int64_t b) { return (a + b); }
$ cc -G -o libadd.so add2.c $ ./a.out -1077941135
• pˇr´ıklad: lib-abi/abi-main.c (koment´aˇrv souboru napov´ıjak pouˇz´ıtos- tatn´ısoubory ve stejn´emadres´aˇri)
38 • zde pak pˇrich´az´ıke slovu verzov´an´ıknihoven, tj. je nutn´e“nˇeco”zmˇenittak, aby po instalaci nov´eknihovny neˇsloprogram spustit bez jeho rekompilace.
• bin´arn´ınekompatibilita je napˇr´ıkladprobl´emu OpenSSL. Vˇetve 0.9.x a 0.9.y nejsou ABI kompatibiln´ı.Konkr´etnˇeverze 0.9.7 a 0.9.8, v roce 2009 st´aleobˇe pouˇz´ıvan´e.Verze rozliˇsen´ep´ısmeny, tj. napˇr´ıklad0.9.8a a 0.9.8g, jsou ABI kompatibiln´ı.Nˇekter´esyst´emy st´alepouˇz´ıvaj´ıpouze 0.9.7 (FreeBSD 6.x, So- laris 10), jin´ejen 0.9.8 (Solaris 11 Express), dalˇs´ıintegruj´ıobˇevˇetve (r˚uzn´e Linuxov´edistribuce). Probl´emje, m´ate-linapˇr´ıkladprogram pro Solaris 10 pouˇz´ıvaj´ıc´ı libcrypto.so knihovnu, kter´ychcete pouˇz´ıvat i na Solaris 11 Ex- press (to je jinak d´ıkyzpˇetn´ebin´arn´ıkompatibilitˇestriktnˇedodrˇzovan´emezi ”major”verzemi Solarisu moˇzn´e- napˇr.program kter´ybˇeˇzel na Solarisu 2.6 z roku 1997 m˚uˇzebˇeˇzetna Solarisu 10 z roku 2009 bez nutnosti rekompilace - to se t´yk´asyst´emu a knihoven s n´ımdod´avan´ych). Jedin´espr´avn´ereˇsen´ıje zkompilovat pro nov´ysyst´em,pˇr´ıpadnˇemanu´alnˇezkop´ırovat potˇrebn´everze knihoven, coˇzale zdaleka nen´ıide´aln´ı– program nebude fungovat s novˇena- instalovan´ymsyst´emem,ale nikdo najednou nev´ı,proˇcto funguje na stejn´em syst´emu vedle, a kdyˇzse to zjist´ıtak je opˇetpotˇrebamanu´aln´ız´asah,a po- chybuji o tom, ˇzeautor “ˇreˇsen´ı”bude instalovat opraven´everze pˇriv´yskytu bezpeˇcnostn´ıch chyb. Nekompatibilita 0.9.x verz´ıje d˚uvodem, proˇcje v dy- namick´esekci knihovny i jej´ıcel´eˇc´ıslo(bez p´ısmen,ta jak jiˇzv´ımenejsou pro ABI kompatibilitu u OpenSSL d˚uleˇzit´a),a d´ıkytomu je pak toto ˇc´ıslo uvedeno i v kaˇzd´emprogramu proti knihovnˇeslinkovan´emu:
$ elfdump -d /usr/sfw/lib/libcrypto.so.0.9.8 | grep SONAME [7] SONAME 0x1 libcrypto.so.0.9.8
$ elfdump -d /usr/bin/ssh | grep NEEDED [1] NEEDED 0x3c99 libsocket.so.1 [3] NEEDED 0x3cb1 libnsl.so.1 [5] NEEDED 0x3cc6 libz.so.1 [7] NEEDED 0x3d12 libcrypto.so.0.9.8 [9] NEEDED 0x3cd9 libgss.so.1 [10] NEEDED 0x3cfe libc.so.1
– pˇr´ıˇcinouzpˇetn´enekompatibility OpenSSL verz´ıje to, ˇzez historick´ych d˚uvod˚ujsou nˇekter´epouˇz´ıvan´estruktury v hlaviˇckov´ych souborech. Tyto struktury je ale nˇekdynutn´erozˇs´ıˇrit, napˇr´ıkladpˇriv´yvoji nov´e funkcionality. T´ımnastane situace, ˇzeprogram pˇreloˇzen´ys verz´ı0.9.7 by pˇredalnovˇejˇs´ıknihovnˇe“menˇs´ı”strukturu, respektive nov´aknihovna by pˇristupovala ve star´estruktuˇrena poloˇzky, kter´eneexistuj´ı– a tedy by pˇristupovala k pamˇeti,kter´aprogramu nebyla pˇridˇelena.To m˚uˇze zp˚usobitp´adprogramu (pˇr´ıstupna nenamapovanou str´anku),m˚uˇzeto fungovat d´ale(v dan´epamˇetije to, co se tam typicky oˇcek´av´a,napˇr´ıklad nula), nebo se to zaˇcnechovat “podivnˇe”(v pamˇetibylo nˇeco,co v dan´e situaci oˇcek´avan´enebylo). Probl´emv OpenSSL je, ˇzenyn´ıjiˇznen´ıtech- nicky jednoduch´ez tˇechto struktur udˇelatintern´ıa navenek pracovat jen s transparentn´ımireferencemi objektov´ympˇr´ıstupem, coˇzby umoˇznilo dˇelatlibovoln´ezmˇeny ve struktur´ach, aniˇzby to program ovlivnilo. – bˇeˇznˇevidˇen´eˇreˇsen´ı zp˚usoben´eneznalost´ı vˇecije vytvoˇritsymbolick´y link, napˇr´ıkladna Solarisu 11 udˇelat0.9.7 symlink na existuj´ıc´ıknihovnu verze 0.9.8. Cast´yv´ysledekjeˇ pak p´adprogramu a ´udivautora symlinku. Nˇekdyto naopak funguje, protoˇzeprogram n´ahodou nepouˇz´ıv´apˇr´ısluˇsn´e
39 struktury, a to je jasn´ymd˚ukazem pro akt´era,ˇzeˇreˇsen´ımus´ıb´ytspr´avn´e. M˚uˇzese ale st´at,ˇzeprogram struktury nepouˇz´ıv´apˇrikonkr´etn´ımpro- veden´emtestu, ale zaˇcnedˇelatprobl´emy aˇzpˇriˇziv´emnasazen´ı.Tady je jedin´arada – pokud si opravdu nejste jisti ˇzev´ıte,co dˇel´atea nejste si jist´ısvoji detailn´ıznalost´ık´oduprogramu i knihoven, vyhnˇetese tomu. Nebo riskujte, ale jiˇzv´ıtejak to m˚uˇzeskonˇcit. – zd´anlivˇejednoduch´eˇreˇsen´ıdod´avat v´ıceverz´ıOpenSSL s jedn´ımsyst´e- mem pˇrin´aˇs´ızase jin´eprobl´emy – obt´ıˇznˇejˇs´ıv´yvoj syst´emu, obt´ıˇznˇejˇs´ı spr´avusyst´emu (pˇriv´yskytubezpeˇcnostn´ıchyby je ˇcastonutn´epatcho- vat vˇsechny instalovan´everze), probl´emy s nepˇr´ım´ymiz´avislostmiobsa- huj´ıc´ıv´ıceverz´ıdan´eknihovny apod. – upgrade verze OpenSSL v existuj´ıc´ımsyst´emu je tak´evˇec,kter´eje dobr´e se vyhnout, respektive toto tˇeˇzko vyˇreˇs´ıtevyd´an´ımpatche pro existuj´ıc´ı syst´emy – uvaˇzteˇzez´akazn´ıkpouˇz´ıv´asv´enebo j´ımkoupen´eprogramy, kter´ez´avis´ına existuj´ıc´ıverzi. A tu byste mu najednou upgradovali na verzi vyˇsˇs´ı,ABI nekompatibiln´ı. – typick´ympˇr´ıkladem,kdy se pouˇz´ıv´atransparentn´ıtyp jako reference, coˇzumoˇzˇnujedalˇs´ırozˇsiˇrov´an´ıpod n´ıleˇz´ıc´ıstruktury bez rizika v´yˇse uveden´ych probl´em˚u,je typ POSIX vl´aken. Struktura typu pthread t (strana 195) je intern´ız´aleˇzitost´ıknihovny. Typicky je to integer, ale to by program´atoranemˇelov˚ubec zaj´ımat.Samozˇrejmˇesouborov´ydeskrip- tor ˇciˇc´ısloprocesu jsou podobn´epˇr´ıpady, ale na pˇr´ıkladuvl´aken je to l´epe vidˇet.
Debugger dbx
• Vol´an´ı: dbx [ options ][ program [ core ]] • Nejbˇeˇznˇejˇs´ıpˇr´ıkazy: run [arglist ] start programu where vypiˇsz´asobn´ık print expr vypiˇsv´yraz set var = expr zmˇeˇnhodnotu promˇenn´e cont pokraˇcov´an´ıbˇehu programu next, step proved’ ˇr´adku(bez/s vnoˇren´ımdo funkce) stop condition nastaven´ıbreakpointu trace condition nastaven´ıtracepointu command n akce na breakpointu (pˇr´ıkazy n´asleduj´ı) help [name ] n´apovˇeda quit ukonˇcen´ıdebuggeru
• z´akladn´ıˇr´adkov´ysymbolick´ydebugger, aby bylo moˇzn´eho plnˇevyuˇz´ıt,mus´ı
40 b´ytprogram pˇreloˇzens ladic´ımiinformacemi (cc -g). Ladˇen´yprogram se startuje z debuggeru pˇr´ıkazem run, nebo se debugger pˇripoj´ık jiˇzbˇeˇz´ıc´ımu procesu. Pomoc´ı dbx lze analyzovat i havarovan´yprogram, kter´yvygeneroval soubor core. • je moˇzn´eho naj´ıtnapˇr.na Solarisu, avˇsakna Linuxu a FreeBSD defaultnˇe nen´ı. • pro debugging se zdrojov´ymik´odynestaˇc´ıpouˇz´ıtvolbu -g, je z´aroveˇnnutn´e m´ıti zdroj´akya objektov´emoduly tam, kde byly pˇripˇrekladu.To je typicky bˇeˇzn´asituace, protoˇzelad´ıtena stroji, kde z´aroveˇni vyv´ıj´ıte.Pokud tomu tak nen´ı,je nutn´esi zdroj´akya objektov´emoduly zajistit, pokud k nim vede jin´acesta, lze pouˇz´ıtdbx pˇr´ıkaz pathmap. • gdb-kompatibiln´ı m´odse spust´ı pˇres gdb on. Pokud v´aszaj´ım´a,jak´ym´a dbx ekvivalentn´ıpˇr´ıkaz ke konkr´etn´ımu gdb pˇr´ıkazu, pom˚uˇzev´am help FAQ; hned prvn´ıot´azka je “A.1 Gdb does
• pˇr´ıklad: debug/coredump.c . Po pˇreloˇzen´ıa spuˇstˇen´ıprogram spadne a za- nech´acore dump.
$ cc coredump.c $ ./a.out Segmentation Fault (core dumped) $ dbx ./a.out core Reading a.out core file header read successfully Reading ld.so.1 Reading libc.so.1 program terminated by signal SEGV (no mapping at the fault address) 0x08050a05: bad_memory_access+0x0015: movb %al,0x00000000(%edx) (dbx) where =>[1] bad_memory_access(0x8047ae8, 0x8047a44, ... [2] main(0x1, 0x8047a50, 0x8047a58, 0x8047a0c), at 0x8050a1b
Vid´ıme,ve kter´efunkci to spadlo a je moˇzn´ese vypsat z´asobn´ık.Nevid´ıme ale pˇresnˇeˇr´adkuk´odu,kde nastal probl´em.Pro to je nutn´epˇreloˇzitpro- gram s lad´ıc´ımisymboly, tj. “cc -g coredump.c”. Z´ajemce o v´ıceinformac´ı o debugging pod unixem odkazuji na navazuj´ıc´ıpˇredn´aˇsku“Programov´an´ıv UNIXu II.” (NSWI138).
$ cc -g coredump.c $ dbx ./a.out core Reading a.out core file header read successfully Reading ld.so.1
41 Reading libc.so.1 program terminated by signal SEGV (no mapping at the fault address) Current function is bad_memory_access 8 x[0] = ’\0’; (dbx)
GNU debugger gdb
• Vol´an´ı: gdb [ options ][ program [ core ]] • Nejbˇeˇznˇejˇs´ıpˇr´ıkazy: run [arglist ] start programu bt vypiˇsz´asobn´ık print expr vypiˇsv´yraz set var = expr zmˇeˇnhodnotu promˇenn´e cont pokraˇcov´an´ıbˇehu programu next, step proved’ ˇr´adku(bez/s vnoˇren´ımdo funkce) break condition nastaven´ıbreakpointu help [name ] n´apovˇeda quit ukonˇcen´ıdebuggeru
• GNU obdoba dbx. M´odkompatibiln´ıs dbx spust´ıtepˇres -dbx. • na r˚uzn´ych platform´ach existuj´ıi debuggery s grafick´ymrozhran´ım,napˇr. workshop (Solaris), cvd (IRIX), xxgdb (GNU), ddd (GNU). Castoˇ funguj´ı jako nadstavby nad dbx, gdb. • #include
Breakpoint 1, main () at main.c:4 4 printf("hello, world\n");
42 (gdb) next hello, world 5 return (0); (gdb) c Continuing. Program exited normally. (gdb) q • debuggery jsou v´yborn´ymipomocn´ıkypokud v´aˇsprogram konˇc´ına chyby typu “segmentation error” – tj. kdyˇzzkus´ıtenekorektnˇepˇristoupitdo pamˇeti, napˇr´ıkladtam kde nem´ateco dˇelat.Kdyˇzpˇripˇrekladupouˇzijeteoption -g, uk´aˇzev´ampak debugger pˇresnˇeˇc´ısloˇr´adku,kde nastal probl´em.Konkr´etn´ı pˇr´ıklad(proˇcse vlastnˇetento program chov´ajak se chov´a???Hint: zkuste pˇreloˇzitna Solarisu pˇrekladaˇcem cc a spustit):
$ cat -n main.c 1 int 2 main(void) 3 { 4 char *c = "hey world"; 5 c[0] = ’\0’; 6 return (0); 7 } } $ gcc -g main.c $ ./a.out Bus error (core dumped) $ gdb a.out a.out.core ... Core was generated by ‘a.out’. Program terminated with signal 10, Bus error. ... #0 0x080484e6 in main () at main.c:5 5 c[0] = ’\0’;
43 Obsah
• ´uvod, v´yvoj UNIXu a C, program´atorsk´en´astroje • z´akladn´ıpojmy a konvence UNIXu a jeho API • pˇr´ıstupov´apr´ava, perifern´ızaˇr´ızen´ı,syst´emsoubor˚u • manipulace s procesy, spouˇstˇen´ıprogram˚u • sign´aly • synchronizace a komunikace proces˚u • s´ıt’ov´akomunikace • vl´akna,synchronizace vl´aken • ??? - bude definov´anopozdˇeji,podle toho kolik zbyde ˇcasu
Standardn´ıhlaviˇckov´esoubory (ANSI C)
stdlib.h . . . z´akladn´ımakra a funkce errno.h . . . oˇsetˇren´ıchyb stdio.h . . . vstup a v´ystup ctype.h . . . pr´acese znaky string.h . . . pr´aces ˇretˇezci time.h . . . pr´aces datem a ˇcasem math.h . . . matematick´efunkce setjmp.h . . . dlouh´eskoky assert.h . . . ladic´ıfunkce stdarg.h . . . pr´aces promˇenn´ympoˇctemparametr˚u limits.h . . . implementaˇcnˇez´avisl´ekonstanty signal.h . . . oˇsetˇren´ısign´al˚u
44 • hlaviˇckov´ysoubor (header file) je soubor s deklaracemi funkc´ı(forward decla- ration), promˇenn´ych a maker. Z pohledu preprocesoru je to obyˇcejn´ysoubor napsan´yv jazyce C.
• tyto hlaviˇckov´esoubory nejsou specifick´epro UNIX. Jsou souˇc´ast´ı standardu ANSI C, kter´yjak jiˇzv´ıme(strana 16), je zahrnut v POSIX.1. Je ale d˚uleˇzit´esi uvˇedomit,ˇzetyto hlaviˇckov´esoubory mus´ıpodporovat kaˇzd´ysyst´em,kter´ypodporuje ANSI C, at’ jiˇz podporuje POSIX.1 nebo ne.
• pˇr´ısluˇsn´yhlaviˇckov´ysoubor pro konkr´etn´ıfunkci najdete v manu´alov´estr´ance dan´efunkce, toto je zaˇc´atekmanu´alov´estr´ankyna Solarisu pro memcpy:
Standard C Library Functions memory(3C)
NAME memory, memccpy, memchr, memcmp, memcpy, memmove, memset - memory operations
SYNOPSIS #include
• jednotliv´amakra obsaˇzen´av tˇechto souborech vˇetˇsinounejsou vysvˇetlena, v´yznamjednotliv´ych maker je ale moˇzn´esi vyhledat v pˇr´ısluˇsn´ych specifi- kac´ıch, kter´ejsou on-line. Na nˇekter´ych syst´emech (Solaris) maj´ıjednotliv´e hlaviˇckov´esoubory svoji vlastn´ımanu´alovou str´anku(man stdlib.h). • makro assert je moˇzn´ez bˇehemkompilace odstranit pomoc´ımakra NDEBUG. Pˇr´ıklad: assert/assert.c .
cat assert.c #include
int main(void) { assert(1 == 0); return (13); } $ cc assert.c $ ./a.out Assertion failed: 1 == 0, file assert.c, line 6 Abort (core dumped) $ cc -DNDEBUG assert.c $ ./a.out $ echo $? 13
45 Standardn´ıhlaviˇckov´esoubory (2)
unistd.h . . . symbolick´ekonstanty, typy a z´akladn´ıfunkce sys/types.h . . . datov´etypy fcntl.h . . . ˇr´ıd´ıc´ıoperace pro soubory sys/stat.h . . . informace o souborech dirent.h . . . proch´azen´ıadres´aˇr˚u sys/wait.h . . . ˇcek´an´ına synovsk´eprocesy sys/mman.h . . . mapov´an´ıpamˇeti curses.h . . . ovl´ad´an´ıtermin´alu regex.h . . . pr´aces regul´arn´ımiv´yrazy
• tyto headery uˇzpatˇr´ıdo UNIXu.
• zaj´ımav´em˚uˇzeb´yt pod´ıvat se do sys/types.h
46 Standardn´ıhlaviˇckov´esoubory (3)
semaphore.h . . . semafory (POSIX) pthread.h . . . vl´akna (POSIX threads) sys/socket.h . . . s´ıt’ov´akomunikace arpa/inet.h . . . manipulace se s´ıt’ov´ymiadresami sys/ipc.h . . . spoleˇcn´edeklarace pro System V IPC sys/shm.h . . . sd´ılen´apamˇet’ (System V) sys/msg.h . . . fronty zpr´av(System V) sys/sem.h . . . semafory (System V)
• dokonˇcen´ı nejd˚uleˇzitˇejˇs´ıch UNIXov´ych header˚u.Existuj´ı samozˇrejmˇejeˇstˇe dalˇs´ı.
47 Funkce main()
• pˇrispuˇstˇen´ıprogramu je pˇred´anoˇr´ızen´ıfunkci main(). • int main (int argc, char *argv []); – argc . . . poˇcetargument˚upˇr´ıkazov´eˇr´adky – argv . . . pole argument˚u ∗ podle konvence je argv[0] jm´enoprogramu (bez cesty) ∗ posledn´ıprvek je argv[argc] == NULL – n´avratz main() nebo vol´an´ı exit() ukonˇc´ıprogram – standardn´ın´avratov´ehodnoty EXIT_SUCCESS (0) a EXIT_FAILURE (1)
ls -l / argv[0] ”ls” argv[1] ”-l” argc 3 argv[2] argv argv[3] ”/”
• prvn´ı parametr (typu int) ud´av´apoˇcetargument˚una pˇr´ıkazov´emˇr´adku (vˇcetnˇeargumentu 0 – jm´enaprogramu) a druh´yparametr (typu char**) je pole ukazatel˚una tyto ˇretˇezce. Za posledn´ımˇretˇezcemje jeˇstˇeukonˇcovac´ı NULL pointer – pozor na to, ˇzeto je nˇecojin´ehoneˇzpr´azdn´yˇretˇezec. • argv[0] nˇekdyb´yv´ad˚uleˇzit´ym zdrojem pˇridan´einformace. Na Solarisu jsou napˇr´ıkladpˇr´ıkazy cp, mv a ln nalinkovan´ena stejn´ysoubor. Hodnota argv[0] pak urˇcuje,jakou funkci vlastnˇeproces m´a.Jin´ypˇr´ıklad– pokud m´ashell prvn´ıznak z argv[0] nastaven na “-”, znamen´ato, ˇzese m´achovat jako lo- gin shell (pod´ıvejte se tˇrebado manu´alov´estr´ankypro bash na sekci INVO- CATION, pokud nev´ıte,co to je login shell). Ve v´ypisuproces˚upak uvid´ıte “-bash”. Toto nen´ısouˇc´astUNIX specifikace pro sh, ale pouˇz´ıval to jiˇzBourne shell na UNIXu V7 (1979) a ostatn´ıshelly to pˇrevzaly.
• pˇrispuˇstˇen´ı programu pˇred´ak´oddynamick´eholinkeru ˇr´ızen´ı funkci main, viz strana 35. Staticky slinkovan´emu programu se ˇr´ızen´ıpˇred´apˇr´ımo.Ne- pˇr´ıtomnost main v programu zp˚usob´ıchybu pˇripˇrekladuna ´urovni linkeru. T´etofunkci se pˇred´ajm´enospuˇstˇen´ehoprogramu, argumenty z pˇr´ıkazov´e ˇr´adkya pˇr´ıpadnˇei promˇenn´eprostˇred´ı.Ukonˇcen´ıt´eto funkce znamen´akonec programu a n´avratov´ahodnota se pouˇzijejako k´odukonˇcen´ıprogramu pro OS. Jinou moˇznost´ıukonˇcen´ıprogramu je pouˇzit´ıfunkce exit nebo _exit, kterou lze pouˇz´ıtkdykoliv, nejen ve funkci main. V C lze pouˇz´ıvat obˇemetody ukonˇcen´ıprogramu.
• pˇred´an´ıpromˇenn´ych prostˇred´ıtˇret´ımparametrem typu char** nen´ısouˇc´ast´ı normativn´ıˇc´astiC standardu, pouze informativn´ı.Pˇrekladaˇceto ale typicky
48 podporuj´ı.Varianta main s promˇenn´ymiprostˇred´ıpak vypad´atakto: int main(int argc, char *argv [], char *envp []);
• n´avratov´ytyp funkce main by mˇelb´ytvˇzdy int; pˇrekladaˇcsi jinak bude stˇeˇzovat. Z t´etohodnoty se ale pouˇzijepouze nejniˇzˇs´ıch 8 bit˚u, a je to nez´aporn´eˇc´ıslo. Pozor na to, ˇzena rozd´ıl od konvence jazyka C n´avratov´ahodnota 0 m´av shellu v´yznamtrue (´uspˇech) a nenula v´yznam false (ne´uspˇech). Typick´akonstrukce v shellu vypad´atakto:
if ! prog; then echo "failure" else echo "success" fi
Pˇr´ıklad: main/return-256.c . • nepouˇz´ıvejte proto ve funkci main return (-1) a nikde pak ani exit(-1), z toho vznikne n´avratov´ahodnota 255 a k´odje matouc´ı.Je v˚ubec velmi vhodn´e pouˇz´ıvat pouze 0 a 1, pokud nen´ız´asadn´ıd˚uvod pro jin´ehodnoty, tˇrebaten ˇzejich potˇrebujetev´ıce– m˚uˇzetese pod´ıvat napˇr´ıkladna manu´alovou str´anku pro passwd na Solarisu, sekce EXIT STATUS. Pˇr´ıklad: main/return-negative-1.c .
• rozd´ılmezi funkcemi exit a _exit je v tom, ˇze exit pˇredukonˇcen´ımpro- gramu jeˇstˇevypr´azdn´ı(pomoc´ıknihovn´ıfunkce fflush) a zavˇrestreamy a vol´afunkce zaregistrovan´epomoc´ı atexit. V z´avislostina syst´emu to mohou b´yti dalˇs´ıakce. Pro zaj´ımavost, napˇr´ıklad ve FreeBSD je exit syst´emov´evol´an´ı a exit knihovn´ı funkce, ale na Solarisu jsou obˇesyst´emov´ymivol´an´ımi. Pˇr´ıklad: exit/exit.c
• pˇr´ıklad: main/print-argv.c
49 Promˇenn´eprostˇred´ı
• seznam vˇsech promˇenn´ych prostˇred´ı(environment variables) se pˇred´av´ajako promˇenn´a extern char **environ; • je to pole ukazatel˚u(ukonˇcen´eNULL) na ˇretˇezceve tvaru: promˇenn´a =hodnota environ
environ[0] ”SHELL=/bin/bash” environ[1] ”DISPLAY=:0” environ[2] environ[3] ”LOGNAME=beran”
• shell pˇred´av´aspuˇstˇen´emu programu ty promˇenn´e, kter´ejsou oznaˇceny jako exportovan´e(Bourne-like shellech pˇr´ıkazem export variable ). Po zmˇenˇe obsahu jiˇzjednou exportovan´epromˇenn´esamozˇrejmˇenen´ıpotˇrebapromˇennou znovu exportovat. Pˇr´ıkaz env v´amvyp´ıˇseaktu´aln´ıpromˇenn´eprostˇred´ı.Abyste pˇridalipromˇennou do prostˇred´ıspouˇstˇen´ehoprogramu staˇc´ıprov´estpˇriˇrazen´ı na pˇr´ıkazov´eˇr´adce,aniˇzbyste museli mˇenitprostˇred´ıvaˇsehoshellu:
$ date Sun Oct 7 13:13:58 PDT 2007 $ LC_TIME=fr date dimanche 7 octobre 2007 13 h 14 PDT
nedivte se, pokud to na vaˇsemsyst´emu takto fungovat nebude, v tom pˇr´ıpadˇe nem´ateinstalovan´ybal´ıks francouzskou lokalizac´ı(coˇzje pravdˇepodobn´e). • pˇrinahrazen´ıaktu´aln´ıhoobrazu procesu obrazem jin´ymse pˇred´av´a,pokud se neˇreknejinak, synovsk´ymproces˚umcel´epole environ automaticky. Je moˇzn´eve vol´an´ıpˇr´ısluˇsn´evarianty funkce exec pˇredatpole jin´e. • jak´epromˇenn´eprostˇred´ıkonkr´etn´ıpˇr´ıkaz pouˇz´ıv´a(a jak je pouˇz´ıv´a)by mˇelo b´ytv manu´alov´estr´ance.Typicky v sekci nazvan´e ENVIRONMENT nebo ENVIRONMENT VARIABLES
• man napˇr´ıkladpouˇz´ıv´a PAGER, vipw pak promˇennou EDITOR apod.
• pokud je envp tˇret´ımparametrem funkce main, tak je to stejn´ahodnota co je v ukazateli environ.
50 • pˇr´ıklad: main/print-env.c (vˇcetnˇepouˇzit´ı env pˇr´ıkazu zp˚usobem, kter´y vyˇcist´ızdˇedˇen´epromˇenn´eprostˇred´ı).
$ cc print-env.c $ env - XXX=yyy aaa=ABC ./a.out aaa=ABC XXX=yyy
Manipulace s promˇenn´ymiprostˇred´ı
• je moˇzn´epˇr´ımomˇenitpromˇennou environ, SUSv3 to ale nedoporuˇcuje
• char *getenv (const char *name ); – vr´at´ıhodnotu promˇenn´ename
• int putenv (char *string ); – vloˇz´ıstring ve tvaru jm´eno =hodnota do prostˇred´ı(pˇrid´a novou nebo modifikuje existuj´ıc´ıpromˇennou) • zmˇeny se pˇren´aˇsej´ıdo synovsk´ych proces˚u • zmˇeny v prostˇred´ısyna samozˇrejmˇeprostˇred´ıotce neovlivn´ı • existuj´ıi funkce setenv() a unsetenv()
• u putenv se vloˇzen´yˇretˇezec stane souˇc´ast´ıprostˇred´ı(jeho pozdˇejˇs´ızmˇena tak zmˇen´ıprostˇred´ı)a nesm´ıteproto pouˇz´ıvat retˇezcev automatick´ych pro- mˇenn´ych, toto ˇreˇs´ı setenv, kter´yhodnotu promˇenn´ezkop´ıruje.Viz pˇr´ıklad main/putenv.c .
• d˚uleˇzit´eje zapamatovat si, ˇzesynovsk´yproces zdˇed´ıv okamˇzikusv´ehovzniku od rodiˇcevˇsechny promˇenn´eprostˇred´ı, ale jak´akoliv manipulace s nimi v synovi je lok´aln´ıa do otce se nepˇren´aˇs´ı.Kaˇzd´yproces m´asvou kopii pro- mˇenn´ych, proto ani n´asledn´azmˇena prostˇred´ı otce nezmˇen´ı promˇenn´ejiˇz existuj´ıc´ıhopotomka.
• dalˇs´ırozd´ılmezi putenv a setenv je ten, ˇzev setenv mohu definovat, zda existuj´ıc´ıpromˇennouchci nebo nechci pˇrepsat. putenv vˇzdypˇrepisuje. • int main(void) { printf("%s\n", getenv("USER"));
51 return (0); } $ ./a.out jp • jelikoˇzpromˇenn´a environ je obyˇcejn´epole ukazatel˚una ˇretˇezce, nen´ınebˇeˇzn´e narazit na k´od,kter´ys t´ımto polem pracuje pˇr´ımo.Pozor vˇsakna to, ˇzev takov´empˇr´ıpadˇepak jiˇznesm´ıtepouˇz´ıvat zde uveden´efunkce, jinak se m˚uˇzete dostat do probl´em˚us jejich konkr´etn´ıimplementac´ı.A hlavnˇe,nov´yk´odtakto nepiˇste,protoˇzenorma SUSv3 pˇr´ımoupr´acis t´ımto polem nedoporuˇcuje.
• pˇr´ıklad: main/getenv.c
• pozor na to, ˇzeje rozd´ıl mezi nastaven´ım hodnoty promˇenn´ena pr´azdn´y string a odmaz´an´ımpromˇenn´eze seznamu promˇenn´ych (pomoc´ı unsetenv).
Zpracov´an´ıargument˚uprogramu
• obvykl´yz´apisv shellu: program -pˇrep´ınaˇceargumenty • pˇrep´ınaˇcetvaru -x nebo -x hodnota , kde x je jedno p´ısmeno nebo ˇc´ıslice, hodnota je libovoln´yˇretˇezec • nˇekolik pˇrep´ınaˇc˚ulze slouˇcitdohromady: ls -lRa • argument ’--’ nebo prvn´ıargument nezaˇc´ınaj´ıc´ı’-’ ukonˇcuje pˇrep´ınaˇce,n´asleduj´ıc´ıargumenty nejsou povaˇzov´any za pˇrep´ınaˇce,i kdyˇzzaˇc´ınaj´ıznakem ’-’. • tento tvar argument˚upoˇzaduje norma a lze je zpracov´avat automaticky funkc´ı getopt.
• argumenty lze samozˇrejmˇezpracov´avat vlastn´ıfunkc´ı,ale standardn´ıfunkce je pohodlnˇejˇs´ı. • argumenty se typicky mohou opakovat, ale to m´asmysl jen v nˇekter´ych si- tuac´ıch
• poˇrad´ıpˇrep´ınaˇc˚um˚uˇzeb´ytd˚uleˇzit´ea je na aplikaci, aby toto specifikovala • UNIX norma definuje pomoc´ı13 pravidel velmi pˇresnˇe,jak by mˇelyvypa- dat n´azvypˇr´ıkaz˚ua form´atpˇrep´ınaˇc˚u.Napˇr´ıklad jm´enopˇr´ıkazu by mˇelo b´ytpouze mal´ymip´ısmeny, dlouh´e2–9 znak˚u,z pˇrenositeln´eznakov´esady.
52 Pˇrep´ınaˇcebez argument˚uby mˇelob´ytmoˇzn´ed´atdo skupiny za jedn´ımzna- kem ’–’. Atd.
• pouˇz´ıvat ˇc´ıslicejako pˇrep´ınaˇceje zastaral´e;je to nˇekdev normˇeSUSv3, i kdyˇzj´ato v n´ınenaˇsel. • pozor na Linux a jeho (ponˇekudzvl´aˇstn´ıa nestandardn´ı)permutov´an´ıargu- ment˚u
• pˇrep´ınaˇc -W by mˇel b´ytrezervovan´ypro vendor options, tj. pro nepˇrenositeln´a rozˇs´ıˇren´ı
Zpracov´an´ıpˇrep´ınaˇc˚u: getopt()
int getopt(int argc, char *const argv [], const char *optstring ); extern char *optarg ; extern int optind, opterr, optopt ; • funkce dostane parametry z pˇr´ıkazov´ehoˇr´adku,pˇrikaˇzd´em vol´an´ızpracuje a vr´at´ıdalˇs´ıpˇrep´ınaˇc.Pokud m´apˇrep´ınaˇc hodnotu, vr´at´ıji v optarg. • kdyˇzjsou vyˇcerp´any vˇsechny pˇrep´ınaˇce,vr´at´ı-1 a v optind je ˇc´ısloprvn´ıhonezpracovan´ehoargumentu. • moˇzn´epˇrep´ınaˇcejsou zad´any v optstring, kdyˇzza znakem pˇrep´ınaˇcen´asleduje’:’, m´apˇrep´ınaˇcpovinnou hodnotu. • pˇrichybˇe(nezn´am´ypˇrep´ınaˇc,chyb´ıhodnota) vr´at´ı’?’, uloˇz´ı znak pˇrep´ınaˇcedo optopt a kdyˇz opterr nebylo nastaveno na nulu, vyp´ıˇsechybov´ehl´aˇsen´ı.
• obvykle se nejprve pomoc´ı getopt naˇctoupˇrep´ınaˇcea pak se vlastn´ımipro- stˇredkyzpracuj´ıostatn´ıargumenty; ˇcastojsou to jm´enasoubor˚u.
• je konvenc´ı,ˇzevolby v parametru optstring jsou setˇr´ıdˇen´e.
53 Pˇr´ıkladpouˇzit´ı getopt()
struct { int a, b; char c[128]; } opts; int opt; char *arg1;
while((opt = getopt(argc, argv, "abc:")) != -1) switch(opt) { case ’a’: opts.a = 1; break; case ’b’: opts.b = 1; break; case ’c’: strcpy(opts.c, optarg); break; case ’?’: fprintf(stderr, "usage: %s [-ab] [-c Carg] arg1 arg2 ...\n", basename(argv[0])); break; } arg1 = argv[optind];
• dobr´ymzvykem je pˇridetekov´an´ınezn´am´ehopˇrep´ınaˇcenebo ˇspatn´ehoz´a- pisu parametr˚uprogramu vypsat struˇcnoun´apovˇedu,pˇr´ıpadnˇes odkazem na podrobnˇejˇs´ıdokumentaci, a ukonˇcitprogram s chybou, tj. s nenulovou n´avratovou hodnotou.
• pˇr´ıkladtak´eukazuje nebezpeˇcn´epouˇzit´ıfunkce strcpy
• z pouˇzit´ıfunkce getopt je vidˇet,ˇzeje stavov´a.Zpracovat dalˇs´ıpole argu- ment˚u,pˇr´ıpadnˇezaˇc´ıtopˇetod zaˇc´atku,je moˇzn´enastaven´ımextern´ıpro- mˇenn´e optreset na 1. • standardn´ı getopt zachov´apoˇrad´ıpˇrep´ınaˇc˚upˇrizpracov´an´ı • pˇripouˇzit´ınedefinovan´ehopˇrep´ınaˇcefunkce vyp´ıˇsechybu; to lze potlaˇcitna- staven´ım opterr na 0.
• pˇr´ıklad:shellov´yskript getopt/getopts.sh pˇrepsan´ydo jazyka C pomoc´ı getopt funkce, getopt/getopt.c
54 Dlouh´ytvar pˇrep´ınaˇc˚u
• poprv´ese objevilo v GNU knihovnˇe libiberty: --jm´enonebo --jm´eno=hodnota • argumenty se permutuj´ıtak, aby pˇrep´ınaˇcebyly na zaˇc´atku, napˇr. ls * -l je tot´eˇzjako ls -l *, standardn´ıchov´an´ılze doc´ılitnastaven´ımpromˇenn´e POSIXLY_CORRECT. • zpracov´avaj´ıse funkc´ı getopt long(), kter´apouˇz´ıv´apole struktur popisuj´ıc´ıch jednotliv´epˇrep´ınaˇce: struct option { const char *name; /* jm´enopˇrep´ınaˇce*/ int has arg; /* hodnota: ano, ne, volitelnˇe */ int *flag; /* kdyˇzje NULL, funkce vrac´ı val, jinak vrac´ı0 a d´a val do *flag */ int val; /* n´avratov´ahodnota */ };
verze jak se objevila ve FreeBSD (funkce getopt long nen´ıstandarizovan´a),m´a n´asleduj´ıc´ıvlastnosti:
• pokud vˇsechny dlouh´epˇrep´ınaˇcemaj´ınastaveny kr´atkou variantu ve val, je chov´an´ı getopt long kompatibiln´ıs getopt • je moˇzn´ezad´avat argument k dlouh´emu pˇrep´ınaˇcii s mezerou (napˇr´ıklad --color green) • pokud je nastaven flag, tak getopt long vrac´ı0, ˇc´ımˇzse tyto dlouh´epˇre- p´ınaˇcebez kr´atk´evarianty zpracuj´ıv jedn´evˇetvipˇr´ıkazu case • existuje i vol´an´ı getopt long only, kter´epovoluje i dlouh´epˇrep´ınaˇceuvozen´e jednou uvozovkou (-option)
• funkci getopt long je moˇzn´epouˇz´ıvat dvˇemizp˚usoby. Prvn´ızp˚usobje, ˇze kaˇzd´ydlouh´ypˇrep´ınaˇcm´akoresponduj´ıc´ıkr´atk´y– takto lze jednoduˇsepˇridat dlouh´epˇrep´ınaˇcedo existuj´ıc´ıho programu a je kompatibiln´ı s getopt. Druh´yzp˚usobumoˇzˇnujem´ıtsamostatn´edlouh´epˇrep´ınaˇce. V tom pˇr´ıpadˇe funkce vrac´ıvˇzdy0 (nekompatibilita s getopt) a promˇenn´a *flag se nastav´ı na val. • na konkr´etn´ımpˇr´ıkladuna n´asleduj´ıc´ıstr´anceje vidˇet,jak to cel´efunguje
55 Dlouh´epˇrep´ınaˇce(pokraˇcov´an´ı)
int getopt long(int argc, char * const argv [], const char *optstring, const struct option *longopts, int *longindex ); • optstring obsahuje jednop´ısmenn´epˇrep´ınaˇce, longopts obsahuje adresu pole struktur pro dlouh´epˇrep´ınaˇce(posledn´ı z´aznampole obsahuje sam´enuly) • pokud funkce naraz´ına dlouh´ypˇrep´ınaˇc,vrac´ıodpov´ıdaj´ıc´ı val nebo nulu (pokud flag nebyl NULL), jinak je chov´an´ı shodn´es getopt. • do *longindex (kdyˇznen´ı NULL) d´anav´ıcindex nalezen´eho pˇrep´ınaˇcev longopts.
• toto je upraven´ypˇr´ıkladz manu´alov´estr´ankyna FreeBSD:
#include
int ch, fd, daggerset, bflag = 0;
static struct option longopts[] = { { "buffy", no_argument, NULL, ’b’ }, { "fluoride", required_argument, NULL, ’f’ }, { "daggerset", no_argument, &daggerset, 1 }, { NULL, 0, NULL, 0 }};
int main(int argc, char **argv) { while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1) switch (ch) { case ’b’: bflag = 1; break; case ’f’: if ((fd = open(optarg, O_RDONLY, 0)) == -1) printf("unable to open %s", optarg); break; case 0: if (daggerset) { printf("Buffy will use her dagger to " "apply fluoride to dracula’s teeth\n"); } break; default: printf("usage: ...\n"); }
56 argc -= optind; argv += optind; return 0; }
Struktura klasick´ehoOS UNIX
uˇzivatelsk´yproces uˇzivatelsk´y n´avratpˇreruˇsen´ı reˇzim
rozhran´ıvol´an´ıj´adra reˇzim subsyst´em j´adra ˇr´ızen´ısoubor˚u
buffery subsyst´em IPC ˇr´ızen´ı pl´anovaˇc znakov´e blokov´e proces˚u pˇridˇelov´an´ı ovladaˇce a pamˇeti pamˇeti
strojovˇez´avisl´avrstva ovl´ad´an´ıhardware
hardware
• toto sch´emaje pˇrevzatoz [Bach86], viz literatura. Zd˚urazˇnujedva ´ustˇredn´ı pojmy v modelu syst´emu UNIX – soubory a procesy. V dneˇsn´ıdobˇeto vypad´avelmi odliˇsnˇe,ale pro n´asstaˇc´ıtato z´akladn´ıpˇredstava. • UNIX rozliˇsujedva reˇzimy bˇehu procesoru: uˇzivatelsk´yreˇzim a reˇzimj´adra. V uˇzivatelsk´emreˇzimu nejsou pˇr´ıstupn´eprivilegovan´einstrukce (napˇr.ma- pov´an´ıpamˇeti,I/O, maskov´an´ıpˇreruˇsen´ı).Tyto dva reˇzimy mus´ıb´ytpod- porov´any na hardwarov´e´urovni (procesorem). • procesy bˇeˇz´ıobvykle v uˇzivatelsk´emreˇzimu, do reˇzimu j´adrapˇrech´az´ıbud’ instrukc´ı synchronn´ıho pˇreruˇsen´ı (trap) pro vol´an´ı sluˇzby j´adra,nebo na z´akladˇeasynchronn´ıch pˇreruˇsen´ı(hodiny, I/O). D´alese v reˇzimu j´adra oˇsetˇru- j´ıv´yjimeˇcn´estavy procesoru (v´ypadekstr´anky, naruˇsen´ıochrany pamˇeti,ne- zn´am´ainstrukce apod.). Nˇekter´especi´aln´ıakce jsou zajiˇst’ov´any syst´emov´ymi procesy, kter´ebˇeˇz´ıcelou dobu v reˇzimu j´adra. • klasick´eUNIXov´ej´adro je tvoˇrenomonolitick´ymk´odem.P˚uvodnˇebylo po- tˇrebavygenerovat (tj. pˇreloˇzit ze zdrojov´ych text˚ua slinkovat) j´adropˇri zmˇenˇenˇekter´ehoparametru nebo pˇrid´an´ıovladaˇcezaˇr´ızen´ı.V novˇejˇs´ıch im- plementac´ıch je moˇznonastavovat parametry j´adra,nˇekdyi za bˇehu, pomoc´ı syst´emov´ych utilit bez nutnosti rekompilace j´adra.Modern´ıunixov´esyst´emy umoˇzˇnuj´ırozˇsiˇrovat k´odj´adraza bˇehu pomoc´ıtzv. modul˚uj´adra(loadable kernel modules). Napˇr´ıkladsyst´emFreeBSD 5.4-RELEASE m´a392 takov´ych modul˚u.
57 • existuj´ıdva zp˚usoby pr´aces perif´eriemi: blokov´a(block devices) a znakov´a zaˇr´ızen´ı (character, raw devices). Data z blokov´ych zaˇr´ızen´ı (napˇr.disky) proch´azej´ı pˇresvyrovn´avac´ı pamˇeti(buffers) po bloc´ıch, znakov´azaˇr´ızen´ı (napˇr.termin´aly)umoˇzˇnuj´ıpracovat s jednotliv´ymibajty a nepouˇz´ıvaj´ıvy- rovn´avac´ıpamˇet’. • j´adronen´ısamostatn´yproces, ale je ˇc´ast´ıkaˇzd´ehouˇzivatelsk´ehoprocesu. Kdyˇzj´adronˇecovykon´av´a,tak vlastnˇeproces, bˇeˇz´ıc´ıv reˇzimu j´adra,nˇeco prov´ad´ı.
Procesy, vl´akna,programy • proces je syst´emov´yobjekt charakterizovan´ysv´ymkontextem, identifikovan´yjednoznaˇcn´ymˇc´ıslem(process ID, PID); jin´ymislovy ,,k´oda data v pamˇeti” • vl´akno(thread) je syst´emov´yobjekt, kter´yexistuje uvnitˇr procesu a je charakterizov´ansv´ym stavem. Vˇsechna vl´akna jednoho procesu sd´ıl´ıstejn´ypamˇet’ov´yprostor kromˇeregistr˚u procesoru a z´asobn´ıku;,,linie v´ypoˇctu”,,,to, co bˇeˇz´ı” • program ... soubor pˇresnˇedefinovan´ehoform´atuobsahuj´ıc´ı instrukce, data a sluˇzebn´ıinformace nutn´eke spuˇstˇen´ı; ,,spustiteln´ysoubor na disku” ◦ pamˇet’ se pˇridˇeluje proces˚um. ◦ procesory se pˇridˇeluj´ı vl´akn˚um. ◦ vl´aknajednoho procesu mohou bˇeˇzetna r˚uzn´ych procesorech.
• kontext je pamˇet’ov´yprostor procesu, obsah registr˚ua datov´estruktury j´adrat´ykaj´ıc´ıse dan´ehoprocesu • jinak ˇreˇceno – kontext procesu je jeho stav. Kdyˇzsyst´emvykon´av´aproces, ˇr´ık´ase, ˇzebˇeˇz´ıv kontextu procesu. J´adro(klasick´e)obsluhuje pˇreruˇsen´ıv kontextu pˇreruˇsen´ehoprocesu.
• vl´aknase dostala do UNIXu aˇzpozdˇeji,p˚uvodnˇev nˇemexistovaly pouze procesy, kter´emˇelyz dneˇsn´ıhopohledu pouze jedno vl´akno.Moˇznostpouˇz´ıt v procesu v´ıcevl´aken byla zavedena, protoˇzese uk´azalo,ˇzeje vhodn´em´ıt v´ıceparaleln´ıch lini´ıv´ypoˇctunad sd´ılen´ymidaty. • pamˇet’ov´eprostory proces˚ujsou navz´ajemizolovan´e,ale procesy spolu mohou komunikovat. Pozdˇejise dozv´ıme,ˇzemohou i ˇc´asteˇcnˇesd´ıletpamˇet’. • procesy jsou entity na ´urovni j´adra,ale vl´akna mohou b´ytˇc´asteˇcnˇenebo zcela implementov´anaknihovn´ımifunkcemi. V pˇr´ıpadˇeimplementace pomoc´ı
58 knihovn´ıch fuknc´ıto znamen´a,ˇzevl´akna nemus´ıj´adrov˚ubec podporovat. S vl´akny je spojena menˇs´ıreˇzieneˇzs procesy.
• syst´emov´yproces, kter´ybˇeˇz´ına pozad´ıobvykle po celou dobu bˇehu syst´emu a zajiˇst’uje nˇekter´esyst´emov´esluˇzby (inetd, cron, sendmail. . . ) se naz´yv´a d´emon (angl. daemon). Syst´emBSD tedy nem´ave znaku ˇcerta,ale d´emona.
J´adro,reˇzimy, pˇreruˇsen´ı(klasick´yUNIX)
• procesy typicky bˇeˇz´ıv uˇzivatelsk´emreˇzimu • syst´emov´evol´an´ızp˚usob´ıpˇrepnut´ıdo reˇzimu j´adra • proces m´apro kaˇzd´yreˇzimsamostatn´yz´asobn´ık • j´adroje ˇc´ast´ıkaˇzd´ehouˇzivatelsk´ehoprocesu, nen´ıto samostn´y proces (procesy) • pˇrepnut´ına jin´yproces se naz´yv´a pˇrepnut´ıkontextu • obsluha pˇreruˇsen´ıse prov´ad´ıv kontextu pˇreruˇsen´ehoprocesu • klasick´ej´adro je nepreemptivn´ı
• j´adronen´ıoddˇelen´amnoˇzinaproces˚u,bˇeˇz´ıc´ıch paralelnˇes uˇziva- telsk´ymiprocesy, ale je ˇc´ast´ıkaˇzd´ehouˇzivatelsk´ehoprocesu. • pˇrechod mezi uˇzivatelsk´ymreˇzimema reˇzimemj´adranen´ıpˇrepnut´ıkontextu – proces bˇeˇz´ıpoˇr´adv tom sam´em
• pˇreruˇsen´yproces nemusel pˇreruˇsen´ıv˚ubec zp˚usobit • v reˇzimu j´adram˚uˇzeproces pˇristupovat i k adres´amj´adra,kter´az uˇzivatelsk´e- ho reˇzimu pˇr´ıstupn´anejsou; takt´eˇzm˚uˇzepˇristupovat k instrukc´ım(napˇr.in- strukce manipuluj´ıc´ıse stavov´ymregistrem), jejichˇzvykon´an´ıv uˇzivatelsk´em reˇzimu vede k chybˇe
• pˇreruˇsovac´ırutina se nem˚uˇzezablokovat, protoˇzet´ımby zablokovala proces; proces se totiˇzm˚uˇzezablokovat jen ze sv´evlastn´ıv˚ule.Modern´ıunixy dnes pouˇz´ıvaj´ıinterrupt vl´akna,v jejichˇzkontextu se mohou drivery zablokovat. • to, ˇzeklasick´eunixov´ej´adroje nepreemptivn´ıznamen´a,ˇze jeden proces nem˚uˇzezablokovat jin´yproces
59 • pˇriobsluze pˇreruˇsen´ıse m˚uˇzest´at,ˇze nastane dalˇs´ıpˇreruˇsen´ı.Pokud je jeho priorita vˇetˇs´ı,je procesorem pˇrijmuto. Posloupnost pˇrijmut´ych pˇreruˇsen´ıje uchov´anav z´asobn´ıkukontextov´ych vrstev. • u modern´ıch kernel˚uje situace ˇcastovelmi rozd´ıln´a– obsluha pˇre- ruˇsen´ı,preemptivnost kernelu atd.; k nˇekter´ymvˇecemse moˇzn´a dostaneme pozdˇejibˇehemsemestru
Vol´an´ısluˇzeba komunikace mezi procesy
• UNIX proces proces proces rozhran´ıvol´an´ıj´adra j´adro
• distribuovan´yOS
uˇzivatelsk´y uˇzivatelsk´y proces proces server server server j´adro j´adro j´adro j´adro j´adro
• pokud unixov´yproces vyˇzadujeproveden´ısyst´emov´esluˇzby, pomoc´ısyst´e- mov´ehovol´an´ıpˇred´aˇr´ızen´ıj´adru.J´adroje kus k´odu sd´ılen´yvˇsemiprocesy (ovˇsempˇr´ıstupn´yjen pro ty, kter´ejsou pr´avˇev reˇzimu j´adra).J´adrotedy nen´ısamostatn´yprivilegovan´yproces, ale vˇzdybˇeˇz´ıv r´amcinˇekter´ehopro- cesu (toho, kter´ypoˇz´adalj´adroo sluˇzbu,nebo toho, kter´ybˇeˇzelv okamˇziku pˇr´ıchodu pˇreruˇsen´ı). • komunikace mezi procesy v UNIXu je ˇreˇsena pomoc´ısyst´emov´ych vol´an´ı,je tedy zprostˇredkovan´aj´adrem. • aby to nebylo tak jednoduch´e,mohou existovat syst´emov´eprocesy (oznaˇco- van´ejako kernel threads), kter´ebˇeˇz´ıcelou dobu v reˇzimu j´adra.Naprost´a vˇetˇsinasyst´emov´ych proces˚uvˇsakbˇeˇz´ıv uˇzivatelsk´emreˇzimu a liˇs´ıse jen t´ım,ˇzemaj´ıvˇetˇs´ıpˇr´ıstupov´apr´ava. Pl´anovaˇcproces˚upˇrep´ın´amezi procesy a t´ımumoˇzˇnujebˇehv´ıceproces˚usouˇcasnˇei na jednom procesoru. Na multi- procesorov´ych poˇc´ıtaˇc´ıch pak funguje skuteˇcn´yparalelismus proces˚ua vl´aken (dokonce se proces m˚uˇzepˇripˇrepl´anov´an´ıdostat i na jin´yprocesor). • v distribuovan´emoperaˇcn´ımsyst´emu m´aj´adroobvykle formu mikroj´adra, tj. zajiˇst’uje pouze nejz´akladnˇejˇs´ısluˇzby ˇr´ızen´ıprocesoru, pˇridˇelov´an´ıpamˇeti
60 a komunikace mezi procesy. Vyˇsˇs´ı syst´emov´esluˇzby, kter´ejsou v UNIXu souˇc´ast´ıj´adra (napˇr.pˇr´ıstupk syst´emu soubor˚u)jsou realizov´any speci´aln´ımi procesy (servery) bˇeˇz´ıc´ımi v uˇzivatelsk´emreˇzimu procesoru. J´adropˇred´a poˇzadavek uˇzivatelsk´ehoprocesu pˇr´ısluˇsn´emu serveru, kter´ym˚uˇzebˇeˇzeti na jin´emuzlu s´ıtˇe. • dostupn´ych mikrokernel˚uje v dneˇsn´ıdobˇemnoho. M˚uˇzetezkusit napˇr´ıklad Minix (unix-like v´yukov´ysyst´em),pˇr´ıpadnˇesyst´emHURD, kter´ybˇeˇz´ınad mikroj´adremMach.
Syst´emov´avol´an´ı,funkce
• v UNIXu se rozliˇsuj´ı syst´emov´avol´an´ı a knihovn´ıfunkce. Toto rozliˇsen´ıdodrˇzuj´ıi manu´alov´estr´anky:sekce 2 obsahuje syst´emov´avol´an´ı(syscalls), sekce 3 knihovn´ıfunkce (library functions). – knihovn´ıfunkce se vykon´avaj´ıv uˇzivatelsk´em reˇzimu, stejnˇe jako ostatn´ık´odprogramu. – syst´emov´avol´an´ımaj´ıtak´etvar vol´an´ıfunkce. Pˇr´ısluˇsn´a funkce ale pouze zpracuje argumenty vol´an´ıa pˇred´aˇr´ızen´ı j´adrupomoc´ıinstrukce synchronn´ıhopˇreruˇsen´ı.Po n´avratu z j´adrafunkce uprav´ıv´ysledeka pˇred´aho volaj´ıc´ımu. • standardy tyto kategorie nerozliˇsuj´ı– z hlediska program´atora je jedno, zda urˇcitoufunkci provede j´adronebo knihovna.
• zjednoduˇsenˇelze ˇr´ıci,ˇze syst´emov´evol´an´ı je funkce, kter´ajen uprav´ı sv´e argumenty do vhodn´epodoby, pˇrepnereˇzimprocesoru a skuteˇcnoupr´aci nech´ana j´adru.Nakonec zase uprav´ıv´ysledek. Knihovn´ıfunkce m˚uˇzea nemus´ıvolat j´adro,ale vˇzdysama dˇel´anˇejakou netrivi´aln´ıˇcinnost v uˇzivatelsk´emreˇzimu.
• v assembleru je moˇzn´ezavolat vol´an´ıj´adrapˇr´ımo • API j´adraje definovan´ena ´urovni vol´an´ıfunkc´ıstandardn´ıknihovny, nikoliv na ´urovni pˇreruˇsen´ıa datov´ych struktur pouˇz´ıvan´ych tˇemitofunkcemi pro pˇred´an´ıˇr´ızen´ı j´adru. Mechanismus pˇrepnut´ı mezi uˇzivatelsk´ymreˇzimema reˇzimemj´adrase totiˇzm˚uˇzeliˇsitnejen v z´avislosti na hardwarov´eplatformˇe, ale i mezi r˚uzn´ymiverzemi syst´emu na stejn´emhardwaru.
61 N´avratov´ehodnoty syst´emov´ych vol´an´ı
• celoˇc´ıseln´an´avratov´ahodnota (int, pid t, off t, apod.) – >= 0 . . . operace ´uspˇeˇsnˇeprovedena – == -1 . . . chyba • n´avratov´ahodnota typu ukazatel – != NULL . . . operace ´uspˇeˇsnˇeprovedena – == NULL . . . chyba • po ne´uspˇeˇsn´emsyst´emov´emvol´an´ıje k´odchyby v glob´aln´ı promˇenn´e extern int errno; • ´uspˇeˇsn´evol´an´ınemˇen´ıhodnotu v errno! Je tedy tˇrebanejprve otestovat n´avratovou hodnotu a pak teprve errno. • chybov´ehl´aˇsen´ıpodle hodnoty v errno vyp´ıˇsefunkce void perror(const char *s ); • textov´ypopis chyby s dan´ymˇc´ıslemvr´at´ıfunkce char *strerror(int errnum );
• v Solarisu je hodnota errno ve skuteˇcnostiknihovnou libc definovan´ajako dereferencovan´ypointer na integer (specifick´ypro dan´yuserland thread) a hodnota se nastavuje ihned po v´ystupuz instrukce pro syst´emov´evol´an´ı. Napˇr.na i386 architektuˇreje hodnota errno po n´avratuz kernelu (po do- konˇcen´ıinstrukce sysenter) uloˇzenav registru eax (pˇredvol´an´ımv n´ıbylo ˇc´ıslosyscallu). Je to tedy knihovna libc kdo je zodpovˇedn´yza to, ˇzeprogram uvid´ıspr´avnouhodnotu errno. • funkce pro pr´acis vl´akny pthread * nenastavuj´ı errno, ale vrac´ıbud’ nulu (´uspˇech) nebo pˇr´ımok´odchyby.
• pro nˇekter´avol´an´ı m˚uˇzem´ıt smysl i n´avratov´ahodnota -1. Pak je tˇreba nejprve nastavit errno = 0 a po n´avratuzkontrolovat, zda se errno zmˇenilo. Napˇr.funkce strtol vrac´ıpˇrichybˇe0, coˇzje platn´ahodnota i pro spr´avn´y v´ysledek(a −1 je samozˇrejmˇeplatn´yv´ysledektak´e). • je tedy vˇzdynutn´esi pˇreˇc´ıstmanu´alovou str´ankupro pˇr´ıˇsluˇsn´evol´an´ınebo knihovn´ıfunkci
• pozn.: ´uspˇeˇsnostfunkc´ıze stdio.h je tˇrebatestovat pomoc´ı int ferror(FILE *stream ), protoˇzejinak nelze rozliˇsitmezi chybou a kon- cem streamu. Vzhledem k tomu, ˇzetyto funkce nepouˇz´ıv´ame(kromˇe printf a fprintf na stdout, resp. stderr), nemˇelibyste ji potˇrebovat.
62 Skupina funkc´ız err(3)
• pomocn´efunkce pro v´ypischybov´ych hl´aˇsen´ıa pˇr´ıpadn´e ukonˇcen´ıprogramu • m´ısto perror() a exit() v´amstaˇc´ıjedna funkce • void err(int status, const char *fmt, ...); – vyp´ıˇsejm´enoprogramu, form´atovan´yˇretˇezec,a chybu podle aktu´aln´ıhodnoty errno – ukonˇc´ıprogram s n´avratovou hodnotou ze status • void warn(const char *fmt, ...); – stejn´ejako err(), ale program neukonˇc´ı • existuj´ıdalˇs´ıpodobn´efunkce, viz manu´alov´astr´anka • funkce poch´azej´ıze 4.4BSD
• vˇetˇs´ıprogramy podobn´efunkce ˇcastonepouˇz´ıvaj´ı,napˇr´ıkladproto, ˇzestejnˇe potˇrebuj´ıprov´estr˚uzn´eukonˇcovac´ıpr´acepˇred skonˇcen´ımprogramu, takˇze maj´ıpodobn´efunkce vlastn´ı.Pro jin´eprogramy jsou ale tyto funkce ide´aln´ı, protoˇzemaj´ırozumn´yv´ystupa ˇsetˇr´ıˇr´adkyvaˇsehok´odu.
• tyto funkce nemus´ıb´ytvˇsude,napˇr´ıkladnejsou v libc.so pro Solaris 10 (ale jsou v Solarisu 11). Jsou na BSD syst´emech a v linuxov´ych distribuc´ıch. Tyto funkce nejsou souˇc´ast´ıSUS, takˇzeani na certifikovan´ych UNIX syst´emech se nelze spolehnout na jejich pˇr´ıtomnost. Reˇsen´ımjeˇ kontrolovat jejich existenci v pˇredkompilaˇcn´ımskriptu a pˇr´ıpadnˇem´ıtjejich verzi souˇc´ast´ızdrojov´ych k´od˚uprogramu pro pˇr´ıpadˇzenebudou na c´ılov´emsyst´emu nalezeny.
• pˇr´ıklad(viz tak´e err/err.c ):
#include
int main(void) { errno = 13; err(3, "ggr %s", "GRR"); printf("after err()\n"); return (0); }
63 $ ./a.out a.out: ggr GRR: Permission denied $ echo $? 3
Obsah
• ´uvod, v´yvoj UNIXu a C, program´atorsk´en´astroje • z´akladn´ıpojmy a konvence UNIXu a jeho API • pˇr´ıstupov´apr´ava, perifern´ızaˇr´ızen´ı,syst´emsoubor˚u • manipulace s procesy, spouˇstˇen´ıprogram˚u • sign´aly • synchronizace a komunikace proces˚u • s´ıt’ov´akomunikace • vl´akna,synchronizace vl´aken • ??? - bude definov´anopozdˇeji,podle toho kolik zbyde ˇcasu
64 Users and groups
beran:x:1205:106:Martin Beran:/home/beran:/bin/bash
The fields, in order from left to right: user name, hashed password (today in /etc/shadow or elsewhere), user ID (aka UID); primary group ID (aka GID), full name, home directory, login shell Note that a superuser (root) has always UID 0.
sisal:*:106:forst,beran
The fields, in order from left to right: group name, group password (not used today), group ID (GID), list of group members
• informace o uˇzivatel´ıch v souborech /etc/passwd, a /etc/group jsou zpra- cov´av´any r˚uzn´ymisyst´emov´ymiprogramy, napˇr. login (pˇrihl´aˇsen´ıdo syst´e- mu na z´akladˇeuˇzivatelsk´ehojm´enaa hesla) nebo su (zmˇenaidentity). J´adro o tˇechto souborech nic nev´ı,pouˇz´ıv´apouze numerickou identifikaci uˇzivatele a skupiny. • dnes jiˇzhesla nejsou z bezpeˇcnostn´ıch d˚uvod˚upˇr´ımo v /etc/passwd, ale napˇr´ıklad v /etc/shadow, kter´ybˇeˇzn´emu uˇzivateli pˇr´ıstupn´ynen´ı, pouze uˇzivatel root m´apr´avo pro ˇcten´ı a z´apis. Tedy pouze privilegovan´epro- gramy jako login nebo sshd mohou z tohoto souboru ˇc´ıstnebo zapisovat (program passwd bˇeˇz´ıpod uˇzivatelem root d´ıky setuid bitu nastaven´emna souboru programu, viz pozn´amkyna stranˇe 71). Takto jsou hesla separo- van´aod veˇrejnˇepˇr´ıstupn´ych informac´ı,nav´ıcsoubor kter´yhesla obsahuje, je ukl´ad´av zahaˇsovan´e/zaˇsifrovan´eformˇe,takˇzenejsou pˇr´ımoˇciteln´a.Na BSD syst´emech (napˇr.FreeBSD, Mac OS X) se m´ısto /etc/shadow pouˇz´ıv´a soubor /etc/master.passwd. • Soubor /etc/shadow je podobnˇestrukturovan´yjako /etc/passwd. Jeden z´aznamobsahuje vˇetˇsinoun´asleduj´ıc´ıpoloˇzky(Solaris): uˇzivatelsk´ejm´eno, zahaˇsovan´eheslo (spolu s indik´atoremˇzedan´y´uˇcetje zablokovan´y),posledn´ı modifikace hesla, minimum dn´ıpoˇzadovan´ych mezi zmˇenouhesla, maximum dn´ıpo kter´eje heslo platn´e,poˇcetdn´ıpo kter´ych je uˇzivatel varov´ano expi- raci hesla, poˇcetpovolen´ych dn´ıneaktivity uˇzivatele, absolutn´ıˇcasexpirace uˇzivatele, poˇcetne´uspˇeˇs´ych pokus˚uo nalogov´an´ıtohoto uˇzivatele. • Hesla v /etc/shadow jsou uloˇzenatakov´ymzp˚usobem, aby pokud se povede nˇekomu soubor z´ıskat, mˇel zt´ıˇzenoupr´acipˇriodhadov´an´ı hesel. P˚uvodn´ı
65 (cleartext) heslo se proˇzenejednosmˇernoukryptografickou funkc´ı(kter´aje nav´ıcparametrizovateln´a,ˇc´ımˇzse v´ypoˇcetn´ıa prostorov´asloˇzitostpro ´utok hrubou silou jeˇstˇezv´yˇs´ı)a uloˇz´ıse do /etc/shadow v t´etoformˇe.Ovˇeˇrov´an´ı hesla pak funguje tak ˇze,se na cleartext heslo aplikuje dan´afunkce s dan´ymi parametry a v´ysledekse porovn´as polem hesla v /etc/shadow. Pokud jsou stejn´e,probˇehlaautentizace ´uspˇeˇsnˇe.P˚uvodnˇenavrˇzen´afunkce pˇrestalas roz- vojem procesor˚ustaˇcit,takˇzese dnes pouˇz´ıvaj´ıfunkce MD5, SHA1, Blowfish a dalˇs´ı.Poloˇzka hesla v /etc/shadow je pak vnitˇrnˇestrukturovan´apomoc´ı speci´aln´ıch znak˚u,takˇzeprogramy ovˇeˇruj´ıc´ıheslo v´ı,jakou funkci a s jak´ymi parametry pouˇz´ıt.Vˇetˇsinasyst´em˚uumoˇzˇnujeglob´aln´ıkonfiguraci pouˇzit´ych funkc´ıa jejich parametr˚u.
• existuj´ı i jin´esyst´emy, kter´e(nejen) pro autentizaci /etc/passwd nemus´ı v˚ubec pouˇz´ıvat, napˇr´ıkladNIS (Network Information Service) nebo LDAP (Lightweight Directory Access Protocol).
• skupina uˇzivatele uveden´av /etc/passwd se naz´yv´a prim´arn´ı. Tuto skupi- novou identifikaci dostanou napˇr.soubory vytvoˇren´eprocesy uˇzivatele. Dalˇs´ı skupiny, ve kter´ych je uˇzivatel uveden v souboru /etc/group, jsou doplˇnkov´e (supplementary) a rozˇsiˇruj´ıpˇr´ıstupov´apr´ava uˇzivatele: skupinov´ypˇr´ıstupje povolen ke vˇsemobjekt˚um,jejichˇzskupinov´yvlastn´ıkje roven bud’ prim´arn´ı, nebo jedn´ez doplˇnkov´ych skupin. • p˚uvodnˇemˇelv UNIXu kaˇzd´yuˇzivatel vˇzdyaktivn´ıpouze jednu skupinovou identitu. Po nalogov´an´ıbyl ve sv´eprim´arn´ıskupinˇe,pro z´ısk´an´ıpr´avjin´e skupiny bylo tˇrebase do n´ıpˇrepnoutpˇr´ıkazem newgrp (skupinov´aobdoba su, ˇr´ıd´ıse obsahem souboru /etc/group), kter´yspustil nov´yshell. • v novˇejˇs´ıch UNIXech nen´ıtˇrebapro pˇr´ıstupk soubor˚ummˇenitprim´arn´ısku- pinovou identitu procesu, pokud uˇzivatel patˇr´ıdo potˇrebn´eskupiny. Zmˇena identity je nutn´a,pouze kdyˇzchceme vytv´aˇretsoubory s jinou skupinovou identitou, neˇzje prim´arn´ıskupina uˇzivatele. Lok´alnˇepro urˇcit´yadres´aˇrtoho lze dos´ahnoutnastaven´ımskupinov´ehovlastn´ıka adres´aˇrena poˇzadovanou skupinu a nastaven´ımbitu SGID v pˇr´ıstupov´ych pr´avech adres´aˇre– to plat´ı pro syst´emy zaloˇzen´ena System V. U BSD staˇc´ızmˇenitpoˇzadovanou skupinu u adres´aˇre.Pˇr´ıkladvytvoˇren´ıtakov´ehoadres´aˇrena Solarisu (pˇr´ıkaz chown mus´ıb´yt proveden pod uˇzivatelem root):
# mkdir mydir # chown :lidi mydir # ls -ald mydir drwxr-xr-x 2 root lidi 4 Nov 2 20:01 mydir # cd mydir/ mydir # touch foo mydir # ls -ald foo -rw-r--r-- 1 root root 0 Nov 2 20:01 foo mydir # chmod g+s . mydir # ls -ald . drwxr-sr-x 2 root lidi 4 Nov 2 20:01 . mydir # touch bar mydir # ls -ald bar -rw-r--r-- 1 root lidi 0 Nov 2 20:01 bar mydir #
66 • druh´apoloˇzka v ˇr´adc´ıch /etc/group obsahuje zak´odovan´eskupinov´eheslo pouˇz´ıvan´epˇr´ıkazem newgrp, to se jiˇzdnes nepouˇz´ıv´a.Napˇr´ıkladna FreeBSD je pˇr´ıkaz newgrp pˇr´ıstupn´yuˇzjen superuˇzivateli (kv˚ulivol´an´ı setgroups).
Name service switch
• today’s systems are not confined to only using /etc/passwd and /etc/groups • such systems have databases (passwd, groups, protocols, . . . ) • database data come from sources (files, DNS, NIS, LDAP, . . . )
• file nsswitch.conf defines what databases use what sources • library functions must support this, obviously • it is possible to combine some sources, eg. users may be first be searched in /etc/passwd, then in LDAP • came first with Solaris, other systems took over the idea
• syst´emy maj´ıtypicky manu´alovou str´anku nsswitch.conf(4), kde lze nal´ezt podrobnosti v z´avislostina konkr´etn´ımoperaˇcn´ımsyst´emu, vˇcetnˇeAPI, po- moc´ıkter´ehose pracuje s jednotliv´ymidatab´azemi.Napˇr´ıklad,s datab´az´ı passwd pracuj´ıstandardn´ıvol´an´ı getpwnam(3), getpwent(3) a dalˇs´ı- nen´ı proto potˇrebazpracov´avat tyto soubory (datab´aze)sami. • zde je ˇc´astskuteˇcn´ehosouboru nsswitch.conf ze stroje u-us:
passwd: files ldap group: files ldap
# You must also set up the /etc/resolv.conf file for DNS name # server lookup. See resolv.conf(4). hosts: files dns
# Note that IPv4 addresses are searched for in all of the # ipnodes databases before searching the hosts databases. ipnodes: files dns
networks: files protocols: files rpc: files ethers: files
67 Z´ısk´av´an´ı´udaj˚uo uˇzivatel´ıch/skupin´ach
• struct passwd *getpwnam(const char *name) vrac´ıstrukturu reprezentuj´ıc´ıuˇzivatele.
• struct passwd *getpwuid(uid t uid) vrac´ıstrukturu reprezentuj´ıc´ıuˇzivatele podle UID.
• void setpwent(void) • void endpwent(void) • struct passwd *getpwent(void) slouˇz´ık proch´azen´ıpoloˇzekv datab´aziuˇzivatel˚u. setpwent nastav´ıpozici na zaˇc´atek, getpwent z´ısk´adalˇs´ıpoloˇzku, endpwent dealokuje prostˇredkypouˇzit´epro proch´azen´ı seznamu.
• tyto funkce funguj´ınez´avislena tom jak z jak´edatab´azebyly z´ısk´any infor- mace o dan´emuˇzivateli. • vˇsechny tyto funkce jsou souˇc´ast´ıPOSIX 1003.1-2008 (sekce XSH) • setpwent je tˇrebazavolat pˇredprvn´ımvol´an´ım getpwent
• analogicky exituj´ıfunkce getgrnam a getgrent kter´ez´ısk´avaj´ıinformace o skupin´ach.
• pro prohled´av´an´ıa v´ypisdatabaz´ılze pouˇz´ıtprogram getent. Napˇr. k nale- zen´ız´aznamu uˇzivatele a skupiny root:
$ getent passwd root root:x:0:0:Super-User:/root:/sbin/sh $ getent group root root::0:
68 Testov´an´ıpˇr´ıstupov´ych pr´av • uˇzivatel je identifikov´anˇc´ıslemuˇzivatele (UID) a ˇc´ıslyskupin, do kter´ych patˇr´ı(primary GID, supplementary GIDs). • tuto identifikaci dˇed´ıkaˇzd´yproces dan´ehouˇzivatele.
• soubor S m´avlastn´ıka (UIDS) a skupinov´ehovlastn´ıka (GIDS). • algoritmus testov´an´ıpˇr´ıstupov´ych pr´avpro proces P (UIDP , GIDP ,SUPG) a soubor S(UIDS, GIDS): Jestliˇze pak P roces m´av˚uˇci Souboru
if(UIDP == 0) . . . vˇsechna pr´ava
else if(UIDP == UIDS) . . . pr´ava vlastn´ıka
else if(GIDP == GIDS ||
GIDS ∈ SUPG) . . . pr´ava ˇclenaskupiny else . . . pr´ava ostatn´ıch
• procesy superuˇzivatele root mohou mˇenitsvoji uˇzivatelskou a skupinovou identitu. Toho vyuˇz´ıv´anapˇr.proces login, kter´ybˇeˇz´ıjako root a po zkon- trolov´an´ıjm´enaa hesla spust´ıshell s uˇzivatelskou identitou (pomoc´ıvol´an´ı setuid – viz dalˇs´ıslajdy). • z algoritmu plyne, ˇzepro roota nen´ı relevantn´ı nastaven´ı pr´av(m´avˇzdy neomezen´ypˇr´ıstup). Pokud se shoduje uˇzivatel, nepouˇzij´ı se nikdy pr´ava skupiny nebo ostatn´ıch, i kdyˇzpovoluj´ıv´ıceneˇzuˇzivatelsk´apr´ava. Podobnˇe pr´ava ostatn´ıch se nepouˇzij´ı, jestliˇzese shoduje skupinov´aidentita. Tedy pokud m´am˚ujsoubor nastaveny pr´ava ---rwxrwx, nemohu ho ˇc´ıst, zapisovat ani spustit, dokud nastaven´ıpr´avnezmˇen´ım.
• ˇc´ımd´alv´ıcsyst´em˚use odkl´an´ıod klasick´ehomodelu, kdy mnoho proces˚u bˇeˇzelopod uˇzivatelem s UID 0 a pˇri bezpeˇcnostn´ıchybˇev takov´eaplikaci ˇcasto´utoˇcn´ıkz´ıskal vl´adunad cel´ymsyst´emema zav´adˇej´ımodely jako je least privilege model v Solarisu nebo privilege separation a systrace v OpenBSD. • opakov´an´ız prvn´ıhoroˇcn´ıku– aby uˇzivatel mohl smazat soubor, mus´ım´ıt pr´avo z´apisudo dan´eho adres´aˇre, protoˇzeto je ten “soubor”, co se mˇen´ı. Pr´ava k mazan´emu souboru nejsou podstatn´a; to ˇzev´asshell upo- zorn´ı,ˇzemaˇzetesoubor, ke kter´emu nem´atepr´avo z´apisu, je pouze vˇectoho shellu. Je to logick´e– pokud si nastav´ıtesoubor jako read-only, shell usuzuje, ˇzeho asi norm´alnˇemazat nechcete. Viz pˇr´ıklad pod t´ımto odstavcem. Uni- xov´esyst´emy nemaj´ıdelete-like operaci na soubor, smaz´an´ısouboru nastane automaticky tehdy, kdyˇzna soubor nen´ıˇz´adn´yodkaz z adres´aˇrov´e struktury, a nikdo soubor jiˇznem´aotevˇren´y.
69 $ whoami janp $ ls -ld janp-dir drwx------2 janp staff 512 Mar 23 12:12 janp-dir/ $ ls -l janp-dir total 0 -rw-r--r-- 1 root root 0 Mar 23 12:11 root_wuz_here.txt $ rm janp-dir/root_wuz_here.txt rm: janp-dir/root_wuz_here.txt: override protection 644 (yes/no)? yes $ ls janp-dir/root_wuz_here.txt janp-dir/root_wuz_here.txt: No such file or directory
• pokud ale root vytvoˇr´ı v adres´aˇri janp-dir sv˚ujpodadres´aˇra tam vloˇz´ı sv˚ujsoubor, uˇzivatel janp uˇznem˚uˇzeadres´aˇr janp-dir a jeho obsah smazat, protoˇze: – podadres´aˇrnelze smazat protoˇzenen´ıpr´azdn´y – a dan´ysoubor nelze smazat z toho d˚uvodu, ˇze janp nen´ıvlastn´ıkem podadres´aˇre. • Pokud odeberu adres´aˇriread bit, nen´ımoˇzn´eˇc´ıstjeho obsah, tedy prov´adˇet v´ypissoubor˚uv nˇemobsaˇzen´ych. Pokud ale zn´amjm´eno souboru v adres´aˇri a execute bit je nastaven, mohu soubor pˇreˇc´ıst:
$ mkdir foo $ ls -ald foo drwxr-xr-x 2 vladimirkotal staff 68 Nov 5 14:37 foo $ touch foo/bar $ file foo/bar foo/bar: empty $ ls foo bar $ chmod u-r foo $ ls foo ls: foo: Permission denied $ file foo/bar foo/bar: empty
• existuje situace, kdy ani pr´avo z´apisu(a execute) pro adres´aˇrnestaˇc´ı.To se pouˇz´ıv´au tmp adres´aˇr˚u,do kter´ych m˚uˇzekaˇzd´yps´at,ale nen´ıˇz´adouc´ı situace, kdy by si uˇzivatel´enavz´ajemmazali soubory. K tomu se pouˇz´ıv´atzv. sticky bit (01000). Syst´emy maj´ıvetˇsinoumanu´alovou str´anku sticky, kde je funkce sticky bitu popsan´a.Na v´ypisu ls je oznaˇcovan´yjako t:
$ ls -ld /tmp drwxrwxrwt 7 root root 515 Mar 23 12:22 /tmp
70 Re´aln´ea efektivn´ıUID/GID • u kaˇzd´ehoprocesu se rozliˇsuje: – re´aln´eUID (RUID) – skuteˇcn´yvlastn´ıkprocesu – efektivn´ıUID (EUID) – uˇzivatel, jehoˇzpr´ava proces pouˇz´ıv´a – uschovan´eUID (saved SUID) – p˚uvodn´ıefektivn´ıUID • podobnˇese rozliˇsujere´aln´e,efektivn´ıa uschovan´eGID procesu. • obvykle plat´ı RUID==EUID && RGID==EGID. • prop˚ujˇcov´an´ıpr´av . . . spuˇstˇen´ıprogramu s nastaven´ym SUID (set user ID) bitem zmˇen´ıEUID a saved UID procesu na UID vlastn´ıka programu, RUID se nezmˇen´ı. • podobnˇeSGID bit ovlivˇnujeEGID procesu. • pˇrikontrole pˇr´ıstupov´ych pr´avse pouˇz´ıvaj´ıvˇzdy EUID, EGID a supplementary GIDs
• bity SUID a SGID se pouˇz´ıvaj´ıu program˚u,kter´epotˇrebuj´ıvˇetˇs´ıpˇr´ıstupov´a pr´ava, neˇzm´auˇzivatel, jenˇzje spouˇst´ı.Pˇr´ıkladem je program passwd, kter´y mus´ıaktualizovat soubory /etc/passwd a /etc/shadow, kde ten prvn´ıne- m˚uˇzebˇeˇzn´yuˇzivatel mˇenita druh´yz nich ani ˇc´ıst.Dalˇs´ıpˇr´ıkladje program su. Ten mus´ım´ıtpr´avo libovolnˇezmˇenituˇzivatelskou a skupinovou identitu, coˇzje privilegium proces˚us UID 0.
• SUID a SGID programy by mˇelyb´ytpeˇclivˇenaprogramov´any, aby dovolily pouze ty operace, pro kter´ejsou urˇceny, a neumoˇznilyzneuˇz´ıtjejich privilegia pro neopr´avnˇen´eakce (napˇr.spuˇstˇen´ırootovsk´ehoshellu). Zkuˇsenostukazuje, ˇzetyto programy jsou jednou z nejˇcastˇejˇs´ıch pˇr´ıˇcinbezpeˇcnostn´ıch probl´em˚u UNIXov´ych syst´em˚u.
• z´akladn´ım pravidlem pro SUID programy je: nepiˇste je pokud to nen´ı opravdu nezbytn´e.Je to typick´em´ıstopro generov´an´ıbezpeˇcnostn´ıch chyb protoˇzedobˇre,tj. bezpeˇcnˇe,napsat sloˇzitˇejˇs´ıSUID program nen´ıjednoduch´e. • toto jsou pravidla pro zmˇeny:
– beˇzn´yuˇzivatel nem˚uˇzezmˇenitsv´eRUID nebo uschovan´eSUID (vyj´ımka je pˇrivol´an´ı exec, viz strana 131) – proces m˚uˇzevˇzdyzmˇenitsv´eEUID na to z RUID nebo z uschovan´eho UID. Toto zaruˇcuje,ˇzev SUID programu je moˇzn´elibovolnˇemˇenitEUID mezi t´ımp˚uvodn´ımkter´ymproces z´ıskal pr´ava vlastn´ıka a mezi UID skuteˇcn´ehouˇzivatele kter´ydan´yproces spustil.
71 – root m˚uˇzevˇsechno, a kdyˇzzmˇen´ıRUID, tak se z´aroveˇnzmˇen´ıi ucho- van´eUID – nemˇeloby smysl mˇenitjen jedno z nich kdyˇzkter´ekoli m˚uˇzetepouˇz´ıtpro nastaven´ıEUID.
Identifikace vlastn´ıka procesu
• uid t getuid(void) vrac´ıre´aln´euser ID volaj´ıc´ıhoprocesu. • uid t geteuid(void) vrac´ıefektivn´ıuser ID volaj´ıc´ıhoprocesu. • gid t getgid(void) vrac´ıre´aln´egroup ID volaj´ıc´ıhoprocesu. • gid t getegid(void) vrac´ıefektivn´ıgroup ID volaj´ıc´ıhoprocesu. • int getgroups(int gidsz, gid t glist []) – do glist d´anejv´yˇse gidsz supplementary group IDs volaj´ıc´ıhoprocesu a vr´at´ıpoˇcet vˇsech GIDs procesu.
• pro re´aln´eUID je vol´an´ı getuid, vol´an´ı getruid neexistuje • getgroups: kdyˇz gidsz == 0, jen vr´at´ı poˇcetskupin. Kdyˇz 0 < gidsz < #skupin, vr´at´ı -1. • v UNIXu je mnoho typ˚ujako uid_t, gid_t, size_t, apod. Vesmˇesjsou to celoˇc´ıseln´etypy, ˇcastoje najdete v /usr/include/sys/types.h • Solaris m´apˇr´ıkaz pcred, kter´yjednoduˇsezobraz´ı informace o identifikaci procesu:
$ pcred 5464 5464: e/r/suid=1993 e/r/sgid=110 groups: 33541 41331 110
72 Zmˇenavlastn´ıka procesu
• int setuid(uid t uid ); – v procesu s EUID == 0 nastav´ıRUID, EUID i saved-SUID na uid – pro ostatn´ıprocesy nastavuje jen EUID, a uid mus´ıb´yt bud’ rovn´eRUID nebo uschovan´emu SUID
• int setgid(gid t gid ); obdoba setuid, nastavuje group-IDs procesu. • int setgroups(int ngroups, gid t *gidset ) nastavuje supplementary GIDs procesu, m˚uˇze b´ytpouˇzitojen superuˇzivatelsk´ymprocesem.
• o nastaven´ıUID pro proces s EUID 0 viz tak´epozn´amkyna stranˇe 71. • co v´yˇseuveden´etedy znamen´a:proces s efektivn´ımi pr´avysuperuˇzivatele m˚uˇzelibovolnˇemˇenitidentitu. Ostatn´ıprocesory mohou pouze stˇr´ıdatsv´a re´aln´aa efektivn´ıpr´ava.
• program login vyuˇz´ıv´avol´an´ı setuid • pokud chce process s UID == 0 zmˇenit svou identitu, mus´ınejprve volat setgid a setgroups. Teprve pak lze zavolat setuid. Pˇriopaˇcn´em poˇrad´ı vol´an´ıby proces po proveden´ı setuid uˇznemˇelpr´ava na setgid a setgroups. • setgroups nen´ıuvedeno v UNIX 98 ani UNIX 03. • RUID/EUID jsou uloˇzen´ev z´aznamu tabulky proces˚upro pˇr´ısluˇsn´yproces a z´aroveˇnv tzv. u-area (viz napˇr´ıklad[Bach]). EUID v tabulce proces˚use naz´yv´ajiˇzzm´ınˇen´euschovan´eUID, neboli saved UID. Jak jiˇzbylo ˇreˇceno, uschovan´eUID se pouˇz´ıv´apro kontrolu, kdyˇzse proces chce vr´atitk EUID, se kter´ymbyl spuˇstˇen(po t´e,co doˇcasnˇenastavil sv´eEUID na UID uˇzivatele, kter´yproces spustil, tj. na RUID).
• pokud tedy jako root vytvoˇr´ıteSUID program a v nˇemzavol´ate setuid pro jak´eholiUID mimo 0, jiˇzse v programu k EUID==0 nem˚uˇzetevr´atit(je to logick´e– pˇredstavte si situaci, kdy se uˇzivatel loguje do syst´emu). V tom pˇr´ıpadˇebyste museli pouˇz´ıtvol´an´ı seteuid, kter´enastavuje pouze EUID.
• pˇr´ıklad: setuid/screate-file.c
73 Syst´emsoubor˚u
• adres´aˇretvoˇr´ıstrom, spolu se soubory acyklick´ygraf (na jeden soubor m˚uˇzeexistovat v´ıceodkaz˚u). • kaˇzd´yadres´aˇrnav´ıcobsahuje odkaz na sebe ’.’ (teˇcka) a na nadˇrazen´yadres´aˇr’..’ (dvˇeteˇcky). • pomoc´ırozhran´ısyst´emu soubor˚use pˇristupujei k dalˇs´ım entit´amv syst´emu: – perifern´ızaˇr´ızen´ı – pojmenovan´eroury – sokety – procesy (/proc) – pamˇet’ (/dev/mem, /dev/kmem) – pseudosoubory (/dev/tty, /dev/fd/0,. . . ) • z pohledu j´adraje kaˇzd´yobyˇcejn´ysoubor pole bajt˚u. • vˇsechny (i s´ıt’ov´e)disky jsou zapojeny do jednoho stromu.
• zaˇr´ızen´ı, soubory v /proc, termin´aly, pamˇet’ atd. jsou vˇsechno jeden typ soubor˚u- speci´aln´ısoubory. Dalˇs´ıtypy soubor˚u- regul´arn´ısoubor (hardlink), adres´aˇr,pojmenovan´aroura, socket, symbolick´ylink. • novˇevytvoˇren´yadres´aˇrm´ana sebe 2 odkazy – jeden z nadˇrazen´ehoadres´aˇre, a jeden s´amna sebe, ’.’:
$ mkdir test $ ls -ld test drwx------2 janp staff 512 Mar 23 12:46 test
• root m˚uˇzev nˇekter´ych syst´emech strukturu adres´aˇr˚uzacyklit, ale t´ımzmate utility pro proch´azen´ı filesyst´emu; moc se cyklick´estruktury nepouˇz´ıvaj´ı. Symbolick´elinky na adres´aˇrefunguj´ıvˇsude. • pojmenovan´eroury (viz strana 94) lze pouˇz´ıti mezi procesy, kter´enejsou pˇr´ıbuzenskyspˇr´ıznˇen´e.Jinak funguj´ıstejnˇejako nepojmenovan´eroury. • zmiˇnovan´esokety jsou v dom´enˇeUNIX, tj. slouˇz´ıpro komunikaci v r´amci jednoho syst´emu. Sokety z dom´eny INET, pˇreskter´eprob´ıh´as´ıt’ov´akomuni- kace, se v syst´emu soubor˚uneobjevuj´ı.S´ıt’ov´akomunikace zaˇc´ın´ana stranˇe 179.
• debuggery pouˇz´ıvaj´ıpamˇet’ov´eobrazy proces˚udostupn´ev /proc. Ve vˇetˇsinˇe unix-like syst´em˚uobsahuje podstrom /proc ´udaje o j´adrusyst´emu a bˇeˇz´ıc´ıch procesech ve formˇetextov´ych soubor˚u.
74 • dneˇsn´ımodern´ıunixy m´ıvaj´ıspeci´aln´ıfilesyst´em devfs, jehoˇzobsah odr´aˇz´ı aktu´aln´ıkonfiguraci syst´emu co se t´yˇcepˇripojen´ych zaˇr´ızen´ı.Tj. napˇr.pˇri pˇripojen´ıUSB sticku se v /dev objev´ıpˇr´ısluˇsn´ediskov´ezaˇr´ızen´ı.Po fyzick´em odpojen´ızaˇr´ızen´ıodkaz z adres´aˇrov´estruktury opˇetzmiz´ı.
Jednotn´yhierarchick´ysyst´emsoubor˚u
/
dev etc usr home tty
• svazek (angl. file system) je ˇc´astsouborov´ehosyst´emu, kterou lze samostatnˇe vytvoˇrit,pˇripojit, zruˇsit...Kaˇzd´yfilesyst´emm˚uˇzem´ıtjinou vnitˇrn´ıstrukturu (s5, ufs, ext2, xfs, atd.) a m˚uˇzeb´ytuloˇzenna lok´aln´ımdisku nebo na jin´em poˇc´ıtaˇcia pˇr´ıstupn´ypo s´ıti(nfs, afs). • po startu j´adraje pˇripojen´yjen koˇrenov´yfilesyst´em,dalˇs´ıfilesyst´emy se za- pojuj´ıdo hierarchie na m´ısta adres´aˇr˚upˇr´ıkazem mount. Tento pˇr´ıkaz je moˇzn´e spustit ruˇcnˇe(uˇzivatel root libovolnˇe, ostatn´ıpouze na nˇekter´ych syst´emech a s omezen´ımi)nebo automaticky bˇeheminicializace syst´emu, kdy se typicky ˇr´ıd´ıobsahem souboru /etc/fstab. Pˇredzastaven´ım syst´emu se filesyst´emy odpojuj´ıpˇr´ıkazem umount. • dalˇs´ımoˇznostje pˇripojen´ıfilesyst´emu na ˇz´adostpˇriprvn´ımpˇr´ıstupua jeho odpojen´ıpo urˇcit´edobˇeneˇcinnosti.Tuto funkci zajiˇst’uje d´emon automounter (autofs, automount, amd). • UNIX nem´aˇz´adn´eA, B, C, D. . . disky apod.
75 Typick´askladba adres´aˇr˚u
/bin . . . z´akladn´ısyst´emov´epˇr´ıkazy /dev . . . speci´aln´ısoubory (zaˇr´ızen´ı,devices) /etc . . . konfiguraˇcn´ıadres´aˇr /lib . . . z´akladn´ısyst´emov´eknihovny /tmp . . . veˇrejn´yadres´aˇrpro doˇcasn´esoubory /home . . . koˇrendomovsk´ych adres´aˇr˚u /var/adm . . . administrativn´ısoubory (ne na BSD) /usr/include . . . hlaviˇckov´esoubory pro C /usr/local . . . lok´alnˇeinstalovan´ysoftware /usr/man . . . manu´alov´estr´anky /var/spool . . . spool (poˇsta,tisk,...)
• v /bin, /lib, /sbin jsou pˇr´ıkazy a knihovny potˇrebn´epˇristartu syst´emu, kdy je pˇripojen pouze koˇrenov´yfilesyst´em.Ostatn´ıpˇr´ıkazy a knihovny jsou typicky v /usr/bin, /usr/lib a /usr/sbin. /usr b´yv´aˇcastosamostatn´y filesyst´em,ˇc´ımˇzjeho obsah nen´ıdostupn´ybˇehemstartu syst´emu.
• s v sbin znaˇc´ı,,system”, ne SUID. Jsou to bin´arky, u kter´ych se pˇredpokl´ad´a, ˇzeje bˇeˇzn´yuˇzivatel nebude typicky potˇrebovat.
• podstrom /usr obsahuje soubory, kter´ese nemˇen´ı pˇribˇeˇzn´emprovozu a nejsou z´avisl´ena konkr´etn´ımpoˇc´ıtaˇci.Proto by mˇelj´ıtsd´ıletread-only. Na sv´estanici doma ho ale vˇetˇsinoubudete m´ıtread-write.
• /lib typicky obsahuje knihovny potˇrebn´epro programy z koˇrenov´ehosvazku. Pokud by vˇsechny knihovny byly v /usr/lib a /usr byl samostatn´ysvazek, probl´ems pˇripojen´ım /usr by kompletnˇeochromil cel´ysyst´em,protoˇzeby neˇslospustit nic. Nˇekdyto syst´emy ˇreˇs´ıtak, ˇzekoˇrenov´ysvazek obsahuje sadu z´akladn´ıch program˚u,kter´ejsou staticky slinkovan´e.Napˇr´ıkladFreeBSD m´a takov´ebin´arkyv adres´aˇri /rescue, m´aale i samostatn´eadres´aˇre /lib a /usr/lib. • v podstromu /var jsou data, kter´ase za provozu mˇen´ıa jsou specifick´apro kaˇzd´ypoˇc´ıtaˇc. • r˚uzn´esyst´emy i instalace jednoho syst´emu se ˇcastoliˇs´ı.
• hier(7) na FreeBSD a Linuxu popisuje adres´aˇrovou hierarchii tohoto syst´emu, Solaris m´a filesystem(5).
76 Pˇr´ıstupk perifern´ımzaˇr´ızen´ım
• adres´aˇr /dev obsahuje speci´aln´ısoubory zaˇr´ızen´ı.Proces otevˇre speci´aln´ısoubor syst´emov´ymvol´an´ım open() a d´ale komunikuje se zaˇr´ızen´ımpomoc´ıvol´an´ı read(), write(), ioctl(), apod. • speci´aln´ısoubory se dˇel´ına – znakov´e . . . data se pˇren´aˇs´ıpˇr´ımomezi procesem a ovladaˇcem zaˇr´ızen´ı,napˇr.s´eriov´eporty – blokov´e . . . data proch´az´ısyst´emovou vyrovn´avac´ıpamˇet´ı (buffer cache) po bloc´ıch pevnˇedan´evelikosti, napˇr.disky • speci´aln´ısoubor identifikuje zaˇr´ızen´ıdvˇemaˇc´ısly – hlavn´ı(major) ˇc´ıslo . . . ˇc´ısloovladaˇcev j´adru – vedlejˇs´ı(minor) ˇc´ıslo . . . ˇc´ıslov r´amcijednoho ovladaˇce
• vyrovn´avac´ıpamˇeti (cache) urychluj´ıperifern´ıoperace. Pˇriˇcten´ıse data hle- daj´ınejprve v bufferu. Teprve kdyˇznejsou k dispozici, tak se ˇctou z disku. Pˇri pˇr´ıˇst´ımˇcten´ıstejn´ehobloku jsou data v bufferu. Pˇriz´apisu se data uloˇz´ıdo bufferu. Na disk je syst´empˇrep´ıˇsepozdˇeji.Lze si vynutit i okamˇzit´yz´apisdat na disk. Dnes jiˇzcache typicky nen´ısamostatn´astruktura, vˇseje zastˇreˇseno modulem vitru´aln´ıpamˇeti.
• disky v UNIXu jsou obvykle pˇr´ıstupn´epˇresznakov´e(pouˇz´ıvan´epˇri mkfs – vy- tvoˇren´ısvazku – a fsck – kontrola konzistence) i blokov´erozhran´ı(pouˇz´ıvan´e pˇrinorm´aln´ımprovozu syst´emu soubor˚u).Nˇekter´esyst´emy (FreeBSD) ale uˇz v /dev v˚ubec soubory pro blokov´azaˇr´ızen´ınemaj´ı,pouze znakov´a. • dˇr´ıve musel administr´atorsyst´emu po zmˇenˇehardwarov´ekonfigurace upravit obsah adres´aˇre /dev skriptem MAKEDEV nebo ruˇcnˇe.Dnes (Linux, IRIX, Free- BSD, Solaris, . . . ) jiˇzspeci´aln´ısoubory dynamicky vznikaj´ıa zanikaj´ıpodle toho, jak j´adrodetekuje pˇrid´an´ınebo odebr´an´ıhardwarov´ych komponent (viz devfs na stranˇe 74).
• okamˇzit´yz´apisna disk lze vynutit pˇres O DIRECT command ve vol´an´ı fcntl.
77 Fyzick´euloˇzen´ısyst´emu soubor˚u
• syst´emsoubor˚u (svazek, filesystem) lze vytvoˇritna: – odd´ıludisku (partition) – ˇc´astdisku, na jednom disku m˚uˇze b´ytv´ıceodd´ıl˚u – logick´emodd´ılu (logical volume) – takto lze spojit v´ıce odd´ıl˚u,kter´emohou b´yti na nˇekolika disc´ıch, do jednoho svazku. • dalˇs´ımoˇznosti:striping, mirroring, RAID / /home /usr
disk 1 disk 2 disk 3
• v´yrazsyst´emsoubor˚use pouˇz´ıv´av nˇekolika v´yznamech:
– jeden filesyst´em,tj. to, co vyrob´ıpˇr´ıkaz mkfs – cel´ahierarchie pˇripojen´ych svazk˚uv syst´emu (v´ystuppˇr´ıkazu mount) – zp˚usoborganizace svazku (tj. typ fs) a tomu odpov´ıdaj´ıc´ımodul j´adra, kter´ys daty manipuluje (UFS2, Ext3, XFS, ...) • striping je od slova stripe, ne strip; podle toho se tak´evyslovuje. Znamen´a, ˇzeza sebou n´asleduj´ıc´ıbloky dat se ukl´adaj´ıparalelnˇena r˚uzn´edisky a t´ım se zvyˇsujepˇrenosov´arychlost. • mirroring ukl´ad´akopie dat v´ıcedisk˚upro pˇr´ıpadhav´arienˇekter´ehoz nich.
• paritn´ıdisky: data se ukl´adaj´ına dva disky, na tˇret´ıse ukl´ad´aXOR prvn´ıch dvou, po hav´ariilibovoln´ehodisku jsou vˇsechna data st´aleˇciteln´a. • jednotliv´e´urovnˇeRAID (Redundant Array of Inexpensive Disks) zahrnuj´ı striping, mirroring a vyuˇzit´ıparitn´ıch disk˚u.
• na terminologii je tˇrebad´atvelk´ypozor. Napˇr.to, co se v DOS svˇetˇenaz´yv´a partition, se v BSD naz´yv´a slice. Tam jsou pak partitions definov´any v r´amci jednoho slice a v nich se vytv´aˇrej´ıfilesyst´emy. • pokud v´asto zaj´ım´anebo se s t´ımsetk´av´atev praxi, doporuˇcujivaˇs´ıpozor- nosti ZFS, coˇzje filesyst´ema manaˇzerlogick´ych odd´ıl˚uv jednom. Ze Solarisu se jiˇzdostal do FreeBSD od verze 7.0. M˚uˇzete okamˇzitˇezapomenout na jed- notliv´edisky, co je d˚uleˇzit´eje pouze celkov´adiskov´akapacita v syst´emu.
78 Organizace syst´emu soubor˚u s5
blok ˇc. 0 zav´adˇec´ıblok (boot block) 1 superblok 09 12 2 oblast i-uzl˚u(i-nodes) ...
oblast datov´ychblok˚u
• p˚uvodn´ıUNIXov´ysyst´emsoubor˚ustandardnˇepouˇz´ıvan´ydo verze System V Release 3; v BSD se prim´arnˇepouˇz´ıval do verze 4.1 • vlastnosti: – bloky d´elky512, 1024 nebo 2048 bajt˚u – jedin´y(neduplikovan´y)superblok – datov´yprostor pevnˇerozdˇelen´yna oblast i-uzl˚u a oblast datov´ychblok˚u – pˇrivelikosti bloku 1024 bajt˚ubyla teoretick´avelikost filesyst´emu pˇres 16 GB • boot block – pro uloˇzen´ızavadˇeˇceOSu • superblok – z´akladn´ıinformace o svazku: poˇcetblok˚upro i-uzly, poˇcetblok˚u svazku, seznam voln´ych blok˚u(pokraˇcujeve voln´ych bloc´ıch), seznam voln´ych i-uzl˚u(po vyˇcerp´an´ıse prohled´av´atabulka i-uzl˚u), z´amky pro seznamy vol- n´ych blok˚ua i-uzl˚u,pˇr´ıznakmodifikace pouˇz´ıvan´ypro kontrolu korektn´ıho odpojen´ısvazku, ˇcasposledn´ıaktualizace, informace o zaˇr´ızen´ı • i-uzel – typ souboru, pˇr´ıstupov´apr´ava, vlastn´ık,skupina, ˇcasyposledn´ıho pˇr´ıstupu,modifikace dat a modifikace i-uzlu, poˇcetodkaz˚una soubor, velikost souboru, 10 odkaz˚una datov´ebloky a 3 odkazy na nepˇr´ım´ebloky. Pozor na to, ˇzeˇcasvytvoˇren´ısouboru nen´ıuloˇzen. • maxim´aln´ıvelikost souboru: 2113674 blok˚u,tj. pˇribliˇznˇe1 GB pˇri pouˇzit´ı blok˚uvelikosti 512 B
79 • jm´enasoubor˚u– max. 14 znak˚u(14 + 2 = 16, tedy mocnina dvou a tedy bezprobl´emov´euloˇzen´ıadres´aˇrov´ych poloˇzekdo blok˚u)
• pˇripouˇzit´ıtohoto filesyst´emu byla v´ykonnost disk˚uvyuˇzitajen cca na 2% a rychlost ˇcten´ıbyla v ˇr´adujen nˇekolika des´ıtekkilobajt˚uza sekundu (!!!) • pro srovn´an´ı– MS-DOS 2.0 z roku 1983 podporoval pouze FAT12, poˇc´ıtaj´ıc´ı s maxim´aln´ı velikost´ı filesyst´emu 16 MB. Velikost svazku do 2 GB byla umoˇznˇenaaˇzve verzi 4.0 (1988); tato verze z´aroveˇnzavedla diskov´evy- rovn´avac´ıpamˇeti,tedy to, co UNIX m´aod sv´ehovzniku v roce 1970.
Navigace v adres´aˇrov´estruktuˇre
i-nodes /etc/passwd i-node 2 i-node 37 i-node 71
data .. 2 37 root:x:0:... 2 .... 2
etc 37 passwd 71
• kdyˇzcesta zaˇc´ın´aznakem ’/’, zaˇc´ın´anavigace v koˇrenov´emadres´aˇri,jinak zaˇcnev pracovn´ımadres´aˇriprocesu. • koˇrenov´yadres´aˇrm´atypicky ˇc´ıslo2. 0 je pro oznaˇcen´ıpr´azdn´eho uzlu a 1 byla dˇr´ıve pouˇz´ıvan´apro soubor, do kter´ehose vkl´adalyvadn´ebloky, aby je syst´emuˇzd´alenepouˇz´ıval.
• cesta ve kter´eje v´ıcelom´ıtekza sebou je st´aleplatn´a,tj. ///a///b///c je ekvivaletn´ı /a/b/c.
80 Linky
hard link origin´al symbolick´ylink /var /etc /usr password 20 passwd 20 passwd 31 ......
i-nodes 0 ... 20 ... 31
root:x:0:... data ../etc/passwd
Hard linky lze vytv´aˇretpouze v r´amcijednoho (logick´eho) filesyst´emu.
• to co “norm´alnˇe” vid´ıtepˇriv´ypisuadres´aˇr˚ujsou vˇetˇsinouhardlinky, takˇze rozdˇelen´ınen´ına soubory, hardlinky a symbolick´elinky. Co se t´yˇcesoubor˚u, jsou pouze hardlinky a symlinky.
hardlink – odkaz na stejn´yi-uzel – vlastnˇedruh´ejm´enosouboru – nen´ırozd´ılmezi origin´alema hardlinkem – lze vytv´aˇretjen v r´amcifilesyst´emu – nelze vytv´aˇretpro adres´aˇre symbolick´ylink (symlink, softlink) – pouze odkaz na skuteˇcnoucestu k souboru jin´ehotypu (ls -l jej oznaˇcuje’l’), tj. symbolick´ylink je typem odliˇsn´yod bˇeˇzn´ehosou- boru a jeho data obsahuj´ıobyˇcejn´yˇretˇezec– jm´enocesty, at’ jiˇz relativn´ınebo absolutn´ı – odliˇsn´echov´an´ıpro origin´ala link (napˇr.pˇrimaz´an´ı) – pozor na relativn´ı a absolutn´ı cesty pˇripˇresouv´an´ı symbolick´eho linku – m˚uˇzeukazovat i na adres´aˇrnebo na neexistuj´ıc´ısoubor
• nejjednoduˇsˇs´ızp˚usobjak si ovˇeˇrit,zda dan´edva linky ukazuj´ına stejn´ysou- bor na disku je pouˇz´ıt -i pˇrep´ınaˇcpˇr´ıkazu ls, kter´yv´amuk´aˇzeˇc´ısloinde- xov´ehouzlu.
81 $ ls -i /etc/passwd 172789 /etc/passwd
Vylepˇsen´ısyst´emu soubor˚u
• c´ıl:sn´ıˇzen´ıfragmentace soubor˚u,omezen´ıpohybu hlav disku um´ıstˇen´ımi-uzl˚ua datov´ych blok˚ubl´ıˇzk sobˇe • UFS (Unix File System), p˚uvodnˇeBerkeley FFS (Fast File System) • ˇclenˇen´ına skupiny cylindr˚u,kaˇzd´askupina obsahuje – kopii superbloku – ˇr´ıdic´ıblok skupiny – tabulku i-uzl˚u – bitmapy voln´ych i-uzl˚ua datov´ych blok˚u – datov´ebloky • bloky velikosti 4 aˇz8 kB, menˇs´ıˇc´astido fragment˚ublok˚u • jm´enadlouh´a255 znak˚u
• superblok v kaˇzd´ecylinder skupinˇeposunut tak, aby superbloky nebyly na stejn´eplotnˇe.
• dalˇs´ıtypy filesyst´em˚u:UFS2, Ext3, ReiserFS, XFS, ZFS aj. • v http://mff.devnull.cz/pvu/common/docs/filesystems.ps je porovn´an´ıosmi r˚uzn´ych filesyst´em˚upodle r˚uzn´ych implementaˇcn´ıch krit´eri´ı; nezahrnuje v sobˇeale v´yvoj posledn´ıch let.
• UFS byl st´ale32-bitov´y,coˇzse odr´aˇzelona maxim´aln´ıd´elcesouboru i na maxim´aln´ıvelikosti filesyst´emu. (Oznaˇcen´ıfile syst´emu jako 32-bitov´ehozna- men´a,ˇzeˇc´ıslai-uzl˚ujsou reprezentov´anajako 32-bitov´a.To pak d´av´ateore- tick´ylimit pro velikost filesyst´emu.) • ˇzurn´alov´an´ı(XFS, Ext3, ReiserFS) – snaha o zmenˇsen´ınebezpeˇc´ıztr´aty dat v pˇr´ıpadˇehav´arie,urychlen´ızotaven´ıpo hav´arii • ZFS – modern´ı128-bitov´yfilesyst´emvyvinut´yv Sun Microsystems, od Sola- risu 10, ted’ jiˇztak´ev FreeBSD 7.
82 V´yvoj ve spr´avˇeadres´aˇrov´ych poloˇzek
• maxim´aln´ıd´elka jm´enasouboru 14 znak˚unebyla dostaˇcuj´ıc´ı • FFS – d´elka aˇz255; kaˇzd´apoloˇzka z´aroveˇnobsahuje i jej´ıd´elku • nov´efilesyst´emy pouˇz´ıvaj´ıpro vnitˇrn´ıstrukturu adres´aˇr˚ur˚uzn´e varianty B-strom˚u – v´yraznˇezrychluje pr´acis adres´aˇriobsahuj´ıc´ıvelk´emnoˇzstv´ı soubor˚u – XFS, JFS, ReiserFS, . . . • UFS2 zav´ad´ızpˇetnˇekompatibiln´ıtzv. dirhash pro zrychlen´ı pˇr´ıstupuk adres´aˇr˚ums velk´ympoˇctem soubor˚u
• dirhash pracuje tak, ˇzepˇriprvn´ımpˇreˇcten´ıadres´aˇrese vytvoˇr´ıv pamˇetihash struktura, n´asledn´epˇr´ıstupy do adres´aˇrejsou pak srovnateln´ese syst´emy pouˇz´ıvaj´ıc´ıB-stromy. T´ımto zp˚usobem je dosaˇzenozlepˇsen´ıbez toho, aby se mˇenilastruktura filesyst´emu na disku. Takov´avylepˇsen´ıale nelze v im- plementaci filesys´emu dˇelat do nekoneˇcna,nakonec je typicky nutn´azmˇena on-disk form´atupro adaptaci na v´ykonostn´ı poˇzadavky (nebo pˇrechod na jin´yfilesyst´em). • mal´esoubory se ˇcasto ukl´adaj´ıv i-nodech, ˇc´ımˇzse uˇsetˇr´ıdalˇs´ıpˇr´ıstupy na disk
83 Virtu´aln´ısyst´emsoubor˚u(Virtual File System)
struct struct struct struct struct file file file file file *file f vnodef vnodef vnodef vnode
VNODE VNODE VNODE VNODE VNODE v data v data v data v data v data INODE INODE INODE INODE INODE s realvp
ufs vnodeops s5 vnodeops spec vnodeops ufs file system s5 file system spec file system
• FFS uveden´yve 4.2BSD byl historicky druh´yunixov´yfilesyst´em. Nˇekteˇr´ı dodavatel´eunixov´ych syst´em˚uho zaˇcalipreferovat vzhledem k jeho lepˇs´ımu v´ykonu a nov´ymmoˇznostem,jin´yz˚ust´avali d´aleu s5fs z d˚uvodu zpˇetn´ekom- patibility. To d´aleprohlubovalo probl´emjiˇztak nedostateˇcn´einteroperability mezi r˚uzn´ymiunixov´ymisyst´emy. Nˇekter´ymaplikac´ım nav´ıcplnˇenevyho- voval ani jeden z tˇechto filesyst´em˚u.Postupnˇese tak´eobjevovala potˇreba pracovat s ne-unixov´ymifilesyst´emy, napˇr. FAT. A s rostouc´ı popularitou poˇc´ıtaˇcov´ych s´ıt´ıse zvyˇsovala popt´avka po sd´ılen´ısoubor˚umezi jednotliv´ymi syst´emy, coˇzmˇeloza n´asledekvznik distribuovan´ych filesyst´em˚u– napˇr. NFS (Network File System). • vzhledem k v´yˇsepopsan´esituaci bylo jen ot´azkou ˇcasu,kdy dojde k funda- ment´aln´ımzmˇen´amv infrastruktuˇresyst´emu soubor˚u,aby souˇcasnˇepodpo- roval v´ıcetyp˚ufilesyst´em˚u.Vzniklo nˇekolik r˚uzn´ych implementac´ıod r˚uzn´ych v´yrobc˚u,aˇzse nakonec de facto standardem stala VFS/vnode architektura od firmy Sun Microsystems. V dneˇsn´ıdobˇeprakticky vˇsechny unixov´ea unix- like syst´emy podporuj´ı VFS, i kdyˇzˇcastose vz´ajemnˇenekompatibiln´ımi ´upravami. VFS se poprv´eobjevilo v roce 1985 v Solarisu 2.0; brzy bylo pˇrevzatoBSD – FFS s podporou VFS se zaˇcalnaz´yvat UFS. • hlavn´ı myˇslenka: kaˇzd´emu otevˇren´emu souboru v syst´emu pˇr´ısluˇs´ı struk- tura file; to by vlastnˇebyl jeden slot v n´amijiˇzzn´am´esyst´emov´eta- bulce otevˇren´ych soubor˚u.Ta ukazuje na vnode (virtual node). Vnode ob- sahuje ˇc´astnez´avislouna konkr´etn´ımsyst´emu soubor˚ua ˇc´astz´avislou, coˇz m˚uˇzeb´ytnapˇr´ıkladstruktura inode. Ta je specifick´apro kaˇzd´ytyp soubo- rov´ehosyst´emu. Kaˇzd´ytyp filesyst´emu implementuje pevnˇedanou
84 sadu funkc´ıpro jednotliv´eoperace nad soubory, na kterou se odka- zuj´ıvˇsechny virtu´aln´ıuzly odpov´ıdaj´ıc´ıdan´emu typu filesyst´emu. Tato sada funkc´ıtedy definuje vnode interface. Kdyˇztedy zavol´atenapˇr´ıklad open, j´adrozavol´apˇr´ısluˇsnouimplementaci v z´avislostina typu filesyst´emu (napˇr. z modulu ext2fs). Implementaˇcnˇez´avisl´aˇc´aststruktury vnode je pˇr´ıstupn´a pouze z funkc´ıpˇr´ısluˇsn´ehotypu filesyst´emu; j´adrodo n´ıtedy ,,nevid´ı”pˇr´ımo. Jak uvid´ıtena dalˇs´ımslajdu, existuje jeˇstˇejedna sada funkc´ı,kter´ase t´yka pr´aces filesyst´emy jako takov´ymi. Ta pak definuje VFS interface. Tyto dvˇesady spoleˇcnˇe tvoˇr´ıvnode/VFS rozhran´ı,kter´emu se bˇeˇznˇeˇr´ık´ajen VFS. • (nebudu zkouˇset) – u speci´aln´ıch soubor˚uje situace sloˇzitˇejˇs´ı,v SVR4 struk- tura file ukazuje na snode (shadow-special-vnode), kter´ydefinuje operace se zaˇr´ızen´ım(pomoc´ısouborov´ehosyst´emu spec) a prostˇrednictv´ım ukazatele s realvp se odkazuje na re´aln´yvnode pro operace se speci´aln´ımsouborem; ten je potˇrebanapˇr´ıkladpro kontrolu pr´avpˇr´ıstupu.Kaˇzd´emu zaˇr´ızen´ım˚uˇze odpov´ıdatv´ıcespeci´aln´ıch soubor˚u,a tedy v´ıcesnodes a pˇr´ısluˇsn´ych re´aln´ych vnodes. Vˇsechny takov´esnodes pro jedno zaˇr´ızen´ımaj´ıukazatel s commonvp na jeden spoleˇcn´ysnode, to ale nen´ı na obr´azkuzachyceno. Pˇriotevˇren´ı speci´aln´ıhosouboru se hled´av hash tabulce snodes otevˇren´ych zaˇr´ızen´ıpo- loˇzka odpov´ıdaj´ıc´ıspeci´aln´ımu souboru (podle major a minor ˇc´ıslazaˇr´ızen´ı). Kdyˇzsnode nen´ınalezen, vytvoˇr´ıse nov´y. Tento snode se pak pouˇz´ıv´apˇri operac´ıch se zaˇr´ızen´ım.V´ıceviz napˇr´ıklad[Vahalia].
Hierarchie souborov´ych syst´em˚u
vfs mount list struct file rootvfs f vnode v vfspVFSVNODEVFS
vfs next vfs next v op INODE vfs data vfs data root vnode root vnode vnodeops super block super block vfs mountedhere vfs op vfs op vfs vnodecovered VNODE mount v vfsp vfsops vfsops v op point INODE in vfssw[] vsw vfsops rootvfs
vnodeops
• struktura vfs obsahuje implementaˇcnˇenez´avisl´einformace o filesyst´emu, nez´avisl´ena konkr´etn´ımtypu filesyst´emu, tedy podobnˇejako vnode funguje
85 pro soubory. Tato struktura reprezentuje jeden konkr´etn´ıfyzick´yfilesyst´em, aktu´alnˇepˇrimontovan´ydo hierarchie soubor˚u.V tomto v´azan´emseznamu tedy m˚uˇzeb´ytv´ıcestruktur stejn´ehotypu souborov´ehosyst´emu.
• rootvfs – odkaz na root file system • vfsops – tabulka funkc´ıpro konkr´etn´ıtyp syst´emu soubor˚u • vfssw[] – pole odkaz˚una tabulky vfsops pro vˇsechny syst´emempodporo- van´etypy filesyst´em˚u,z tabulky se vyb´ır´apˇripˇripojov´an´ısvazku podle typu filesyst´emu zadan´ehopˇrivol´an´ı mount • v vfsp – odkaz z vnode na filesyst´em(strukturu vfs), na kter´emleˇz´ısoubor reprezentovan´ypomoc´ıvnode
• v vfsmountedhere – pouze ve vnode, kter´yreprezentuje mount point (ad- res´aˇr,na kter´emje pˇripojen koˇrenjin´ehofilesyst´emu); odkazuje na strukturu vfs reprezentuj´ıc´ıpˇripojen´yfilesyst´em • v vnodecovered – odkaz na vnode adres´aˇre,na kter´emje filesyst´empˇripojen
Otevˇren´esoubory z pohledu j´adraI.
Per-process File System System Descriptor Tables File Table Inode Table
Process A Count 1 WRONLY
. Count 1 . /etc/group . Count 2 RDONLY Process B
Count 2 Count 4 RDWR /etc/passwd ......
• toto je nejjednoduˇsˇs´ıpohled na tabulky v j´adˇrekter´ese t´ykaj´ısoubor˚u,je to pˇrevzatoz [Bach]; dnes to je o nˇecosloˇzitˇejˇs´ı,myˇslenka je ale poˇr´adstejn´a. Realitˇev´ıcese podobaj´ıc´ıobr´azekje na pˇr´ıˇst´ımslajdu. • kaˇzd´yproces m´asvoji tabulku souborov´ych deskriptor˚u(user file descriptor table)
86 • z t´etotabulky je odkazovn´anona syst´emovou tabulku otevˇren´ych soubor˚u syst´emu (file table; ano, tato tabulka je pouze jedna). Zde je m´odotevˇren´ı souboru a tak´e aktu´aln´ıpozice v souboru.
• z tabulky otevˇren´ych soubor˚uje odkazov´anodo tabulky naˇcten´ych inod˚uv pamˇeti.Dnes jsou to tzv. vnodes – virtual nodes, ale to v t´etochv´ılinen´ı relevantn´ı. • tabulka otevˇren´ych soubor˚usyst´emu, kter´avlastnˇevytv´aˇr´ıo jednu ´uroveˇn odkaz˚unav´ıc,je zde proto, aby r˚uzn´eprocesy mohly sd´ıletstejnou aktu´aln´ı pozici v souboru.
• pˇriotevˇren´ısouboru pomoc´ıvol´an´ı open se vˇzdyalokuje nov´yslot v tabulce deskriptor˚ua tak´ev syst´emov´etabulce otevˇren´ych soubor˚u(to je d˚uleˇzit´e!). Sd´ılen´ıse pak v r´amci jednoho procesu dos´ahneduplikac´ıdeskriptor˚u,kdy v´ıcedeskriptor˚usd´ıl´ıstejn´yslot v tabulce otevˇren´ych soubor˚usyst´emu nebo v pˇr´ıpadˇer˚uzn´ych proces˚upak pomoc´ı vytvoˇren´ı nov´ehoprocesu pomoc´ı vol´an´ı fork(), viz strana 138.
Otevˇren´esoubory z pohledu j´adraII.
struct proc uf next uf next u first u proc struct struct struct struct user ufchunk ufchunk ufchunk
p cred 201...201...201... uf ofile[]
f cred struct cred
f next struct struct struct struct struct struct file file file file file file *file f prev f vnode VNODE VNODE VNODE VNODE VNODE
• struktury proc a user vytv´aˇr´ıj´adropro kaˇzd´yproces a drˇz´ıv nich sluˇzebn´ı informace o procesu.
• struktura ufchunk obsahuje NFPCHUNK (obvykle 24) deskriptor˚usoubor˚u, po zaplnˇen´ıse alokuje dalˇs´ı ufchunk. • struktura file (otevˇren´ısouboru) obsahuje m´odsouboru (otevˇrenpro ˇcten´ı, z´apis,atd.), poˇcetdeskriptor˚u,kter´ese na ni odkazuj´ı,ukazatel na vnode a
87 pozici v souboru. Jedno otevˇren´ısouboru m˚uˇzeb´ytsd´ılenov´ıcedeskriptory, jestliˇzebyl p˚uvodn´ıdeskriptor zkop´ırov´an,napˇr.vol´an´ım fork() nebo dup().
• struktura cred obsahuje uˇzivatelskou a skupinovou identitu procesu, kter´y otevˇrelsoubor. • jeden vnode odpov´ıdaj´ıc´ıjednomu souboru m˚uˇzeb´ytsd´ılennˇekolika struk- turami file, pokud byl dan´ysoubor v´ıcekr´atotevˇren. • ne vˇsechny vnodes jsou asociov´any s tabulkou otevˇren´ych soubor˚u.Napˇr.pˇri spuˇstˇen´ıprogramu je potˇrebapˇristupovat do spustiteln´ehosouboru a proto se alokuje vnode.
Oprava konzistence souborov´ehosyst´emu • pokud nen´ıfilesyst´empˇredzastaven´ımsyst´emu korektnˇe odpojen, mohou b´ytdata v nekonzistentn´ımstavu. • ke kontrole a opravˇesvazku slouˇz´ıpˇr´ıkaz fsck. Postupnˇe testuje moˇzn´enekonzistence: – v´ıcen´asobn´eodkazy na stejn´yblok – odkazy na bloky mimo rozsah datov´eoblasti syst´emu soubor˚u – ˇspatn´ypoˇcetodkaz˚una i-uzly – nespr´avn´avelikost soubor˚ua adres´aˇr˚u – neplatn´yform´ati-uzl˚u – bloky kter´enejsou obsazen´eani voln´e – chybn´yobsah adres´aˇr˚u – neplatn´yobsah superbloku • operace fsck je ˇcasovˇen´aroˇcn´a. • ˇzurn´alov´e(napˇr.XFS v IRIXu, Ext3 v Linuxu) a transakˇcn´ı (ZFS) syst´emy soubor˚unepotˇrebuj´ı fsck.
• data se pˇrepisuj´ı na disky z vyrovn´avac´ıch pamˇet´ı se zpoˇzdˇen´ım. Uloˇzen´ı vˇsech vyrovn´avac´ıch pamˇet´ılze vynutit syst´emov´ymvol´an´ım sync(). Perio- dicky vyrovn´avac´ıpamˇetiukl´ad´azvl´aˇstn´ısyst´emov´yproces (d´emon).
• fsck kontroluje pouze metadata. pokud doˇslok poruˇsedat samotn´ych, ne- pozn´ato, natoˇzaby s t´ımnˇecomohl udˇelat.
• zde je uk´azka fsck na odpojen´y filesyst´em:
toor@shewolf:~# fsck /dev/ad0a ** /dev/ad0a ** Last Mounted on /mnt/flashcard ** Phase 1 - Check Blocks and Sizes ** Phase 2 - Check Pathnames
88 ** Phase 3 - Check Connectivity ** Phase 4 - Check Reference Counts ** Phase 5 - Check Cyl groups 24 files, 8848 used, 12951 free (7 frags, 1618 blocks, 0.0% fragmentation)
Dalˇs´ızp˚usoby zajiˇstˇen´ıkonzistence filesyst´emu
• tradiˇcn´ıUFS – synchronn´ız´apismetadat – aplikace vytv´aˇrej´ıc´ınov´ysoubor ˇcek´ana inicializaci inode na disku; tyto operace pracuj´ırychlost´ıdisku a ne rychlost´ı CPU – asynchronn´ız´apisale ˇcastˇejizp˚usob´ınekontistenci metadat • ˇreˇsen´ıprobl´em˚us nekonzistenc´ımetadat na disku: – journalling – skupina na sobˇez´avisl´ych operac´ıse nejdˇr´ıve atomicky uloˇz´ıdo ˇzurn´alu;pˇriprobl´emech se pak ˇzurn´al m˚uˇze“pˇrehr´at” – bloky metadat se nejdˇr´ıve zap´ıˇs´ıdo non-volatile pamˇeti – soft-updates – sleduje z´avislostimezi ukazately na diskov´e struktury a zapisuje data na disk metodou write-back tak, ˇzedata na disku jsou vˇzdykonzistentn´ı – ZFS je nov´yfilesyst´emv Solarisu, kter´ypouˇz´ıv´a copy-on-write transakˇcn´ımodel
• filesystem metadata = inodes, directories, free block maps • ext2 dokonce defaultnˇepouˇz´ıv´aasynchronn´ız´apismetadat a je pˇripouˇz´ıt´ı synchronn´ıhoz´apisuv´yraznˇepomalejˇs´ıneˇzUFS • z´avisl´eoperace jsou napˇr´ıklad smaz´an´ı poloˇzkyz adres´aˇrea smaz´an´ı dis- kov´ehoinode. Pokud by se stalo, ˇzese nejdˇr´ıve smaˇzediskov´yinode a pak te- prve poloˇzka v adres´aˇri,pˇriv´ypadkumezi tˇemitodvˇemioperacemi vnik´ane- konzistence – link ukazuje na diskov´ysoubor, kter´yneexistuje. Nen´ıprobl´em se tomuto vyhnout pˇrisynchronn´ımz´apisumetadat (v´ımekdy a co zapisu- jeme, urˇcujemetedy poˇrad´ız´apisu),ale pˇrimetodˇewrite-back je jiˇznutn´e ˇreˇsitz´avislostijednotliv´ych blok˚una sebe, protoˇzepˇriklasick´esynchronizaci vyrovn´avac´ıch pamˇet´ına disk j´adronezaj´ım´a,kter´yblok se zap´ıˇsedˇr´ıv a kter´ypozdˇeji. • ˇcastojsou bloky na sobˇez´avisl´eve smyˇcce.Soft updates dok´aˇzetakovou smyˇckurozb´ıtt´ım,ˇzeprovede roll-back a po z´apisupak roll-forward • v´ykon soft updates je srovnateln´yv´ykonu UFS filesyst´emu s asynchronn´ım z´apisemmetadat • teoreticky soft updates zaruˇcuj´ı,ˇzepo rebootu nen´ıpotˇrebapouˇz´ıt fsck, tj. ˇzefilesyst´embude v takov´emstavu, ˇzeje moˇzn´enabootovat. Je vˇsaknutn´e
89 pouˇz´ıttzv. background fsck pro opravy nez´avaˇzn´ych chyb – to je povaˇzov´ano st´aleza velkou nev´yhodu soft updates zvl´aˇstˇes t´ım,jak rostou velikosti bˇeˇznˇe pouˇz´ıvan´ych disk˚u.Takovou chybou, kter´anebr´an´ınabootov´an´ı,ale je nutn´e ji odstranit je napˇr´ıklad blok, kter´yje oznaˇcenjako pouˇzit´y,ale ˇz´adn´ysoubor ho nepouˇz´ıv´a. • soft updates nejsou vˇzdydoporuˇcov´any pro root filesyst´em.Probl´emje to, ˇzeztr´atametadat na root filesyst´emu (viz 30-ti sekundov´aperioda z´apisu) m˚uˇzeb´ytv´yraznˇevˇetˇs´ıhrozbou zde neˇzna /usr, /home atd. Dalˇs´ınev´yhodou m˚uˇzeb´yti to, ˇzeu soft updates mi smaz´an´ıvelk´ehosouboru hned neuvoln´ı m´ısto. • pˇr´ıklad:na bezpeˇcnouoperaci rename potˇrebujupˇrisynchronn´ımz´apisume- tadat 4 z´apisy– zv´yˇsen´ıpoˇctuodkaz˚uv inode, vytvoˇren´ınov´eadres´aˇrov´e poloˇzky, smaz´an´ıstar´e,a opˇetn´esn´ıˇzen´ıpoˇctuodkaz˚uv inode. Kdykoli by syst´emspadnul, nenastane nebezpeˇcn´asituace. Napˇr´ıklad 2 odkazy z ad- res´aˇr˚una inode s referenˇcn´ımpoˇctem1 je probl´em,protoˇzepo zruˇsen´ıjed- noho odkazu to bude vypadat, ˇzesoubor je st´alena disku, kdyˇzuˇzbyla jeho data d´avnosmaz´ana.Nen´ıteˇzk´esi asi pˇredstavit, co by to mohlo znamenat v pˇr´ıpadˇe,ˇze soubor obsahoval opravdu d˚uleˇzit´adata – napˇr´ıkladz´alohu. Opaˇcn´asituace, tj. jeden odkaz na inode s referenc´ı2 sice tak´enen´ıspr´avn´asi- tuace, ale neohroˇzujeto moˇznostfilesyst´emnamontovat a norm´alnˇepouˇz´ıvat. V nejhorˇs´ım se stane, ˇzesoubor vypad´aˇzejiˇzna disku nen´ıa pˇritomst´ale existuje. U soft updates operace rename vytvoˇr´ıkruˇznici,protoˇzenejdˇr´ıve je potˇrebazapsat zv´yˇsen´ıpoˇctureferenc´ı,pak adres´aˇrov´ebloky a pot´esn´ıˇzen´ı referenc´ı.A protoˇzezv´yˇsen´ı/sn´ıˇzen´ıse t´yk´astejn´ehoinode, tak je pˇriz´apisu tˇrebaudˇelatroll-back na (ˇreknˇeme)2, zapsat inode na disk, zapsat bloky adres´ar˚ua pak roll-forward na poˇcetreferenc´ı1. Pˇrit´etoakci je nad inodem drˇzenz´amek,takˇzenikdo nenaˇctestarˇs´ıdata. Je jednoduch´euk´azat, ˇzenelze zapsat ˇz´adn´yz tˇech tˇr´ıblok˚uv kruˇznicitak, jak to je na konci operace re- name, ˇzeje opravdu nutn´yten roll-back – mohli bychom uvaˇzovat, ˇzeinode se vlastnˇenezmˇenila nen´ıtˇrebaˇreˇsitzda se m˚uˇze/nem˚uˇzezapsat; z´apisnov´eho adres´aˇrov´ehoodkazu bez zv´yˇsen´ıpoˇctuodkaz˚uv inodu by n´astotiˇzmohl dostat pˇresnˇedo situace, kter´aje pops´anao p´arˇr´adk˚uv´yˇse.
90 Pˇr´ıstupov´apr´ava vlastn´ık(u) skupina (g) ostatn´ı(o) z }| { z }| { z }| { nejvyˇsˇs´ıbit 4 2 1suid sgid r sticky w x • SGID pro soubor bez pr´ava spuˇstˇen´ıpro skupinu v System V: kontrola z´amk˚upˇrikaˇzd´empˇr´ıstupu(mandatory locking) • sticky bit pro adres´aˇre:pr´avo mazat a pˇrejmenov´avat soubory maj´ıjen vlastn´ıcisoubor˚u • SGID pro adres´aˇr:nov´esoubory budou m´ıtstejnou skupinu jako adres´aˇr(System V; u BSD syst´em˚uto funguje jinak, viz pozn´amky)
• SGID pro adres´aˇreu BSD syst´em˚uzp˚usob´ı,ˇzesoubory a podadres´aˇrevy- tvoˇren´ev tomto adres´aˇribudou m´ıtstejn´ehomajitele jako je majitel dan´eho adres´aˇre.Nutn´ympˇredpokladem je d´aleto, ˇzedan´yUFS filesyst´emmus´ıb´yt namontov´ans suiddir pˇr´ıznakem a v j´adruje option SUIDDIR (a to nen´ı default). Nav´ıcto nefunguje pro roota. Tato moˇznost existuje kv˚uliSambˇea Nettalku.
• sticky bit pro adres´aˇre: pˇrejmenovat nebo smazat soubor m˚uˇzejen jeho vlastn´ık(v nˇekter´ych implementac´ıch staˇc´ıi pr´avo z´apisudo souboru), nesta- ˇc´ıpr´avo z´apisudo adres´aˇre.Toto nastaven´ıse pouˇz´ıv´apro veˇrejn´eadres´aˇre (napˇr. /tmp). • p˚uvodnˇemˇelsticky bit v´yznami pro spustiteln´esoubory: program s nasta- ven´ymsticky bitem z˚ustalpo ukonˇcen´ıv pamˇetia jeho opˇetovn´espuˇstˇen´ı bylo rychlejˇs´ı.Dnes se sticky bit v tomto v´yznamu uˇznepouˇz´ıv´a. • nˇekter´efilesyst´emy (XFS, AFS, UFS2, ZFS) maj´ıtzv. access control lists (ACLs), kter´edovoluj´ıjemnˇejˇs´ıpˇridˇelov´an´ıpr´avjednotliv´ymuˇzivatel˚uma skupin´am.
91 API pro soubory
• pˇredpouˇzit´ımmus´ıproces kaˇzd´ysoubor nejprve otevˇr´ıt vol´an´ım open() nebo creat(). • otevˇren´esoubory jsou dostupn´epˇres deskriptory soubor˚u (file descriptors), ˇc´ıslovan´eod 0, v´ıcedeskriptor˚um˚uˇzesd´ılet jedno otevˇren´ısouboru (m´odˇcten´ı/z´apis,ukazatel pozice) • standardn´ıdeskriptory: – 0 . . . standardn´ıvstup (jen pro ˇcten´ı) – 1 . . . standardn´ıv´ystup(jen pro z´apis) – 2 . . . chybov´yv´ystup(jen pro z´apis) • ˇcten´ıa z´apisz/do souboru: read(), write() • zmˇenapozice: lseek(), zavˇren´ı: close(), informace: stat(), ˇr´ıdic´ıfunkce: fcntl(), pr´ava: chmod(),...
• kaˇzd´afunkce, kter´aalokuje deskriptory (nejen open a creat, ale napˇr.i pipe, dup, socket) alokuje vˇzdyvoln´edeskriptory s nejniˇzˇs´ımˇc´ıslem. • proces dˇed´ıotevˇren´esoubory od rodiˇce,tyto soubory nemus´ıznovu otv´ırat. Obvykle (ale ne vˇzdy)proces dostane otevˇren´ealespoˇndeskriptory 0, 1 a 2.
• funkce ze souboru stdio.h (napˇr. fopen, fprintf, fscanf) a odkazy na soubory pomoc´ıukazatele na FILE jsou definov´any ve standardn´ıknihovnˇe a pro svoj´ıˇcinnostpouˇz´ıvaj´ıvol´an´ıj´adra(napˇr. open, write, read). My se nebudeme knihovnou stdio zab´yvat.
92 Otevˇren´ısouboru: open()
int open(const char *path, int oflag, ... ); • otevˇresoubor dan´yjm´enem(cestou) path, vr´at´ıˇc´ıslojeho deskriptoru (pouˇzijeprvn´ıvoln´e), oflag je OR-kombinace pˇr´ıznak˚u – O RDONLY/O WRONLY/O RDWR . . . otevˇr´ıtpouze pro ˇcten´ı/ pouze pro z´apis/ pro ˇcten´ıi z´apis – O APPEND . . . pˇripojov´an´ına konec – O CREAT . . . vytvoˇrit,kdyˇzneexistuje – O EXCL . . . chyba, kdyˇzexistuje (pouˇzit´ıs O CREATE) – O TRUNC . . . zruˇsitpˇredchoz´ıobsah (pr´avo z´apisunutn´e) – ... • pˇri O CREAT definuje tˇret´ıparametr mode pˇr´ıstupov´apr´ava
• pˇripouˇzit´ı O CREAT se mode jeˇstˇemodifikuje podle nastaven´ıaktu´aln´ımasky, kter´ese mˇen´ıvol´an´ım umask. Defaultn´ıhodnota je typicky 022. Doporuˇcuji se zamyslet, zda ji ve vaˇsem shell profile skriptu nenastavit na 077. To ale nikdy nedˇelejtepro roota, jinak skonˇc´ıtes podivnˇese chovaj´ıc´ımsyst´emem – nainstalovan´ysoftware nebude moct spustit pod bˇeˇzn´ymuˇzivatelem, to co dˇr´ıve fungovalo fungovat pˇrestaneapod.
• mode nem´adefaultn´ıhodnotu, tj. vezme se to, co je na z´asobn´ıkui kdyˇztento parametr nen´ıpˇr´ıtomen!Pˇr´ıznakyi m´odjsou uloˇzeny v syst´emov´etabulce otevˇren´ych soubor˚u. • pokud se znovu pouˇzijedˇr´ıve vyuˇz´ıvan´apoloˇzka v tabulce deskriptor˚unebo v tabulce otevˇren´ych soubor˚u,vˇsepotˇrebn´ese vynuluje (pozice v souboru, flagy deskriptoru, . . . ) • existuj´ıjeˇstˇedalˇs´ınastaviteln´epˇr´ıznaky:
– O SYNC (O DSYNC, O RSYNC – nen´ı na BSD) . . . operace se souborem skonˇc´ıaˇzpo fyzick´emuloˇzen´ıdat (synchronized I/O) – O NOCTTY . . . pˇriotv´ır´an´ı termin´aluprocesem, kter´ynem´aˇr´ıdic´ı ter- min´al,se tento termin´alnestane ˇr´ıd´ıc´ımtermin´alemprocesu – O NONBLOCK . . . pokud nelze ˇcten´ınebo z´apisprov´estokamˇzitˇe,vol´an´ı read/write skonˇc´ıs chybou m´ıstozablokov´an´ıprocesu • v pˇr´ıstupov´ych pr´avech se vynuluj´ı ty bity, kter´ejsou nastaven´epomoc´ı umask.
93 • pro ˇcten´ıa z´apisnelze pouˇz´ıt O RDONLY | O WRONLY, protoˇzeimplementace pouˇzily0 pro read-only flag. Norma proto definuje, ˇzeaplikace mus´ıpouˇz´ıt pr´avˇejeden z tˇechto tˇr´ıflag˚u. • je moˇzn´eotevˇr´ıta z´aroveˇnvytvoˇritsoubor pro z´apistak, ˇzejeho m´odz´apis nedovoluje. Pˇripˇr´ıˇst´ım otevˇren´ı souboru se ale jiˇztento m´oduplatn´ı pˇri kontrole pˇr´ıstupua pro z´apisjej otevˇr´ıtnep˚ujde.Pro O TRUNC tak´eplat´ı,ˇze mus´ıtem´ıtpro dan´ysoubor pr´avo z´apisu. • Chov´an´ı O EXCL bez souˇcasn´ehopouˇzit´ı O CREAT nen´ı definov´ano.Pro za- myk´an´ısoubor˚use pouˇz´ıv´a fcntl, viz strana 104.
Vytvoˇren´ısouboru
int creat(const char *path, mode t mode ); • open() s pˇr´ıznakem O CREAT vytvoˇr´ısoubor, pokud jeˇstˇe neexistuje. V zadan´ehodnotˇepˇr´ıstupov´ych pr´avse vynuluj´ı bity, kter´ebyly nastaveny pomoc´ıfunkce mode t umask(mode t cmask ); • funkce je ekvivalentn´ıvol´an´ı open(path, O WRONLY|O CREAT|O TRUNC, mode); int mknod(const char *path, mode t mode, dev t dev ); • vytvoˇr´ıspeci´aln´ısoubor zaˇr´ızen´ı. int mkfifo(const char *path, mode t mode ); • vytvoˇr´ıpojmenovanou rouru.
• Vol´an´ıvrac´ınejniˇzˇs´ıdeskriptor, kter´yv dan´echv´ılinebyl otevˇren´ypro proces • open dok´aˇzeotevˇr´ıt regul´arn´ı soubor, zaˇr´ızen´ı i pojmenovanou rouru, ale vytvoˇritdok´aˇzejen regul´arn´ısoubor; pro ostatn´ıtypy soubor˚uje nutn´epouˇz´ıt zde uveden´aspeci´aln´ıvol´an´ı. • Test pomoc´ı pˇr´ıznaku O EXCL na to, zda soubor existuje, a jeho pˇr´ıpadn´e vytvoˇren´ıje atomick´aoperace. Toho se vyuˇz´ıv´apˇripouˇz´ıv´an´ılock soubor˚u. Ze slajdu je vidˇet,ˇzetento test je moˇzn´eprov´estjen pomoc´ıvol´an´ı open, ne creat. • Speci´aln´ısoubory m˚uˇzevytv´aˇretpouze root, protoˇzese pomoc´ınich definuj´ı pˇr´ıstupov´apr´ava k perifern´ımzaˇr´ızen´ım. • Povolen´ehodnoty pro mode je moˇzn´enal´eztvˇetˇsinouv manu´alov´estr´ankce pro chmod(2), a urˇcitˇeje naleznete i v hlaviˇckov´emsouboru stat.h, kde mus´ıb´yt podle normy definovan´e.
94 Cten´ıaˇ z´apissoubor˚u: read(), write()
ssize t read(int fildes, void *buf, size t nbyte ); • z otevˇren´ehosouboru s ˇc´ıslemdeskriptoru fildes pˇreˇcteod aktu´aln´ıpozice max. nbyte bajt˚udat a uloˇz´ıje od adresy buf. • vrac´ıpoˇcetskuteˇcnˇepˇreˇcten´ych bajt˚u(<= nbyte), 0 znamen´a konec souboru.
ssize t write(int fildes, const void *buf, size t nbyte ); • do otevˇren´ehosouboru s ˇc´ıslemdeskriptoru fildes zap´ıˇsena aktu´aln´ıpozici max. nbyte bajt˚udat uloˇzen´ych od adresy buf. • vrac´ıvelikost skuteˇcnˇezapsan´ych dat (<= nbyte).
• pro UNIX je kaˇzd´ysoubor posloupnost bajt˚ubez dalˇs´ıvnitˇrn´ıstruktury. • chov´an´ı read a write z´avis´ına typu souboru (regul´arn´ı,zaˇr´ızen´ı,roura, soket) a na tom, zda je soubor v blokuj´ıc´ımnebo neblokuj´ıc´ımm´odu(flag O NONBLOCK pˇriotevˇren´ısouboru, viz strana 93). • pro obˇevol´an´ıexistuje nˇekolik z´asadn´ıch rohov´ych pˇr´ıpad˚ua n´asleduj´ıc´ıinfor- mace jsou v´yˇnatkem z manu´alov´ych str´anek.Pokud si nejste jisti, doporuˇcuji se pod´ıvat pˇr´ımodo normy (POSIX 1003.1, sekce XSH, ˇc´astSystem Interfa- ces). • vol´an´ı read vr´at´ınenulov´ypoˇcet bajt˚umenˇs´ıneˇz nbyte, pokud v souboru zb´yv´am´enˇeneˇz nbyte bajt˚u,nebo vol´an´ı bylo pˇreruˇsenosign´alem, nebo soubor je roura, zaˇr´ızen´ıˇcisoket a aktu´alnˇeje k dispozici m´enˇeneˇz nbyte bajt˚u.Pˇrineexistenci dat se blokuj´ıc´ı read zablokuje, dokud se nˇejak´adata neobjev´ı,neblokuj´ıc´ı read vr´at´ı -1 a nastav´ı errno na EAGAIN. • vol´an´ı write vr´at´ınenulov´ypoˇcetbajt˚umenˇs´ıneˇz nbyte, jestliˇzese do sou- boru nevejde v´ıcdat (napˇr.zaplnˇen´ydisk), z´apisje pˇreruˇsensign´alemnebo je nastaveno O_NONBLOCK a do roury, soketu nebo zaˇr´ızen´ıse vejde pouze ˇc´ast zapisovan´ych dat. Bez O_NONBLOCK se ˇcek´a,dokud se nepodaˇr´ızapsat vˇse. Pokud nelze aktu´alnˇezapsat nic, blokuj´ıc´ı write se zablokuje, dokud nen´ı moˇzn´ezapisovat, neblokuj´ıc´ı write vr´at´ı -1 a nastav´ı errno na EAGAIN. • d˚uleˇzit´ev´yjimkyvzhledem k rour´am jsou uvedeny na stranˇe 98. • kdyˇz read nebo write vr´at´ı m´enˇeneˇz nbyte z d˚uvodu chyby, opakovan´e vol´an´ıt´eˇze funkce vr´at´ı -1 a nastav´ık´odchyby v errno.
95 • pˇreruˇsen´ı read, write sign´alemdˇr´ıv,neˇzse podaˇr´ıpˇreˇc´ıst,resp. zapsat aspoˇn jeden bajt, zp˚usob´ın´avrat s hodnotou -1 a nastaven´ı errno na EINTR. Pozor na to, ˇzezde je rozd´ılproti situaci, kdy pˇreddoruˇcen´ımsign´alupodaˇr´ıpˇreˇc´ıst nebo zapsat alespoˇnjeden bajt (viz v´yˇse). • pˇr´ıznakotevˇren´ısouboru O_APPEND zajist´ıatomick´yz´apisna konec souboru (pouze na lok´aln´ımdisku), tj. kaˇzd´y z´apisse provede na konec souboru (tzv. append-only soubor).
Uzavˇren´ısouboru: close()
int close(int fildes ); • uvoln´ıdeskriptor fildes, pokud to byl posledn´ıdeskriptor, kter´yodkazoval na otevˇren´ısouboru, zavˇresoubor a uvoln´ı z´aznamo otevˇren´ısouboru. • kdyˇzje poˇcetodkaz˚una soubor 0, j´adrouvoln´ıdata souboru. Tedy i po zruˇsen´ıvˇsech odkaz˚u(jmen) mohou se souborem pracovat procesy, kter´eho maj´ıotevˇren´y.Soubor se smaˇze,aˇz kdyˇzho zavˇreposledn´ıproces. • kdyˇzse zavˇreposledn´ıdeskriptor roury, vˇsechna zb´yvaj´ıc´ıdata v rouˇrese zruˇs´ı. • pˇriskonˇcen´ıprocesu se automaticky provede close() na vˇsechny deskriptory.
• Pokud proces potˇrebuje doˇcasn´ysoubor, m˚uˇzeho vytvoˇrit,ihned smazat a pak s n´ım pracovat pˇresexistuj´ıc´ı deskriptor (tento deskriptor lze pˇredat synovsk´ymproces˚um).Kdyˇzje takov´ysoubor zavˇrenvˇsemiprocesy, j´adro smaˇzejeho data z disku.
• I operace close m˚uˇzeselhat. Napˇr.nˇekter´efilesyst´emy zapisuj´ıdata na disk aˇzv okamˇzikuzavˇren´ısouboru, kdyˇzz´apisskonˇc´ıchybou, close vr´at´ı -1. • Chbˇej´ıc´ızav´ır´an´ıdeskriptor˚upˇriukonˇcen´ıpr´aces nimi vede k situaci, kter´ese ˇr´ık´a file descriptor leak. Nen´ıto ´uplnˇepˇresnˇeto, jak se typicky ch´ape memory leak (pamˇet,na kterou jsme ztratili ukazatel), ale n´asledkyjsou podobn´e.
• Pˇr´ıkladna jednoduch´y cat(1) program: read/cat.c
96 Example: copy files
#include
int main(int argc, char *argv[]) { char buf[4096]; int inf, outf; ssize t ilen;
inf = open(argv[1], O RDONLY); outf = creat(argv[2], 0666); while ((ilen = read(inf, buf, sizeof (buf))) > 0) write(outf, buf, ilen);
close(inf); close(outf); return (0); }
• Tento pˇr´ıkladje kompletn´ı! Staˇc´ıprov´estcut-and-paste, pˇreloˇzita spustit. Nutno poznamenat, ˇzepro ´uˇcelypouˇzit´ıpouze jednoho slajdu se netestuj´ı ˇz´adn´echyby, vˇcetnˇeignorov´an´ıtoho, ˇzeuˇzivatel m˚uˇzeprogram spustit bez parametr˚u,coˇzzp˚usob´ıpokus o pˇr´ıstupdo pamˇetina m´ısto,kter´eneobsahuje oˇcek´avan´adata. To pak na nˇekter´ych syst´emech m˚uˇzezp˚usobitcore dump.
• Je neefektivn´ıˇc´ısta zapisovat soubor po jednotliv´ych bajtech, protoˇzekaˇzd´e syst´emov´evol´an´ım´ajist´yoverhead, nez´avisl´yna velikosti zpracov´avan´eho bloku. Lepˇs´ıje proto najednou zpracov´avat rozumnˇevelk´ebloky, napˇr´ıklad8- 64KB. Pˇrechoz´ıpˇr´ıklad read/cat.c m´apˇrep´ınaˇc -b pro nastaven´ıvelikosti bloku pro ˇcten´ı;zkuste s (a bez) -b 1 a zmˇeˇrtepomoc´ı time(1). Uvid´ıte velk´yrozd´ıl.
• Pokud potˇrebujetepracovat s mal´ymiˇc´astmi/buffery, je lepˇs´ıpouˇz´ıtstream orintovan´eknihovn´ıfunkce fopen, fread, . . . kter´edata vnitˇrnˇebufferuj´ı. • Vˇsimnˇetesi, ˇzevˇzdyzapisujeme jen tolik bajt˚u,kolik jsme jich naˇcetli.
97 Working with a named pipe (FIFO)
• it may not be possible to create a FIFO on a distributed filesystem (eg. NFS or AFS) • you need to know the semantics of opening a FIFO – opening a FIFO for just reading will block until a writer (aka producer) shows up, unless one already exists. – opening a FIFO for just writing will block until a reader (aka consumer) shows up, unless one already exists. – this behavior can be adjusted using a flag O NONBLOCK • semantics for reading and writing is a bit more complicated, see the notes below this slide. – same as for a conventional, unnamed, pipe (will be later)
• Co se t´yˇcevytvoˇren´ıpojmenovan´eroury, mluv´ımezde o vol´an´ı mkfifo ze strany 94. Pouˇzit´ınepojmenovan´eroury je popsan´ena stranˇe 137. • Cten´aˇrjeˇ proces, kter´yotevˇresoubor (i) pro ˇcten´ı, zapisovatel je proces, kter´yotevˇresoubor (i) pro z´apis.
• Je moˇzn´eotevˇr´ıtrouru pro z´apisi ˇcten´ıstejn´ymprocesem najednou, aniˇzby pˇredt´ımexistoval ˇcten´aˇrnebo zapisovatel. Proces pak m˚uˇzedo roury zapiso- vat a z opaˇcn´ehokonce ˇc´ıst,co do roury napsal. • Pokud rouru nem´aˇz´adn´yproces otevˇrenoupro z´apis,pro okamˇzit´evr´acen´ı deskriptoru pouze pro ˇcten´ı je nutn´e otevˇr´ıt rouru s flagem O NONBLOCK, proces se jinak na rouˇrezablokuje ˇcek´an´ım na zapisovatele. Pozor ale na to, ˇzepokus o ˇcten´ı z roury bez zapisovatele okamˇzitˇevr´at´ı0 jako indikaci konce souboru; proces se nezablokuje ˇcek´an´ım na zapisovatele, bez ohledu na to zda byl soubor otevˇrenv blokovac´ımˇcineblokovac´ımm´odu.Pˇri z´apisu do roury bez ˇcten´aˇre(tj. zapisovatel otevˇrelrouru jeˇstˇev dobˇe,kdy ˇcten´aˇrexistoval, viz n´asleduj´ıc´ıodstavec) poˇslekernel procesu sign´al SIGPIPE (“broken pipe”):
bash$ dd if=/dev/zero | date Sun Mar 2 01:03:38 CET 2008 bash$ echo ${PIPESTATUS[0]} 141 bash$ kill -l 141 PIPE
98 • v pˇr´ıpadˇeotev´ır´an´ıpouze pro z´apiss O NONBLOCK bez existuj´ıc´ıhoˇcten´aˇre se vr´at´ıchyba a errno se nastav´ına ENXIO. Tato asymetrie je snahou, aby v rouˇrenebyla data, kter´anebudou v kr´atk´edobˇepˇreˇctena– syst´emnem´a zp˚usob,jak uschov´avat data v rouˇrebez ˇcasov´ehoomezen´ı.Bez O NONBLOCK flagu se proces zablokuje ˇcek´an´ım na ˇcten´aˇre.Asymetri´ı je m´ınˇenoto, ˇze syst´emu nevad´ı ˇcten´aˇri bez zapisovatel˚u,ale nechce m´ıt zapisovatele bez ˇcten´aˇr˚u.I tato situace se m˚uˇzest´at,viz pˇredchoz´ıodstavec, ale tam to jinak ˇreˇsitnelze. • z uveden´ehotedy vypl´yv´a,ˇzepokud chcete vytvoˇritproces, kter´yˇcek´ana po- jmenovan´erouˇrea vykon´av´apoˇzadavky od r˚uzn´ych proces˚u-zapisovatel˚u(od kaˇzd´ehojeden), mus´ıteji otevˇr´ıts flagem O RDWR i kdyˇzdo roury nehodl´ate zapisovat; jinak po prvn´ımzablokov´an´ıv open pˇriˇcek´an´ına otevˇren´ıroury zapisovatelem by dalˇs´ıvol´an´ı read pro akceptov´an´ıdalˇs´ıhopoˇzadavku ty- picky vr´atilo0, pokud by n´ahodou roura nebyla mezit´ımpro z´apisotevˇrena dalˇs´ımprocesem. • z´apismaxim´aln´ıvelikosti PIPE BUF (limits.h) je zaruˇcen´yjako atomick´y,tj. data nesm´ıb´ytproloˇzenadaty jin´ych zapisuj´ıc´ıch proces˚u.Napˇr.v Solarisu 11 to je to 5120 bajt˚u,ve FreeBSD 5.4 je to 512 bajt˚u.Pokud zapisujete v´ıce,m˚uˇzese to st´at.Z´aroveˇnplat´ı,ˇzepokud se zapisuje m´enˇeneˇz PIPE BUF bajt˚u,zap´ıˇsouse vˇzdynajednou, a pokud je nastaveno O NONBLOCK a nelze toho dos´ahnout,vr´at´ıse chyba. • roura nem´apozici v souboru, z´apistak vˇzdypˇrid´av´ana konec. • stejnˇese vzhledem ke ˇcten´ıa z´apisuchov´ai nepojmenovan´aroura, viz strana 137.
Setting file position: lseek()
off t lseek(int fildes, off t offset, int whence ); • will reposition the file offset for reading and writing in an already opened file associated with a file descriptor fildes
• based on value of whence, the file offset is set to: – SEEK SET . . . the value of offset – SEEK CUR . . . current position plus offset – SEEK END . . . size of the file plus offset • returns the resulting offset (ie. from the file beginning)
• lseek(fildes, 0, SEEK CUR) only returns the current file position
99 • Poˇc´ıt´ase od 0, tj. offset 0 je prvn´ıbajt souboru. Tam, kde to m´asmysl, je moˇzn´epro offset pouˇz´ıti z´aporn´eˇc´ıslo.Pˇr´ıklad: read/lseek.c . • Lze se pˇresunouti na pozici za koncem souboru. Pokud se pak provede z´apis, soubor se prodlouˇz´ıa v pˇreskoˇcen´eˇc´astibudou sam´enuly (samotn´e lseek nestaˇc´ı).Nˇekter´efilesyst´emy takov´ebloky cel´ych nul pro ´usporu m´ıstane- ukl´adaj´ı.
• Velikost souboru je moˇzn´ezjistit pomoc´ı lseek(fildes, 0, SEEK END).
• Nejˇcastˇejˇs´ıoperace s lseek jsou tˇri: nastaven´ıkonkr´etn´ıpozice od zaˇc´atku souboru, nastaven´ıpozice na konec souboru a zjiˇstˇen´ıaktu´aln´ıpozice v sou- boru (0 spoleˇcnˇese SEEK CUR) • Pˇripouˇzit´ı lseek se ˇz´adn´eI/O neprovede, tj. ˇz´adn´ypˇr´ıkaz se nepoˇslena ˇradiˇcdisku.
• lseek nemus´ıslouˇzitjen pro operace read a write, ale tak´epro n´aslednou operaci lseek
• Seekov´an´ıa z´apism˚uˇzev´estk probl´em˚umse z´alohami.Pˇr´ıklad: read/big-file.c demonstruje, ˇzepˇresun souboru s ”d´ırami”(tzv. sparse file) m˚uˇzev´estk n´ar˚ustuvelikosti souboru co se t´yˇceblok˚ualokovan´ych file syst´emem.Chov´an´ı z´aleˇz´ına kombinaci operaˇcn´ıhosyst´emu, archivn´ıhoprogramu a file syst´emu (a jejich verz´ı).Nˇekter´eprogramy maj´ıpˇrep´ınaˇce,kter´eumoˇzn´ıd´ıry zachovat (napˇr. dd s conv=sparse, tar s -S, rsync s --sparse, atd.). • Pozor na pˇrehozen´ıparametr˚u.Druh´aˇr´adka samostatnˇevypad´aOK, ale m´a pˇrehozen´eparametry. SEEK SET je nav´ıc0 a SEEK CUR je 1, takˇze v´asto nikam neposune a nic ˇspatn´ehose nestane, a o to je horˇs´ıto pak naj´ıt.
lseek(fd, 1, SEEK_SET) lseek(fd, SEEK_SET, 1)
100 Change file size: truncate()
int truncate(const char *path, off t length ); int ftruncate(int fildes, off t length ); • causes the regular file to be truncated to a size of precisely length bytes. • if the file was larger than length, the extra data is lost • if the file previously was shorter, it is extended, and the extended part reads as null bytes
• zruˇsitveˇsker´yobsah souboru pˇriotevˇren´ıse d´apˇr´ıznakem O TRUNC ve funkci open. • podrobnosti je tˇrebahledat v manu´alov´estr´ance,napˇr.ve FreeBSD v sekci BUGS nalezneme toto: Use of truncate to extend a file is not portable.
101 Descriptor duplication: dup(), dup2()
int dup(int fildes ); • creates a copy of the file descriptor fildes, using the lowest-numbered unused descriptor. Returns the new descriptor.
• same as fcntl(fildes, F DUPFD, 0); (will be later) int dup2(int fildes, int fildes2 ); • duplicates fildes to fildes2. • same as close(fildes2); fcntl(fildes, F DUPFD, fildes2);
• prvn´ıvoln´ydeskriptor se pouˇzijei u otev´ır´an´ıa vytv´aˇren´ısoubor˚u,viz strany 93a 94. • duplikovan´ya p˚uvodn´ıdeskriptor sd´ıl´ıstejn´eotevˇren´ısouboru a tedy i ak- tu´aln´ıpozici a m´odˇcten´ı/z´apis.
• ekvivalent pro dup2 nen´ızcela ekvivalentn´ı,napˇr.pokud je fildes rovn´y fildes2, tak se neprovede close(fildes2) a dup2 rovnou vr´at´ı fildes2. V´ıceviz POSIX 1003.1 (ˇc´astXSH, System interfaces).
102 Example: implement shell redirection
• $ program < in > out 2>> err close(0); open("in", O_RDONLY); close(1); open("out", O_WRONLY | O_CREAT | O_TRUNC, 0666); close(2); open("err", O_WRONLY | O_CREAT | O_APPEND, 0666); • $ program > out 2>&1 close(1); open("out", O_WRONLY | O_CREAT | O_TRUNC, 0666); close(2); dup(1);
• note the flag O APPEND used to implement a redirection >>. • Dalˇs´ı pˇr´ıklad pouˇzit´ı dup uvid´ıme, aˇzse budeme zab´yvat rourami. Prvn´ı pˇresmˇerov´an´ı(bez stderr) je v read/redirect.c . Vol´an´ı execl v tomto pˇr´ıkladunahrad´ıaktu´aln´ıobraz bˇeˇz´ıc´ıhoprocesu obrazem programu pˇreda- n´ehojako prvn´ıargument. V´ıceo vol´an´ı execl je na stranˇe 131. • pro pochopen´ıtoho jak funguje pˇresmˇerov´an´ıje dobr´esi nakreslit tabulku deskriptor˚uv ˇcasea kam ”ukazuj´ı”.napˇr.pro druh´ypˇr´ıklad(inici´aln´ıstav, stav po close(1) open("out", ...), koneˇcn´ystav):
+------+ +------+ +------+ | 0 +-> stdin | 0 +-> stdin | 0 +-> stdin +------+ +------+ +------+ | 1 +-> stdout ===> | 1 +-> "out" ===> | 1 +-> "out" +------+ +------+ +------+ ^ | 2 +-> stderr | 2 +-> stderr | 2 +----/ +------+ +------+ +------+
• Je potˇrebasi d´atpozor na stav deskriptor˚u.Druh´ypˇr´ıkladnebude fungovat, kdyˇzbude deskriptor 0 uzavˇren,protoˇze open vr´at´ıdeskriptor 0 (prvn´ıvoln´y) a dup vr´at´ıchybu (pokus o duplikaci uzavˇren´ehodeskriptoru). Moˇzn´eˇreˇsen´ı:
close(1); if((fd = open("out", O WRONLY | O CREAT | O TRUNC, 0666)) == 0) dup(0);
103 close(2); dup(1); if(fd == 0) close(0);
nebo
fd = open("out", O WRONLY | O CREAT | O TRUNC, 0666); if(fd != 1) { dup2(fd, 1); close(fd); } dup2(1, 2);
Manipulate file descriptors and devices: fcntl(), ioctl()
int fcntl(int fildes, int cmd, ...); • provides file descriptor duplication, setting descriptor and file status flags, and advisory and possibly mandatory locking. Example: close standard error output on program execution (exec call) fcntl(2, F SETFD, FD CLOEXEC); int ioctl(int fildes, int request, ... ); • manipulates the underlying device parameters of special files • used as a universal interface for manipulating devices. Each device defines a set of requests it understands.
• jak pozdˇejiuvid´ıme,i k socket˚umse pˇristupujepˇressouborov´edeskriptory, a je tedy moˇzn´e fnctl pouˇz´ıt i na nˇe,tˇrebapro nastaven´ı neblokuj´ıc´ıho socketu. V´ıceinformac´ıviz strana 192.
• moˇzn´ehodnoty cmd ve funkci fcntl:
– F DUPFD . . . duplikace deskriptoru – F GETFD . . . zjiˇstˇen´ıpˇr´ıznak˚udeskriptoru (FD CLOEXEC – uzavˇren´ıpˇri exec). FD CLOEXEC je jedin´yflag pro deskriptory, definovan´yv normˇe UNIX 03. – F SETFD . . . nastaven´ıpˇr´ıznak˚udeskriptoru
104 – F GETFL . . . zjiˇstˇen´ım´oduˇcten´ı/z´apisa pˇr´ıznak˚uotevˇren´ısouboru (jako u open) – F SETFL . . . nastaven´ıpˇr´ıznak˚uotevˇren´ısouboru (O APPEND, O DSYNC, O NONBLOCK, O RSYNC, O SYNC). Nemohu nastavit pˇr´ıznakypro RO/RW a ani pˇr´ıznakypro vytvoˇren´ı, zkr´acen´ınebo exkluzivn´ıpˇr´ıstupk sou- boru. – F GETLK, F SETLK, F SETLKW . . . nastavov´an´ız´amk˚u • je d˚uleˇzit´esi uvˇedomit,ˇzejsou dva druhy pˇr´ıznak˚u– pˇr´ıznak(y)pro sou- borov´ydeskriptor a pˇr´ıznaky pro jedno konkr´etn´ı otevˇren´ı souboru – tj. pˇr´ıznakyjsou uloˇzen´eve dvou r˚uzn´ych tabulk´ach.
• perifern´ızaˇr´ızen´ıpodporuj´ıˇcten´ıa z´apisdat pomoc´ı read, write a mapov´an´ı dat do pamˇeti(mmap), veˇsker´edalˇs´ıoperace se zaˇr´ızen´ım(napˇr.nastaven´ı parametr˚u,zamˇcen´ınebo eject) se dˇelaj´ıfunkc´ı ioctl. • pˇrinastavov´an´ı pˇr´ıznak˚unejdˇr´ıv vˇzdyzjistˇete, jak´ebyly pˇredt´ım. I kdyˇz jste si jisti, ˇzev dan´echv´ılijsou nulov´ea je tedy moˇzn´eprov´est fcntl(fd, O APPEND), nem˚uˇzetevˇedˇet,co se m˚uˇzezmˇenit(napˇr´ıklado p´arˇr´adk˚uv´yˇse nˇejak´yflag pˇrid´ate,aniˇzbyste vˇedˇeli,ˇzejste ovlivnˇenik´odemdole). Tedy vˇzdypouˇzijtenapˇr´ıkladtoto:
flags = fcntl(fd, F_GETFL); if (fcntl(fd, F_SETFL, flags | O_APPEND) == -1) ...
. . . a podobnˇepro odebr´an´ıflagu – je ˇspatn´eˇreˇsen´ınastavit hodnot˚uflag˚una nulu, m´ıstotoho je tˇrebapouˇz´ıtbitov´ehojedniˇckov´ehodoplˇnkupˇr´ısluˇsn´eho flagu (flags & ~O APPEND).
105 Get file status information: stat()
int stat(const char *path, struct stat *buf ); int fstat(int fildes, struct stat *buf ); • for a file specified by a path or a file descriptor, returns a struct containing file information, such as: – st ino . . . i-node number – st dev . . . ID of device containing file – st uid, st gid . . . user/group ID of owner – st mode . . . file type and mode – st size, st blksize, st blocks . . . total size in bytes, preferred blocksize for filesystem I/O, and number of 512B blocks allocated – st atime, st mtime, st ctime . . . time of last access, last modification, and last i-node modification – st nlink . . . number of hard links
• update ˇcasuposledn´ıho pˇr´ıstupuk souboru lze na bˇeˇzn´ych file syst´emech vy- pnout pomoc´ıoptionu noatime pˇr´ıkazu mount. Hodit se to m˚uˇzepro urych- len´ı,pokud se prov´ad´ıˇcten´ıvelk´ehomnoˇzstv´ısoubor˚ua nez´aleˇz´ına ˇcasu pˇr´ıstupuna tˇechto souborech (napˇr.pˇrikompilaci). • Metadata jsou informace o souboru – tedy m´od,ˇcasypˇr´ıstupu,d´elka, vlastn´ık a skupina atd. Nepatˇr´ımezi nˇeskuteˇcn´adata souboru, a ani jm´eno,kter´e nen´ıuloˇzenov r´amcidan´ehosouboru, ale v adres´aˇriˇciv adres´aˇr´ıch. • Metadata je moˇzn´epˇreˇc´ıst,i kdyˇzproces nem´apr´ava pro ˇcten´ıobsahu sou- boru.
• Touto funkc´ınez´ısk´amflagy deskriptoru ani flagy z pole tabulky otevˇren´ych soubor˚uv syst´emu, zde jde o informace ohlednˇesouboru uloˇzen´ehona pamˇe- t’ov´emm´ediu.
• Co se stane kdyˇzse zavol´a fstat na deskriptory 0,1,2 ? (pˇredpokl´ad´ameˇze nejsou pˇresmˇerovan´ez norm´aln´ıhostavu)
• st ctime nen´ıˇcasvytvoˇren´ısouboru (creation time), ale ˇcaszmˇeny inde- xov´ehouzlu (change time) • Norma nespecifikuje poˇrad´ıpoloˇzekve struktuˇreani nezakazuje pˇridatdalˇs´ı.
• Pˇr´ıklad: stat/stat.c
106 Get file status information (2)
• for a file type, in
• typ a pr´ava souboru jsou uloˇzena spoleˇcnˇev st_mode, proto existuj´ızmiˇno- van´amakra. • S IFMT specifikuje tu ˇc´astbit˚u,kter´ejsou vˇenovan´etypu souboru, makra pro jednotliv´etypy pak nejsou masky, ale hodnoty, takˇzetest na typ souboru je nutn´eudˇelattakto: (st mode & S IFMT == S IFREG). Vˇsechna makra jsou v normˇe,takˇzejejich pouˇz´ıv´an´ımzaruˇc´ımepˇrenositeln´yk´od.
• Pˇr´ıklad: stat/filetype.c
107 Setting file times
int utime(const char *path, const struct utimbuf *times ); • changes file last access and modification times • cannot change i-node access time (ctime) • calling process must have write permission for the file
• Tuto funkci pouˇz´ıvaj´ıhlavnˇekop´ırovac´ıa archivaˇcn´ıprogramy, aby zajistily stejn´eˇcasykopie a origin´alu (napˇr. tar nebo rsync). • Shellov´erozhran´ıpro funkci utime pˇredstavuje pˇr´ıkaz touch. Mˇenittakto ˇcasmodifikace i-uzlu ale nelze.
108 Check permissions for access: access()
int access(const char *path, int amode ); • checks whether the calling process can access the file path • amode is an OR-combination of contants – R_OK . . . read permission test – W_OK . . . write permission test – X_OK . . . execution permission test – F_OK . . . file existence test • in contrast to stat(), the result depends on the process’s RUID and RGID • never use this call, it cannot be used in a safe way. See below.
• Vol´an´ı access aplikuje mechanismus testov´an´ıpˇr´ıstupov´ych pr´avk zadan´emu souboru pro volaj´ıc´ıproces a vr´at´ıv´ysledek.
• Funkce access vol´an´ıbyla pro setuid proces, aby si mohl ovˇeˇrit,zda uˇzivatel bˇeˇz´ıc´ıdan´ysetuid proces by mˇelza norm´aln´ıch okolnost´ık pˇr´ısluˇsn´emu sou- boru pˇr´ıstup.Z toho vypl´yv´a,ˇzetoto vol´an´ıje security hole – mezi testem a n´aslednouakc´ıse soubor m˚uˇzezmˇenittˇrebatak, ˇzep˚uvodn´ı(m˚uj)sou- bor smaˇzua vytvoˇr´ım symbolick´ylink se stejn´ymjm´enemna soubor, ke kter´emu bych jinak nemˇelpˇr´ıstup. Toto proces nem˚uˇzenikdy oˇsetˇrit,takˇze vesele zmodifikuje soubor, kter´ybych jako uˇzivatel nikdy nemohl zmˇenit. Spr´avn´ymˇreˇsen´ımje vr´atitse zp´atkyk re´aln´ymUID/GID a pˇr´ıstup rovnou vyzkouˇset.Pokud napˇr´ıkladdan´ysoubor otevˇreme,uˇzn´amho nikdo pod rukama “nevymˇen´ı”.
109 Setting file permissions
int chmod(const char *path, mode t mode ); • changes permissions of file path to mode. • can be used by the file owner or root
int chown(const char *path, uid t owner, gid t group ); • changes file owner and group for path. Value of -1 means do not change that ID. • only root change change owners so that users could not work around quotas to disown their files • a regular user can change a group of files he/she owns, and must belong to the target group
• parametr mode zde samozˇrejmˇeneobsahuje typ souboru, jako tomu je napˇr´ı- klad u vol´an´ı stat. Hodnoty mode viz chmod(2). • pokud nejsem vlastn´ık,nemohu celkem logicky zmˇenitm´odani u souboru s nastaven´ympˇr´ıstupem rw-rw-rw- • v nˇekter´ych implementac´ıch m˚uˇzevlastn´ık souboru pˇredatvlastnictv´ı nˇe- komu jin´emu, napˇr.v IRIXu je chov´an´ı chown nastaviteln´ejako parametr j´adra.
• nen´ıbˇeˇzn´evolat funkci chmod z uˇzivatelsk´ych aplikac´ı,na to se pouˇz´ıvaj´ı flagy u vol´an´ı open, hlavn´ıpouˇzit´ıje v aplikaci chmod(1)
110 File name manipulations
int link(const char *path1, const char *path2 ); • creates a new link (aka hard link), ie. a directory entry, named path2 to file path1. Hard links cannot span filesystems (use symlink for that). int unlink(const char *path ); • deletes a name (ie. a directory entry) and after deleting the last link to the file and after closing the file by all processes, delete the file data. int rename(const char *old, const char *new ); • change the file name (ie. one specific link) from old to new. Works within the same filesystem only.
• opˇetzd˚urazˇnuji,ˇze unix nem´avol´an´ıtypu delete na soubory. Podrob- nˇejiviz strana 69.
• vol´an´ı link vytv´aˇr´ıhardlinky, tj. zobrazen´ıze jm´enasouboru na ˇc´ısloi-uzlu. C´ıslai-uzl˚ujsouˇ jednoznaˇcn´apouze v r´amcisvazku, proto pro linky mezi filesyst´emy je nutn´epouˇz´ıtsymlinky.
• parametr path2 nesm´ıexistovat, tedy nelze takto pˇrejmenov´avat • unlink nefunguje na adres´aˇre • shellov´ypˇr´ıkaz mv pouˇz´ıv´a rename pro pˇresuny v r´amcijednoho svazku. Pˇresunsouboru mezi filesyst´emy vyˇzadujenejprve soubor zkop´ırovat a pak smazat origin´alvol´an´ım unlink. • rename funguje nad symlinky, ne nad soubory, na kter´esymlink ukazuje • existuje i vol´an´ı remove, viz strana 114.
111 Symbolic links
int symlink(const char *path1, const char *path2 ); • make a new symbolic name from path2 → path1. • path1 may span filesystems, and may not exist at all
int readlink(const char *path, char *buf, size t bufsz ); • put maximum of bufsz bytes from the symlink target path to buf • returns the number of bytes written to buf.
• buf is not terminated by ’\0’
• Shellov´ypˇr´ıkaz ln vol´a symlink nebo link, podle toho, jestli je pouˇzitpˇre- p´ınaˇc -s nebo ne. • Smaz´an´ıhardlinku nesmaˇze soubor, pokud na nˇejvede jeˇstˇejin´yhardlink. Naopak soubor (poloˇzku adres´aˇrei data) je moˇzn´esmazat, i kdyˇzna nˇej ukazuj´ınˇejak´esymlinky.
• readlink je pouˇziteln´yv situaci, pokud chci smazat soubor, na kter´ydan´y symlink ukazuje
• bufsize se typicky d´av´ao 1 menˇs´ı neˇzvelikost bufferu, to pro ukonˇcen´ı znakem ’\0’
112 Working with directories
int mkdir(const char *path, mode t mode ); • attempts to create an empty directory path with entries ’.’ a ’..’ int rmdir(const char *path ); • deletes directory path. The directory must be empty. DIR *opendir(const char *dirname ); struct dirent *readdir(DIR *dirp ); int closedir(DIR *dirp ); • sequentially reads directory entries • structure dirent contains: – d_ino . . . i-node number – d_name . . . file name
• Poloˇzkyadres´aˇrenejsou nijak uspoˇr´ad´any, readdir je m˚uˇzevracet v libo- voln´empoˇrad´ı.V pˇr´ıpadˇechyby se vrac´ıNULL jako pˇredt´ıma errno je na- staveno. Konec adres´aˇrese signalizuje t´ım,ˇze readdir vr´at´ıNULL a errno nen´ızmˇenˇeno.
• readdir je stavov´afunkce. Pro vr´acen´ıse na zaˇc´atekje moˇzn´epouˇz´ıtfunkci rewinddir. Pokud tuto funkci vol´atez v´ıcevl´aken je nutn´epouˇz´ıvat reent- rantn´ı readdir r, protoˇzestruktura dirent je statick´a. • V nˇekter´ych implementac´ıch (napˇr.FreeBSD) lze adres´aˇrotevˇr´ıtpro ˇcten´ı(ne pro z´apis)jako norm´aln´ısoubor a ˇc´ıstho pomoc´ı read, ale je tˇrebazn´atjeho vnitˇrn´ıorganizaci. Proto je readdir pro zpracov´an´ıobsahu adres´aˇrelepˇs´ı neˇz read, kter´yvrac´ıraw data adres´aˇre.Kromˇetoho, norma nevyˇzaduje, aby adres´aˇrbylo moˇzn´eˇc´ıstfunkc´ı read, Linux to napˇr´ıkladnedovol´ı. • d ino nen´ımoc uˇziteˇcn´e,protoˇzev pˇr´ıpadˇe,kdy dan´yadres´aˇrje mount point, tak ukazuje na adres´aˇr,na kter´yje dalˇs´ıfilesyst´em namontov´an,ne na koˇren namontovan´ehofilesyst´emu
• Nˇekter´esyst´emy maj´ıve struktuˇre dirent poloˇzku d type. Ta m˚uˇzenab´yvat hodnot DT REG, DT DIR, DT FIFO atd., viz manu´alov´astr´anka pro dirent. Byla to vˇecspecifick´apro BSD a n´aslednˇepˇrevzat´ai jin´ymisyst´emy, napˇr´ı- klad Linuxem. Nen´ıto souˇc´ast´ınormy a tedy to nen´ıpˇrenositeln´e. Pˇreno- siteln´yzp˚usobje na kaˇzdoupoloˇzkuzavolat stat.
• rmdir nefunguje na nepr´azdn´yadres´aˇr,mus´ıtesami smazat jeho obsah pˇred smaz´an´ımadres´aˇre.Nˇekdylze v k´odunal´eztzoufal´epokusy typu system("rm
113 -r xxx") coˇzm´asvoje nev´yhody (napˇr.z´avislostprogramu na shellu. D´ale pozor na sanitizaci promˇenn´ych prostˇred´ıa jm´enaadres´aˇre).
• Norma specifikuje i vol´an´ı remove, kter´ese chov´ajako unlink pro regul´arn´ı soubory, a jako rmdir pro adres´aˇre.
Example: read a directory
int main(int argc, char *argv[]) { DIR *d; struct dirent *de;
for(int i = 1; i < argc; i++) { d = opendir(argv[i]); while(de = readdir(d)) printf("%s\n", de->d_name); closedir(d); } return (0); }
• pˇr´ıkaz ls je zaloˇzenna takov´eto smyˇcce,nav´ıcprov´ad´ınapˇr.tˇr´ıdˇen´ıjmen soubor˚ua zjiˇst’ov´an´ıdalˇs´ıch informac´ıpomoc´ı stat. • konec adres´aˇrese pozn´atak, ˇze readdir vr´at´ı NULL. To vˇsakvr´at´ıi v pˇr´ıpadˇe, pokud nastala chyba. V takov´empˇr´ıpadˇeje k´odchyby v promˇenn´e errno, v pˇr´ıpadˇeprvn´ımje errno nezmˇenˇena.Proto by errno mˇelob´ytvˇzdyna- staven´ena nulu pˇredvol´an´ım readdir. V pˇr´ıkladutomu tak nen´ı,protoˇzez d˚uvodu m´alom´ıstanekontrolujeme errno v˚ubec.
• pˇr´ıklad: readdir/readdir.c
114 Change working directory
• every process has its current working directory. When a process refers to a file using a relative path, the reference is interpreted relative to the current working directory of the process. • the working directory is inherited from the process parent
int chdir(const char *path ); int fchdir(int fildes ); • changes working directory for the process
char *getcwd(char *buf, size t size ); • stores the absolute path to the current working directory to buf, its size must be at least one byte longer than the path length.
• funkci fchdir se pˇred´av´adeskriptor z´ıskan´yvol´an´ım open na adres´aˇr. • funkce getcwd m˚uˇzevr´atitjinou cestu neˇztu, po kter´ejsme se do aktu´aln´ıho adres´aˇredostali, jesliˇzeˇc´astcesty v chdir byl symlink nebo doˇslok pˇresunu (pˇrejmenov´an´ı)nˇekter´ehoadres´aˇrena cestˇeod koˇrene.U souˇcasn´ych unix˚u by se to ale uˇzst´atnemˇelo.
• na vˇetˇsinˇemodern´ıch unixov´ych syst´em˚uexistuje funkce chroot, kter´aumoˇz- ˇnujezmˇenitkoˇrenov´yadres´aˇrvolaj´ıc´ıhoprocesu na dan´yadres´aˇr.Je ˇcasto pouˇz´ıvan´av implementac´ıserver˚uk omezen´ıpˇr´ıstupupouze na dan´ypod- strom file syst´emu (napˇr.FTP servery). Pokud se pouˇz´ıv´apro zapezpeˇcen´ı, vyˇzadujeto zvl´aˇstn´ıopatrnost, protoˇzeexistuj´ıcesty jak se dostat do p˚uvod- n´ıhostromu. Pokud je nutn´ez chroot prostˇred´ıspouˇstˇetprogramy, nast´avaj´ı dalˇs´ı komplikace s nutnost´ı replikace kritick´ych syst´emov´ych soubor˚udo chroot prostˇred´ı(pokud nen´ıprogram upraven aby mˇelvˇsezabudovan´ev sobˇe).Tato funkce nen´ısouˇc´ast´ıaktu´aln´ıverze standardu (POSIX 1003.1- 2008).
– dalˇs´ı,mnohem obecnˇejˇs´ı,zp˚usoby izolace proces˚use daj´ınal´eztv uni- xov´ych syst´emech (jails v FreeBSD, zones v Solarisu, sandboxing v Mac OS X). Zpravidla se velmi liˇs´ıt´ımjak´ehranice dok´aˇz´ıvytyˇcit,k ˇcemu jsou urˇceny, zp˚usobem administrace, . . . .
115 Obsah
• ´uvod, v´yvoj UNIXu a C, program´atorsk´en´astroje • z´akladn´ıpojmy a konvence UNIXu a jeho API • pˇr´ıstupov´apr´ava, perifern´ızaˇr´ızen´ı,syst´emsoubor˚u • manipulace s procesy, spouˇstˇen´ıprogram˚u • sign´aly • synchronizace a komunikace proces˚u • s´ıt’ov´akomunikace • vl´akna,synchronizace vl´aken • ??? - bude definov´anopozdˇeji,podle toho kolik zbyde ˇcasu
116 Pamˇet’ procesu v uˇzivatelsk´emreˇzimu
text data bss adresovateln´e uˇziv.programem nelze adresovat z´asobn´ık { oblast user uˇziv.programem
• kaˇzd´yproces m´atˇriz´akladn´ısegmenty (pamˇet’ov´esegmenty, nemluv´ımeo hardwarov´ych segmentech): – text . . . k´odprogramu – data . . . inicializovan´epromˇenn´e – z´asobn´ık
• sekce text a data jsou uloˇzeny ve spustiteln´emsouboru • sekce pro inicializovan´ei neinicializovan´epromˇenn´ea heap jsou br´any dohro- mady jako data
• d´alelze do adresov´ehoprostoru pˇripojit segmenty sd´ılen´epamˇeti(shmat) nebo soubory (mmap). • text je sd´ılen vˇsemiprocesy, kter´eprov´ad´ı stejn´yk´od.Datov´ysegment a z´asobn´ıkjsou priv´atn´ıpro kaˇzd´yproces. • kaˇzd´ysyst´emm˚uˇzepouˇz´ıvat zcela jin´erozdˇelen´ıadresov´ehoprostoru pro- cesu (a typicky tomu tak je). Konkr´etn´ıpˇr´ıkladje na n´asleduj´ıc´ımslajdu, a zobrazuje i sekce pro mmap a heap. • bss . . . neinicializovan´epromˇenn´e(bss poch´az´ı z assembleru IBM 7090 a znamen´a,,block started by symbol”). Za bˇehu programu tvoˇr´ısekce data, bss a heap (nen´ına obr´azku)dohromady datov´esegmenty procesu. Velikost heapu lze mˇenitpomoc´ısyst´emov´ych vol´an´ı brk a sbrk.
117 • pozn´amka – neinicializovan´epromˇenn´ejsou statick´epromˇenn´e,kter´e(pˇrekva- pivˇe)nejsou inicializovan´e– tj. glob´aln´ıpromˇenn´enebo promˇenn´edefinovan´e jako static ve funkc´ıch i mimo funkce. Jak v´ıtez pˇredn´aˇseko jazyku C, vˇsechny tyto promˇenn´ejsou pˇristartu programu automaticky inicializovan´e nulami. Proto nen´ınutn´em´ıtjejich hodnotu v bin´arce.Jakmile ale nˇejakou z takov´ych promˇenn´ych inicializujete, bude jiˇzsouˇc´ast´ıdatov´ehosegmentu programu na disku. • (uˇzivatelsk´y)z´asobn´ık . . . lok´aln´ınestatick´epromˇenn´e,parametry funkc´ı(na urˇcit´ych architektur´ach v dan´ych modech - 32-bit x86), n´avratov´eadresy. Kaˇzd´yproces m´adva z´asobn´ıky, jeden pro uˇzivatelsk´yreˇzima jeden pro reˇzimj´adra.Uˇzivatelsk´yz´asobn´ıkprocesu automaticky roste podle potˇreby (neplat´ı,pokud se pouˇz´ıvaj´ıvl´akna,tam m´anav´ıckaˇzd´evl´aknoz´asobn´ık sv˚uj).
• oblast user (u-area) . . . obsahuje informace o procesu pouˇz´ıvan´ej´adrem,kter´e nejsou potˇrebn´e, kdyˇzje proces odloˇzenna disku (poˇcetotevˇren´ych soubor˚u, nastaven´ıoˇsetˇren´ısign´al˚u,poˇcetsegment˚usd´ılen´epamˇeti,argumenty pro- gramu, promˇenn´eprostˇred´ı,aktu´aln´ıadres´aˇr,atd.). Tato oblast je pˇr´ıstupn´a pouze pro j´adro,kter´evˇzdyvid´ıpr´avˇejednu u-oblast patˇr´ıc´ıpr´avˇebˇeˇz´ıc´ımu procesu. Dalˇs´ıinformace o procesu, kter´ej´adrom˚uˇzepotˇrebovat i pro jin´y neˇzpr´avˇebˇeˇz´ıc´ıproces, nebo i kdyˇzje proces odloˇzen, jsou ve struktuˇre proc. Struktury proc pro vˇsechny procesy jsou st´alerezidentn´ıv pamˇetia viditeln´e v reˇzimu j´adra.
Pˇr´ıklad:Solaris 11 x86 32-bit
• z obr´azkulze vyˇc´ıstnˇekolik dalˇs´ıch vˇec´ı:
118 – maxim´aln´ıvelikost kernelu pro Solaris 11 x86 32-bit je 256 megabajt˚u – mezi namapov´an´ımkernelu a pamˇet´ıvyhrazenou pro mmap je voln´em´ısto – z´asobn´ıkroste smˇeremk niˇzˇs´ımadres´ama jeho velikost je omezena na 128 megabajt˚u
• heap je ˇc´astpamˇeti,kterou si proces m˚uˇzezvˇetˇsovat pomoc´ıvol´an´ı brk a sbrk, a je ˇcastopouˇz´ıvan´afunkc´ı malloc. Funguje to tak, ˇze malloc si po- stupnˇezvˇetˇsujeheap podle potˇreby, a pˇriˇrazenoupamˇet’ internˇespravuje a pˇridˇelujeji procesu po ˇc´astech. Kdyˇztedy vol´ate free, neznamen´ato, ˇze vrac´ıtepamˇet’ syst´emu, ale pouze intern´ımu alok´atoru.
• oblast pro mmap se pouˇz´ıv´apro mapov´an´ısoubor˚u,tedy i sd´ılen´ych knihoven. Nˇekter´ealok´atorypouˇz´ıvaj´ıinternˇei tuto pamˇet’, napˇr´ıkladpro vˇetˇs´ıkusy pamˇetiˇz´adan´enajednou. Je moˇzn´eexkluzivnˇepouˇz´ıvat pouze mmap, pro apli- kaci je to zcela transparentn´ı.Pˇripouˇzit´ı mmap je moˇzn´epamˇet’ syst´emu vracet (vol´an´ım munmap), na rozd´ılod implementace pomoc´ı brk/sbrk. • obr´azekbyl pˇrevzatz [McDougall-Mauro], a nen´ına nˇemoblast pro neini- cializovan´epromˇenn´e.Pokud si ale na tomto syst´emu nech´atevypsat ad- resu jedn´ez nich, zjist´ıte,ˇzeinicializovan´ei neinicializovan´epromˇenn´esd´ıl´ı spoleˇcn´ydatov´ysegment, na obr´azkuoznaˇcen´yjako ,,executable – DATA”. Pˇr´ıklad: pmap/proc-addr-space.c
• mapov´an´ıkernelu nen´ınutn´e,napˇr´ıkladu Solarisu na amd64 architektuˇre (tj. 64-bit) uˇzkernel do uˇzivatelsk´ehoprostoru procesu mapov´annen´ı.
• brk ani sbrk nejsou souˇc´ast´ı normy, pˇrenositeln´eaplikace by proto mˇely pouˇz´ıvat, pokud podobnou funkcionalitu potˇrebuj´ı,vol´an´ı mmap, viz strana 140.
119 Pamˇet’ procesu v reˇzimu j´adra
text j´adra data a bss j´adra (tabulky, promˇenn´e,apod.)
struktura user beˇz´ıc´ıhoprocesu
extern struct user u; z´asobn´ıkj´adra
• proces se dostane do reˇzimu j´adrabud’ pˇr´ıchodem pˇreruˇsen´ıvyvolan´ehoproce- sorem (v´ypadekstr´anky, nezn´am´ainstrukce,...), ˇcasovaˇcem (v pravideln´ych intervalech je potˇreba aktivovat pl´anovaˇcproces˚u), perifern´ım zaˇr´ızen´ım, nebo instrukc´ısynchronn´ıhopˇreruˇsen´ı(standardn´ıknihovna takto pˇred´av´a ˇr´ızen´ıj´adru,aby obslouˇzilo syst´emov´evol´an´ı).
• v pamˇetije pouze jedna kopie k´odua dat j´adra,sd´ılen´avˇsemiprocesy. K´od j´adraje vˇzdycel´yrezidentn´ıv pamˇeti,nen´ıodkl´ad´anna disk. • text j´adra . . . k´odj´adraoperaˇcn´ıhosyst´emu, zaveden´ypˇristartu syst´emu a rezidentn´ıv pamˇetipo celou dobu bˇehu syst´emu. Nˇekter´eimplementace umoˇzˇnuj´ıpˇrid´avat funkˇcn´ımoduly do j´adraza bˇehu (napˇr.pˇripˇrid´an´ınov´eho zaˇr´ızen´ıse do j´adradynamicky pˇrid´anov´yovladaˇc),nen´ıproto tˇrebakv˚uli kaˇzd´ezmˇenˇeregenerovat j´adroa restartovat syst´em. • data a bss j´adra . . . datov´estruktury pouˇz´ıvan´ej´adrem,souˇc´ast´ıje i u-oblast pr´avˇebˇeˇz´ıc´ıhoprocesu. • z´asobn´ıkj´adra . . . samostatn´ypro kaˇzd´yproces, je pr´azdn´y,jestliˇzeje proces v uˇzivatelsk´emreˇzimu (a tedy pouˇz´ıv´auˇzivatelsk´yz´asobn´ık).
120 Pamˇet’ov´esegmenty procesu
a segs read only struct as text s as shared s prev s next read/write data private struct proc read/write z´asobn´ık private
read/write sd´ılen´apamˇet’ shared
• takto vypad´avˇetˇsinoureprezentace pamˇet’ov´ych segment˚uprocesu v j´adˇre. • z´akladn´ımrysem t´etoarchitektury je tzv. memory object, coˇzje abstrakce mapov´an´ımezi kusem pamˇetia m´ıstem,kde jsou data norm´alnˇeuloˇzena(tzv. backing store nebo data object). Takov´em´ıstouloˇzen´ım˚uˇzeb´ytnapˇr´ıklad swap nebo soubor. Adresov´yprostor procesu je pak mnoˇzinamapov´an´ına r˚uzn´edatov´eobjekty. Existuje i anonymn´ıobjekt, kter´ynem´am´ıstotrval´eho uloˇzen´ı(pouˇz´ıv´ase napˇr´ıkladpro z´asobn´ık).Fyzick´apamˇet’ pak slouˇz´ıjako cache pro data tˇechto namapovan´ych datov´ych objekt˚u. • tato zde velmi hrubˇepopsan´aarchitektura se naz´yv´aVM (od Virtual Me- mory), a objevila se v SunOS 4.0. Na t´etoarchitektuˇreje zaloˇzenaarchitek- tura viru´aln´ıpamˇetiv SVR4. V´ıceinformac´ıviz [Vahalia], p˚uvodn´ıˇcl´anek z roku 1987 pˇredstavuj´ıc´ı tuto architekturu: Gingell, R. A., Moran J. P., Shannon, W. A. – Virtual Memory Architecture in SunOS nebo pˇredn´aˇska o operaˇcn´ıch syst´emech na MFF (NSWI004 - Operaˇcn´ısyst´emy). • z jak´ych segment˚use skl´ad´apamˇet’ov´yprostor konkr´etn´ıhoprocesu lze zjistit pomoc´ıpˇr´ıkazu pmap(1) (na Solarisu, na NetBSD a v nˇekter´ych Linuxov´ych distribuc´ıch) nebo procmap(1) (v OpenBSD) nebo vmmap(1) v Mac OS X.
121 Virtu´aln´ıpamˇet’
pamˇet’ pamˇet’ pamˇet’ pamˇet’ procesu 1 procesu 2 procesu 3 procesu 4