Linux-järjestelmän rakenne
GNU/Linux-järjestelmä on varsin monimutkainen kokonaisuus. Tämän tarinan tarkoitus on valottaa järjestelmän sisäistä rakennetta yksinkertaistaen asioita ja takertumatta yksityiskohtiin. Tarina alkaa jakamalla järjestelmä osiin ja jatkuu käymällä osia läpi yksi kerrallaan aloittaen järjestelmän ytimestä eli kernelistä päätyen aina graafisiin sovelluksiin (ohjelmiin).
Yleiskuva
Oikeissa käyttöjärjestelmissä laitteistoa eli rautaa lähinnä on käyttöjärjestelmän ydin, kernel. GNU/Linux järjestelmän ytimen nimi on Linux, vaikka nykyään samaa nimeä käytetään monesti koko järjestelmästä. Kerneliin kuuluvat olennaisena osana laiteajurit.
Jo pelkän ytimen avulla voisi ajaa sovelluksia, mutta yleensä välissä on vähintään yksi kirjasto, standardi C-kirjasto, joka helpottaa suuresti ohjelmien kirjoittamista. Monesti mukana on myös liuta muita kirjastoja. Kirjasto on kokoelma ohjelmakoodia: käskyjonoja eli rutiineja, joita tarvitaan monissa sovelluksissa aina samalla tavalla (esimerkiksi rutiinit tekstin tulostamiseksi ruudulle).
Ylimpänä kuvassa ovat sovellukset eli hyötyohjelmat, esimerkiksi tekstieditori. Kun ihminen kirjoittaa tietokoneella, painelee näppäimiä, näppäinten painalluksista tulevat signaalit menevät ensimmäiseksi ytimen käsiteltäviksi. Ydin muuntaa signaalit yleisesti sovittuun muotoon ja antaa ne eteenpäin oikealle sovellukselle. Sovellus voi käyttää C-kirjastoa, jolloin signaalit tulevat sovelluksen pääohjelmaan C-kirjaston kautta.
Jos sovellus haluaa kertoa käyttäjälle jotakin, se käyttää C-kirjaston rutiinia, joka auttaa viestin koodaamisessa ja lähettämisessä ytimelle. Ydin käyttää laitteistoa, vaikkapa näyttöä, esittämään viestin käyttäjälle. Viesti koodataan aina samalla tavalla, joten viestin koodaava ohjelmanpätkä kannattaa olla kirjastossa. Näin jokaisen sovelluksen ei tarvitse itse erikseen sisältää tuota ohjelmanpätkää, vaan ne voivat käyttää yhteistä kirjastoa.
Ydin eli kernel
Ydin on sellainen ohjelma, joka pitää tietokoneen järjestyksessä. Linux (ydin) osaa moniajaa, mikä tarkoittaa, että se jakaa prosessoriaikaa vuorotellen eri käynnissä oleville prosesseille (ohjelmille, sovelluksille). Vuorottelu on niin nopeaa, että ohjelmat näyttävät toimivan yhtäaikaa (moniprosessorikoneissa ne voivat ihan oikeasti toimia yhtäaikaa). Ydin pitää huolen siitä, että kukin prosessi pysyy kiltisti omassa karsinassaan, eikä pääse sotkemaan muita prosesseja tahattomasti.
Ydin tarjoaa ohjelmille yhtenäisen rajapinnan - "käyttöliittymän" - kaikkiin järjestelmän resursseihin, kuten muistiin, äänikortille, näytölle, kiintolevylle jne. Näin jokaisen sovelluksen ei tarvitse tietää, miten jokaista erilaista laitetta ja piirikorttia pitää käsitellä, koska ydin hoitaa ne. Tai tarkemmin sanoen ajurit hoitavat ne. Ydin antaa prosessien käyttää näitä laitteita niin, ettei systeemi mene sekaisin, kun useampi ohjelma toimii "yhtäaikaa".
Kernel pitää huolta myös käyttäjien - tai pikemminkin prosessien - käyttöoikeuksista, eli siitä, mikä prosessi saa tehdä mitäkin. Esimerkiksi ydin voi sanoa, että sinulla (prosessilla) ei ole oikeutta poistaa jotakin tiedostoa. Tiedostoista puheenollen, ydin hoitaa myös kiintolevyjä ja muita massamuisteja niin, että niille voidaan tallentaa tietoja järkevällä tavalla: hakemistoihin ja tiedostoihin.
Ytimeen itseensä ei varsinaisesti ole mitään käyttöliittymää, vaan se tarjoaa ohjelmointirajapinnan. Voit siis kirjoittaa C-kielellä ohjelman, joka kutsuu suoraan kernelin toimintoja. Yleensä välissä käytetään jotakin kirjastoa, sillä ytimen rajapinta on varsin karu ja jopa vaikea käyttää. Toisaalta ytimessä on kyllä ajureita hoitamassa mm. näppäimistöä, mutta ydin itse ei tee näppäimistöllä tai sen syötteellä mitään (paria poikkeusta lukuunottamatta), vaan ohjaa näppäimistöltä tulevan datan jollekin prosessille, joka sitten tekee sillä mitä huvittaa, vaikkapa näyttää sen näytöllä (eli lähettää takaisin ytimelle toista reittiä).
Ytimellä on myös monia muita tehtäviä, esimerkiksi tietokoneverkkoihin ja ajanlaskentaan liittyen, mutta niitä ei tässä käsitellä.
Verrataanpa tähän mennessä kuvattua järjestelmää DOS:iin. DOS:ssa on command.com ja kaverit, jotka osaavat hoitaa joitakin asioita, kuten tiedostojärjestelmää, mutta siellä ei varsinaisesti ole ydintä. Kukaan ei valvo ohjelmien oikeuksia, joten mikä tahansa ohjelma pystyy tekemään ihan mitä vain, vaikkapa pyyhkimään koko kiintolevyn tyhjäksi. (Tämä on se perimmäinen syy, miksi Linuxissakaan ei kannata aina olla kirjautuneena pääkäyttäjänä.) Ohjelmia ei voi moniajaa, eikä DOS tarjoa mitään kovin hyödyllisiä ajureita: jos ohjelma haluaa käyttää esimerkiksi äänikorttia, sen pitää itse tietää, miten äänikortin mikropiiriä pitää käskyttää saadakseen oikean äänen ulos. Voi kuvitella, miten ikävää olisi tehdä DOS:lle ohjelmia, joiden pitäisi toimia mahdollisimman monessa erilaisessa kokoonpanossa, kun nykyaikaisissakin järjestelmissä on aina välillä yhteensopivuusongelmia.
Prosessit ja init
Tähän väliin hypätään hetkeksi sivupolulle ja selvitetään, mitä nuo edellä mainitut prosessit oikein ovat ja mistä ne tulevat.
Prosessi on käynnissä oleva ohjelma. Kiintolevyllä olevasta ohjelmasta syntyy prosessi, kun se käynnistetään. Jos sama ohjelma käynnistetään uudestaan, syntyy toinen, uusi prosessi. Prosesseja suoritetaan prosessorissa vuorotellen, koska yhdessä prosessorissa voi ajaa vain yhtä prosessia kerrallaan. Prosessiin kuuluu ohjelman koodi eli se ohjelma, jota ajetaan, sekä ohjelman tila, joka tarkoittaa kaikkien ohjelmassa käytettyjen muuttujien ja muistialueiden sisältöä. Ohjelman tilaan kuuluu myös tieto siitä, missä kohtaa ohjelmaa suoritus on menossa. Ohjelmahan on loppujenlopuksi vain tietyssä järjestyksessä oleva lista yksinkertaisia käskyjä.
Linuxissa prosessit on järjestetty hierarkiaksi, joka syntyy itsestään, kun uusia prosesseja luodaan. Ainoa tapa luoda uusia prosesseja on nimittäin tehdä olemassaolevasta prosessista klooni ja sitten vaihtaa sen ohjelmakoodi. Näin syntyy prosessien "sukupuu", ja uusi prosessi perii isäprosessilta ominaisuuksia, kuten käyttöoikeudet.
Mistä se ensimmäinen prosessi sitten tulee, kun järjestelmä käynnistetään, eikä yhtään prosessia vielä ole kloonattavaksi? Tämä onkin ainoa kerta, kun prosessi luodaan tyhjästä. Ydin luo sen käynnistyessään ja tätä ensimmäistä prosessia kutsutaan nimellä init. Init on kaikkien prosessien kantaisä. Jos jokin prosessi kuolee hierarkian keskeltä niin, että sen lapsiprosesseista tulee orpoja, init "adoptoi" ne. Niistä tulee siis init-prosessin lapsia. Init itse ei saa koskaan kuolla tai koko järjestelmä kaatuu.
GNU/Linux järjestelmän prosessihierarkiaa voi katsella esimerkiksi komennolla ps -ejH. Ydintä itseään ei mielletä prosessiksi.
Kirjastot
Kaikki ohjelmat haluavat tehdä tietynlaisia asioita, jotka tehdään aina samalla tavalla. Esimerkiksi kirjoittaa näytölle rivin tekstiä tai graafisessa tilassa piirtää suorakulmion. Ohjelma voisi periaatteessa tehdä sen käskyttämällä laitteistoa suoraan, mutta kuten aiemmin todettiin, se on hyvin vaikeaa, eikä luultavasti tulisi koskaan toimimaan kunnolla muiden ohjelmien kanssa (muistetaan, että Linux osaa moniajaa).
Niinpä homma kannattaisi ehkä tehdä ytimen tarjoamien palvelujen avulla, eipä tarvitsisi ainakaan välittää laitteistosta tai muista ohjelmista niin kovasti. Ytimen kautta se jo onnistuisi, mutta nyt huomataan, että jokainen ohjelma tekee saman asian: piirtää suorakulmioita, joista muodostuu kullekin ohjelmalle oma ikkuna näytölle.
Hommaa voidaan helpottaa tekemällä kirjasto, joka osaa piirtää suorakulmioita. Nyt ohjelmien ei enää tarvitse edes tietää, miten suorakulmio piirretään, vaan ne voivat käyttää kirjastoa, jossa on ohjeet (koodi) suorakulmion piirtämiseksi. Myöskään ohjelmoijan ei ole pakko tietää, miten suorakulmio piirretään, ja ohjelmointi on helpompaa. Ohjelmoija vain käskee piirtämään tietynlaisen suorakulmion ja luottaa, että kirjaston ohjelmoinut suorakulmioiden asiantuntija on osannut hommansa.
Tämä on siis kirjastojen perusidea, helpottaa ohjelmoijien elämää. Se helpottaa myös käyttäjien elämää, sillä kaikki suorakulmiokirjastolla piirretyt suorakulmiot ovat samanlaisia ja ne ymmärtää heti suorakulmioiksi. Hieman ontuva esimerkki, mutta varsinkin käyttöliittymien kanssa sillä on suuri merkitys. Jos kaikissa ohjelmissa ruksattava nappi näyttää samanlaiselta, se on hyvin helppo tunnistaa juuri ruksattavaksi napiksi ja vieläpä nähdä, onko se ruksattu vai ei.
Kirjastoja on maailma pullollaan, mutta yksi kirjasto on syytä esitellä hieman lähemmin. Se on jo aiemminkin mainittu standardi C-kirjasto. Se sisältää hyvin suuren määrän erilaisia ohjelmien perustoimintoja helpottavia rutiineja. Ohjelmoijalle se on kuin lämmin turkki talvipakkasella, sillä siellä on toteutettu monia ikäviä ja vaikeitakin asioita valmiiksi. Mikä parasta, se sisältyy C-kielen määritelmään, mikä tarkoittaa, että C-kielellä ohjelmoitaessa tuo kirjasto on lähes poikkeuksetta käytettävissä.
C-kirjastosta on useampia erilaisia toteutuksia, mutta Linux-maailmassa käytetyin niistä on Gnu C Library eli "glibc".
X-ympäristön rakenne
Lopuksi käsitellään erästä erikoisempaa järjestelmän osaa, joka on X Window System:iin, tuttavallisemmin X:ään, perustuva graafinen ympäristö. X:n termistöä näkee käytettävän varsin väljästi ja monesti suorastaan väärin, joten yritetään nyt tässä selvittää tilanne.
X-ympäristön selkäranka on X-palvelin. X-palvelin on ohjelma, joka osaa piirtää kuvia näytölle ja lukea käyttäjän komentoja: näppäimistöä, hiirtä, piirtopöytää jne. X-palvelin tuntee myös ikkunan käsitteen, mutta juuri mitään muuta se ei teekään (ainakaan sellaista, joka näkyisi tavalliselle käyttäjälle). X-palvelimia ovat mm. vapaat XFree86 ja X.org, mutta on olemassa myös kaupallisia vaihtoehtoja. Niitä on saatavilla moniin eri käyttöjärjestelmiin, jopa Microsoft Windowsiin. Niiden mukana tulee myös joukko muita ohjelmia, esimerkiksi yksinkertainen ikkunointiohjelma.
X-palvelin siis tietää, miten ruudulle piirretään pikseli, mitä tarkoittaa ikkuna ja miten käyttäjältä luetaan syötettä. X-palvelimella ei ole hajuakaan, miten käyttäjän syötteeseen pitäisi reagoida! Graafisten sovellusten tehtävä on tulkita käyttäjän liikkeitä ja toimia sen mukaisesti.
X-palvelimen lisäksi vaaditaan siis vähintään yksi ohjelma, jotta graafista ympäristöä voisi jotenkin käyttää. Monesti tämä ohjelma on ikkunointiohjelma. Se voi kyllä periaatteessa olla jokin muukin, vaikkapa peli. X-palvelin sammuttaa itsensä, kun se ohjelma päättyy.
Ikkunointiohjelman kanssa voikin jo työskennellä. Yleensä se tarjoaa jonkin hiiren napin takaa valikon, josta voi käynnistää graafisia ohjelmia. Ikkunointiohjelma mahdollistaa sen, että ikkunoita voi siirrellä, niiden kokoja muuttaa, niitä voi sulkea jne. Jotkut ikkunointiohjelmat tarjoavat enemmän toimintoja kuin toiset, toimivat hieman eri tavalla tai muuten vain näyttävät ja tuntuvat erilaisilta.
Kun puhutaan Linuxin graafisesta ympäristöstä, monelle tulevat mieleen heti KDE ja GNOME. KDE ja GNOME ovat kokonaisia työpöytäympäristöjä ja sisältävät suuren määrän erilaisia ohjelmia, joita voi käyttäjän kuvitella tarvitsevan. Yksi (ehkä jopa useampi) työpöytäympäristön sisältämistä kymmenistä tai sadoista ohjelmista on ikkunointiohjelma. Lisäksi voi olla kaikenlaista nappulapalkkia ja ikonihärdelliä.
Eräs X-ympäristön mielenkiintoisimmista ominaisuuksista on sen kyky toimia verkon yli. Sovellus voi pyöriä jossakin etäpalvelimella ja sen ikkuna näkyy käyttäjän nenän edessä olevassa monitorissa. Kun jokin graafinen sovellus eli X:n asiakasohjelma käynnistyy, se ottaa yhteyden X-palvelimeen, joka piirtää kuvan ja toimittaa käyttäjän komennot sovellukselle. Käyttäjällä on siis X-palvelin nenänsä edessä ja se etäpalvelimella ajettava sovellus on X:n asiakasohjelma. Termit ovat ikäänkuin väärinpäin, mutta näin asia toimii.