2. Hogyan működik ?

2.1. Memóriakezelés, többfeladatos működés

A Linux - a DOS-tól eltérően - valódi többfeladatos (multitask) operációs rendszer. Kihasználva az Intel 80386 processzor nyújtotta fejlett tár és taszkkezelési lehetőségeket, valódi időosztásos környezetet biztosít. A 386-os processzor többféle üzemmódjai közül a Linux a "supervisor" üzemmódot használja a kernel, az operációs rendszer mag futtatására, ebben az üzemmódban a kernelnek hozzáférése van a gép összes fizikai erőforrásához, a felhasználói folyamatok (processzek) pedig ún. "user" üzemmódban futnak. A 386-os processzoron lehetőség van több, egymástól független "user" módú ún. taszk definiálására, amelyek egymástól védettek, nem tudják egymás és a felügyelő kernel memória- területét kiolvasni vagy módosítani, és a gép közvetlen hardver erőforrásaihoz sincs hozzáférésük (a valóságban ez úgy működik, hogy "user" módban csak a processzor utasításkészletének egy része hajtható végre, nem megengedett utasítás végrehajtásának kísérletekor vagy nem megendegett memóriacímre hivatkozáskor a vezérlés hibaüzenettel visszakerül a supervisor módban futó felügyelő programhoz, vagyis a kernelhez). Így biztosítható az egyes felhasználói programok egymástól való védelme. Mivel az egyes folyamatoknak a gép fizikai erőforrásaihoz (pl. winchester, képernyő) sincs közvetlen hozzáférésük, bármilyen perifériaműveletet csak a kernel meghívása útján végezhetnek, így mód nyílik peldául biztonságos file-rendszer megvalósítására is. Nincs az a trükk, amivel az egyik felhasználó el tudna olvasni olyan adatot, amihez nincs engedélyezett hozzáférése - amennyiben persze a biztonsági rendszerben nincsenek programozói hibák és a rendszer konfigurációja megfelelő. Az emberi gyarlóságot nem tekintve a Linux biztonságos többfelhasználós operációs rendszernek tekinthető.

A kernel teljes mértékben, fizikai szinten hozzáfér a gép erőforrásaihoz. Fizikai, a lehető legalacsonyabb szinten kezeli is a hardvert, a legnagyobb teljesítmény elérése érdekében. A boot-olást (rendszer betöltést) kivéve egyáltalán nem használja a BIOS-t: ennek oka, hogy a BIOS programja a DOS figyelembevételével készült, és nem alkalmas multitaszk operációs rendszer futtatására.

Memóriakezelésében szintén kihasználja a 386 által nyújtott lehetőségeket: lapozásos virtuális memóriakezelést használ, ahol a fizikai memóriát kiegészíthetjük a winchesterről vett virtuális memóriával (page vagy swap terület). A teljes memóriát lapokra osztja, ezen virtuális lapokat rendeli hozzá az egyes folyamatokhoz, és gondoskodik róla, hogy az éppen szükséges lapok a fizikai memóriában legyenek. Itt kell megemlíteni, hogy a Linux használja a virtuális tárkezelés mindkét (gyakran összekevert) fajtáját, a lapozást (paging) és a tárcserét (swapping) is. Lapozásnál folyamatoktól függetlenül, a rendszer arra ügyel, hogy a szükséges lapok a fizikai memóriában legyenek, ha azok esetleg diszken vannak, akkor gondoskodik memóriába olvasásukról, illetve a ha a fizikai memória teli van, akkor a ritkábban használt lapokat a diszkre írja. Tárcserénél pedig a rendszer figyelemmel kíséri az egyes folyamatok aktivitását is, es ha szabad memóriára van szükség, egy inaktív folyamat egészét háttértárra írja, felszabadítva ezzel a folyamat által használt összes fizikai memóriát. A Linux a két módszer keverékét használja: amíg bővében van a memóriának, csak egyes lapokat lapoz ki/be, de például ha úgy látja, hogy egy folyamat hosszú ideje inaktív, és nem csak egy-két lapnyi memóriára van szükség, akkor az adott folyamathoz tartozó összes fizikai lapot diszkre menti.

2.2. Automatikus diszk-gyorsítótár

Szorosan kapcsolódik a memória-lapkezelés mechanizmusához a Linux buffer cache kezelési módszere: a buffer cache a Unix rendszerek diszk- eléréshez használt gyorsítótárja, amelyet a kernel kezel, mivel minden folyamat csak és kizárólag a kernel meghívásával végezhet diszkműveletet. Linuxban a buffer cache mérete dinamikusan, a rendszer- terheléstől függően változik: mindig az éppen szabad fizikai memória egészét erre a célra használja. A diszk-irások is a buffer cache-n keresztül történnek: minden írás először a cache memóriába kerül, és vagy egy megadott idő elteltével iródik ki diszkre, vagy pedig akkor, ha a rendszer számára "elegendő" kiírnivaló összegyűlt. Ezért fontos az, hogy a megfelelő shutdown procedúra (a rendszer "lelövése", leállítása) végrehajtása nélkül soha ne kapcsoljuk ki a gépet: kikapcsolás előtt mindig szükséges a diszk tartalmának szinkronizálása a memóriában lévő állapottal, a nyitott file-ok lezárása - ezen lépések elmulasztása esetén kikapcsoláskor a diszk tartalma helytelen lehet, információk, egész file-ok veszhetnek el. Ugyanez történhet persze áramszünet vagy más hiba esetén is: ez az az ár, amit a Unix filerendszer által nyújtott nagyobb teljesítményért fizetnünk kell. A Unix-ok általában (így a Linux is) rendelkeznek funkciókkal az esetleges információvesztés minimalizálására, illetve a korrekt file-rendszer visszaállítására - tulajdonképpen egy átlagos Linux rendszerben váratlan rendszerösszeomláskor maximum csak a legutóbbi 30 másodperc munkája veszhet el - nagyon kicsi valószínűségű extrém esetektől eltekintve. De az ilyen adatvesztés veszélye minden, a diszk- írást bufferelő rendszerben fennáll.

2.3. Fejlett memóriakezelési technikák

2.3.1 A "demand paging" módszer

A fejlett memóriakezelés lehetővé teszi további, a teljesítményt növelő megoldások használatát is: ezek egyike az ún. "demand paging", ami azt jelenti, hogy egy futtatható file végrahatjtásakor nem az egész file töltődik be a memóriába, hanem mindig csak azok a lapjai, amelyekre a végrehajtás során éppen szükség van: gondoljunk csak bele, minden programnak vannak olyan részei (inicializálás, hibakezelő részek), amelyek csak egyszer, vagy éppenséggel egyszer sem futnak le - ezeket aztán vagy soha be sem tölti a rendszer a memóriába, vagy pedig miután lefutottak, rögtön fel is szabadítja az általuk elfoglalt területet.

2.3.2. Megosztott programkönyvtárak

Többfeladatos működés esetén, amikor egyszerre több program tartózkodik a fizikai memóriában, hasznos a Linuxban szintén használt "osztott könyvtár" (shared library) mechanizmus, vagy más néven a dinamikus (futásidejű) programösszefűzés (link). Alapötlete az, hogy mivel mindegyik program C-ben iródott és ugyanabban a környezetben fordult le, ezért valószínűleg lesz egy csomó olyan függvény (például a képernyőkezelő könyvtári függvények) amelyeknek kódja minden programban ugyanaz, és felesleges minden programmal együtt a memóriába tölteni őket, elég csak egyszer - csak a programok tudják, hol keressék a memóriában ezeket a függvényeket. Így minden programba elég egy "csonk"- nak (stub) nevezett programrészlet beépítése, amelyik a dinamikus linker segítségével gondoskodik a megfelelő függvény megtalálásáról illetve memóriába töltéséről, amennyiben az még nem lenne betöltve.

2.3.3. A copy-on-write mechanizmus

Még egy memóriakezelési finomság van, amelyet Unix rendszerekben előszeretettel használnak: ez pedig az úgynevezett copy-on-write (irásnál másold) mechanizmus, amely a következőképpen működik: multitaszkos operációs rendszerben gyakran lehet arra szükség, hogy bizonyos memória- lapokat több folyamat között megosszunk, vagy a legtipikusabb példa: Unix-ban új folyamat létrehozása mindig egy másik folyamat memóriájának lemásolásával történik. Mivel viszont egy memórialapra "többfelől", több folyamat memóriatérképéből tudunk hivatkozni, nem is kell azt a lapot lemásolni, csak elhelyezni az ugyanarra a lapra mutató hivatkozásokat a megfelelő helyeken. Mivel a memóriamásolás meglehetősen időigényes dolog, ezzel kritikus helyen (a felhasználó szemszögéből holtidőnek számító folyamat-létrehozáskor) sok időt takaríhatunk meg, és most már csak arra kell vigyáznunk, hogy ha az ugyanarra a lapra hivatkozó több folyamat közül valamelyik módosítani akarja a lapot, (mivel mindegyik folyamat azt hiszi, a memórialap csak az övé) akkor készítsünk csak annak a folyamatnak a számára másolatot, amelyet aztán módosíthat kedve szerint.

2.4. A folyamatok ütemezése

Mivel egy processzoron kell konkurrensen több feladatot végrehajtania, az operációs rendszernek, ezért valamilyen formában meg kell osztania a rendelekzése álló CPU időt az egyes folyamatok között. A Unix rendszerek (így a Linux is) a preemptív időosztásos ütemezés módszerét alkalmazzák, ami azt jelenti, hogy a rendelkezésre álló időt felosztja egyenlő részekre, és ezekből az egyenlő időszeletekből juttat - a folyamat prioritásának megfelelően - többet vagy kevesebbet az adott folyamatnak. Az egyes folyamatok prioritása természetesen állítható. Az ütemezés preemptív volta annyit jelent, hogy amikor az adott folyamat számára kijelölt időszelet letelt, a kernel megszakítja a folyamat futását és más folyamatnak adja át a vezérlést - nincs tehát mód arra, hogy egy folyamat a végtelenségig magánál tartsa a vezérlést, és megakadályozza a többi folyamat futását. Linuxban az ütemezés alapegysége az 1/100 másodperc.

Nem szabad azonban egy fontos dologról megfeledkeznünk: A Unix nem valós- idejű (real-time) operációs rendszer, ami annyit jelent, hogy ha több folyamat fut egyszerre, és az egyiktől elkerül a vezérlés, akkor valamekkora (rendszerint nagyon rövid) idő múlva vissza is fogja majd kapni - a két aktív (futó) állapot közti időre azonban nincs szigorú felső korlát. Az esetek 99.9999999 százalékában ez az idő (még egy leterhelt - de nem indokolatlanul túlterhelt rendszeren is) pár tized másodperc - azonban soha nem mondhatjuk, hogy biztosan csak ennyi. Ezt a tényt pontos és rövid időzítéseket használó programoknál nem árt szem előtt tartani.

2.5. Többfelhasználós működés

2.5.1. A terminál koncepció

A Linux, eltérően a PC-n eddig megszokott operációs rendszerektől, nem csak többfeladatos, ahol egy felhasználó egyidejűleg több programot futtathat (mint például a MS-Windows és az OS/2), hanem többfelhasználós is, vagyis egyidejűleg több felhasználó használhatja ugyanazt a rendszert, és mindegyikük akár több programot is futtathat. Ennek megvalósításához azonban szükség van néhány új fogalom, koncepció bevezetésére: Rögtön első problémaként jelentkezik az, hogy egy PC-nek csak egy billentyűzete, és (kevés kivételtől eltekintve) csak egy monitora van, amit értelemszerűen egyszerre csak egyvalaki használhat. A Unix filozófia minden egyes bejelentkezett felhasználóhoz hozzárendel egy egy úgynevezett terminált: egy terminál pedig egy billentyűzet + megjelenítő egység (leggyakrabban szöveges display) együttesét jelenti. Az adott Unixos géphez legközvetlenebbül csatolt terminált (Linux esetén a gép saját billentyűzetét és monitorát) konzol terminálnak (console terminal) nevezzük, ez abból a szempontból kitüntett, hogy bizonyos rendszeradminisztrációs feladatok csak innét hajthatók végre. További terminálok csatolhatók még a géphez soros vonalon (ez a legősibb Unixos megoldás, egy terminálemulációs szoftver és egy soros kábel segítségével akár kidobandó XT-inket is egyszerűen soros terminállá alakíthatjuk, illetve direkt erre a célra készült terminálokhoz manapság már fillérekért hozzájuthatunk). De köthetünk soros vonalra modemet is: ekkor a felhasználói terminál a telefonvonal "túlsó végén" lesz, távolról is elérhetővé téve rendszerünket.

A hálózaton vagy grafikus felületen keresztül bejelentkezett felhasználókhoz ún. pszeudo-terminálokat rendel a rendszer, ahol is a billentyűzet és a képernyő annak a gépnek a billentyűzetéhez és képernyőjéhez rendelődik, amely előtt a felhasználó ül. A terminálok megnevezése a szakzsargonban tty (angolul betűzve ejtik), illetve a pszeudo-termináloké pty vagy ttyp, a Linux ez utóbbi megnevezést használja. Minden Unix rendszer többféle, képességeik alapján osztályozható terminált képes kezelni: mivel nem alakult ki egységes szabvány, és a nagygépek hőskorában sokféle gyártó sokféle terminált gyártott, ezért a Unix rendszereket általában felkészítik a sornyomtató tipusú, sorüzemmódú, kurzor-címzésre nem képes termináloktól kezdve a modernebb, színkezelésre és akár ANSI grafikára képes terminálokig bezárólag sokféle termináltípus kezelésére. Az egyes terminálokat gyártó és típusra utaló megnevezéssel azonosítják: Amennyiben csak kozolról használjuk gépünket, elég annyit tudni hogy a konzol terminál azonosítója "console".

2.5.2. Az egyes felhasználók megkülönböztetése

Az egyes felhasználók azonosítására a "login név" (account, témaszám) rendszert használja a Unix: minden felhasználónak van egy (maximum 8 karakter hosszú, konvenció szerint kisbetűvel irott) azonosítója, és ehhez tartozik a maximum 8-16 karakter hosszú jelszó. A finomabb hozzáférés hierarchia kialakítása érdekében a felhasználókat csoportokba (groups) oszthatjuk: minden felhasználónak van egy elsődleges csoportja (pl. student), és ezen kívül tartozhat még más csoportokhoz is (pl. texusers). A csoportneveket is konvenció szerint kisbetűvel írják. Belsőleg a rendszer minden egyes felhasználóhoz az egyedi felhasználó- néven kívul még egy numerikus felhasználó és (esetleg több) csoport- azonosítót rendel (UID - user identification és GID - group identification). Léteznek kitüntetett felhasználónevek is, illetve legalább egy, amelyik minden rendszeren megvan: ez a "root" felhasználó, a rendszergazda azonosítója, aki felelős az adott rendszer karbantartásáért és üzemeltetéséért, és akinek a rendszeren "mindent szabad": ő az, akinek a rendszer egészéhez hozzáférése van. Fel kell itt hívni a figyelmet egy kialakult, de elkerülendő rossz gyakorlatra: sokan, akik csak egyedül használják Linuxos gépüket, minden tevékenységüket "root" hozzáférési jogokkal végzik, mondván, hogy így jobban hozzáférnek a rendszerhez, nem kell mindenféle korlátozásokkal vesződniük. Nem érdemes ezt a gyakorlatot folytatni, mert egy jól bekonfigurált rendszerben normál (nem privilegizált) felhasználókent is kényelmesen elérhetünk minden szolgáltatást, amire hétköznapi felhasználás során szükségünk lehet - viszont figyelmetlenséggel vagy elgépeléssel sokkal kisebb kárt tudunk okozni. Egy root jogokkal kiadott hibás vagy át nem gondolt utasítás egy pillanat alatt az egész rendszerünket jóvátehetetlenül tönkreteheti. Megjegyzendő még, hogy "root"-tal ekvivalens felhasználót akár többet is hozhatunk létre, az összes olyan felhasználó, akinek UID-je 0 (felhasználó létrehozásakor ezt megadhatjuk) root-tal ekvivalens lesz, de általában nem érdemes ezt tennünk: egy rendszeren éppen elég egy darab teljhatalmú felhasználó.

2.6. A file-okról

2.6.1. A Unix file koncepció

Mielőtt továbblépnénk, feltétlenül szükséges megismerkednünk még egy, az egész rendszert átható szervező elvvel: ez pedig a file koncepció. Unixban ugyanis (túlzás nélkül) az égvilágon minden file. Definíció szerint (kissé tudományosan) a file olyan "kommunikációs végpont", ahova vagy byte-folyamot (byte stream) tudunk írni, vagy byte-folyamot tudunk onnét olvasni (esetleg mindkettőt). Fileként kezelhető tehát a billentyűzet (csak olvasható), a szöveges képernyő (csak írható), a nyomtató, de még a fizikai memória tartalma is (!). A gépben lévő winchester szektorait (ha nem csak egyes file-okat akarunk elérni) is egy speciális file olvasásával illetve irásával érhetjük el, ugyanígy az hálózati eszközöket is a file-kezelés szabályainak megfelelően használhatjuk. Ez utóbbi három esetben persze szükség van a megfelelő jogosultságokra: a fizikai memória tartalmát vagy direktben a winchester szektorait "mezei" felhasználó nem láthatja. Ezt a file-orientált szervezésmódot (amely tulajdonképpen egy Unix rendszer fő szervező ereje) folyamatosan érdemes észben tartanunk: ha egyszer kellően átláttuk logikáját, sok addig bonyolultnak, lehetetlennek tartott művelet roppant egyszerűvé válik.

2.6.2. A file-rendszer struktúrája

A Unix file rendszere a DOS-hoz hasonló könyvtár rendszerű (helyesebben szólva a DOS hasonlít a Unixhoz), azzal a különbséggel, hogy itt nincsenek különböző meghajtók, hanem a rendszerben lévő minden file-t egy gyökérkönyvtárból kiindulva (ennek jelölése / könyvtár) elérhetünk. Fontos külőnbség még, hogy a Unix file-nevek nem a DOS-ból ismert 8+3 szabály szerint formálódnak: egy file-név maximum 255 karakter hosszú lehet, és tetszőleges karaktert tartalmazhat (vigyázat, tartalmazhat nem nyomtatható, nem gépelhető karaketereket is! Gonoszul elnevezett file- okkal sok bosszúságot okozhatunk magunknak és felhasználótársainknak.) Fontos külőnbség továbbá, hogy a Unix (nem csak file-nevekben, mindenhol) különbséget tesz kis- és nagybetű között (case sensitive). Az ALMA, Alma,alma,almA tehat mind-mind különböző file-okat jelentenek. Mivel file-névben pont is lehet, ezért Unixban is adhatunk kiterjesztéseket file- oknak: ezek azonban a rendszer számára semmilyen jelentéssel nem bírnak: csak a felhasználók eligazodását segíti elő, ha betartjuk a megfelelő file-nevezési konvenciókat. Azt sem a file-névből tudja meg a rendszer, hogy például az adott file futtatható-e vagy sem: a következő részben látni fogjuk, miből is derül ez ki. Előtte azonban még egy fontos dolgot tisztáznunk kell: hogyan valósul meg az, hogy a gépben több fizikai eszköz van (floppy, esetleg több winchester) és mégis az összes file-ot egy könyvtárstruktúrában látjuk ? Úgy történik, hogy van egy kitüntetett diszk (vagy partíció, esetleg ramdisk) amelyen a gyökér könyvtár ( / könyvtár) található, és a többi úgynevezett filesystem-et (filesystem-nek Unix alatt az egy diszken,partíción, egy rendszerbe szervezett file-ok összességét nevezzük) pedig a file-rendszer valamely alkönyvtárába lehet beilleszteni (mounting, igazán jó magyar terminológia mindezidáig nem született rá). Tehát ha van például egy /mnt/floppy alkönyvtárunk a rendszerben, es van egy floppy diszkünk, amelyen lévő filesystem-ben a /alma, /narancs és a /alma/starking könyvtárak vagy file-ok vannak, akkor a floppy "felmount-olása" után a /mnt/floppy/alma, /mnt/floppy/narancs és a /mnt/floppy/alma/starking könyvtárakat vagy file- okat fogjuk látni. Láttuk azt is, hogy Unixban az egyes könyvtárak szeparálására a DOS \ (backslash) karakterével ellentétben a / -t (slash) használják. Nem érdemes eltéveszteni, mert amint később látni fogjuk, a backslash karakternek is megvan a saját szerepe.

Unixban kétféleképpen adhatunk meg file elérési útvonalat, ez hasonlít a DOS-nál megszokottra: abszolút módon, a gyökérkönyvtárból indulva, amikor az elérési út neve / -rel kezdődik, vagy relatív módon, például ../../alma/starking, ami azt jelenti, hogy az aktuális könyvtárból lépjünk felfelé kettőt, és onnét lépjünk az alma könyvtárba, ha a starking-ot akarjuk megtalálni.

2.6.3. Többféle file-rendszer kezelése

A Linux képes arra, hogy többféle fizikai és logikai szervezésű filesystem-et egy könyvtárszerkezetben kezeljen: támogatja többféle Unix-os filesystem formátum mellett a DOS FAT filerendszert, tudja olvasni az OS/2 HPFS file-okat, ismeri a CD-s fileformátumokat, és tudja kezelni a TCP/IP hálózat felett működő hálózati file-rendszert az NFS-t is.

2.6.4. További érdekességek a file-rendszerről. A link

Még két Unix-os specialitásról kell beszélnünk: az egyik az, hogy abból hogy /mnt/floppy/narancs, nem derül ki, hogy ez a narancs egy könyvtár-e vagy egy file - ennek eldöntéséhez a file neve egyedül nem elég. A másik specialitás ismertetéséhez kicsit jobban bele fogunk mászni a Unix filerendszerek rejtelmeibe. A tárgyalt sajátosság a "link", az a tulajdonság, hogy egy file-nak egyszerre több neve is lehet: több néven is tudunk ugyanarra a file-ra hivatkozni (pl. megcsinálhatjuk, hogy a /gyumolcs/alma és a /holnap/reggeli file-nevek fizikailag ugyanarra a file-ra mutassanak). Ez pedig úgy lehetséges, hogy egy Unix filesystem-ben minden egyes file-hoz tartozik egy inode -nak nevezett rekord, amely tartalmazza a file nevét, létrehozásának dátumát és minden egyéb, a file-lal kapcsolatos adatot, kivéve a file tartalmát - többek között azt az információt is, hogy fizikailag a diszk melyik szektorában kezdődik az a file. Létrehozhatunk egy újabb inode-ot, amelyben a file neve más, de a kezdő szektor száma azonos: és máris két helyről hivatkozhatunk ugyanarra a file-ra. Törléskor pedig mindaddig csak az inode-okat töroljük, amíg el nem érünk az utolsóhoz, amikor már csak egy darab inode címzi meg a file-ot: ennek törlésekor szabadítjuk fel a file által elfoglalt diszkhelyet. Az ilyen típusú linket hard link-nek nevezzük, és van egy hátránya: csak ugyanazon a diszken illetve partíción lévő file-ra tudunk ilyet létrehozni, mert az inode-on belül nem tudunk mondjuk egy cserélhatő floppy vagy CDROM szektorszámaira hivatkozni - egy másik diszkről. Ezért találták ki az ún. szimbolikus vagy soft-linket, amely szintén egy link, de úgy működik, hogy a link maga egy speciális file, amiben a hivatkozott file neve van. Itt általában érdemes relatív nevekkel dolgozni, így később egész könyvtárszerkezetek, részfák másolásakor, mozgatásakor kevesebb problémába ütközünk. Mozgatás alatt az is értendő, ha az adott filesystem-et a könyvtárstruktúra egy más pontjára illesztjük be!

Láthattuk, hogy a .. itt is a szülő könyvtárra hivatkozás, a . pedig logikusan az aktuális könyvtárra utal. Unixban (mint minden), a könyvtárak is file-ként jelennek meg - ennek az is az előnye, hogy a könyvtár neve, a könyvtárban lévő . file és a könyvtár közvetlen alkönyvtáraiban lévő .. hivatkozások mind-mind ugyanarra az inode-ra, a könyvtár inode-jára mutató hard linkek. Ugye milyen logikus?

Ennyi elméleti alapozás után már éppen itt az ideje, hogy billentyűzetet ragadjunk, és elkezdjük egy Linux rendszer felfedezését a gyakorlatban is!

Tovább...