ITKA203 Käyttöjärjestelmät, luento 3/14, To 26.5.2011 ===================================================== Paikkausta eiliseen: -------------------- - Huomattakoon eilistä videoluentoa mahdollisesti katsottaessa että viivat tuli piirrettyä silloin tällöin miten sattuu, ja aina ei tullut ihan se oikea sana suusta ulos. Pääasiat ja painotukset tuli toki oikein. Yksityiskohdat sen sijaan kannattaa varmistaa kirjallisesta materiaalista (mun matsku tulee ensi viikoksi; Tietotekniikan perusteet -monisteeseen on linkki kurssin sivulta luennon 2 kohdalta). - Nykyisten prosessorien käskykannat sisältävät itse asiassa aika monimutkaisiakin käskyjä, jotka tapahtuvat useassa vaiheessa ja toteuttavat samalla kertaa useita asioita. Prosessori suorittaa sisäisesti ns. mikro-ohjelman. Ulospäin näyttää kuitenkin siltä, että prosessorille menee yksi käsky, joka löytyy käskykannasta. Käskyn jälkeen voi asioita olla muuttunut prosessorin rekistereissä ja lisäksi useimmiten myös jossakin muistipaikassa. - Muita nykyprosessorin ominaisuuksia: liukuhihnat (pipelines) mahdollistavat useamman käskyn suorituksen samaan aikaan, välimuistit (cache memory) nopeuttavat muistin käyttöä. Mutta: Ulospäin, ohjelman kannalta, näyttää siltä että on yksi muisti, jota voi osoittaa muistiosoitteilla. Prosessorin elektroniikka hoitaa välimuistien käytön. - Nykyisin tyypillistä on että tietokoneessa on moniydinprosessori, eli itse asiassa monta prosessoria rinnakkain. Tämä monimutkaistaa elektroniikkaa, koska prosessorien pitää päästä väylän kautta käsiksi samaan muistiin, ja niiden yhteistoiminta pitää olla järkevää, jos ne suorittavat rinnakkain jotain yhteistä tehtävää. Ja kas: tämäkään ei vaikuta siihen, että ohjelma on edelleen vain yksi konekielisten käskyjen sarja. Rinnakkaisuuteen palataan tarkemmin, kun päästään teemaan nimeltä "synkronointi". - Osoiteavaruus tarkoittaa niiden muistiosoitteiden joukkoa, joita konekieliset käskyt voivat käyttää. Osoitteita on nykyään reilusti enemmän kuin muistiin varsinaisesti mahtuu tavuja. Laitteisto (=prosessori) kartoittaa osoitteet, eli jotkut osoitteet ovat käytössä keskusmuistin osoittamista varten ja jotkut I/O -laitteita varten. Suuri osa ei ole käytössä lainkaan. - Miksi oikein käsiteltiin tietokoneen rakennetta näinkin tarkoin? Tarkoituksena oli havaita, mikä oikein on käyttöjärjestelmä, ja joitain syitä miksi sellainen tarvitaan. On selvää, että jos tietokoneelle syötetään yksittäinen ohjelma (siis konekieliset käskyt pötköksi muistiin), ja suoritetaan se (eli laitetaan nouto-suoritussykli käyntiin ensimmäisen käskyn osoitteesta), niin ohjelman loppuessa tietokone ei pysty tekemään mitään ennen kuin sille syötetään seuraava ohjelma. Tästä seuraa seisonta-aikaa. Eli tarvittaisiin mielellään automaattinen systeemi, joka käynnistää seuraavan jonossa olevan ohjelman heti kun edellinen on päättynyt. Jos on interaktiivinen ohjelma, joka odottaa käyttäjältä syötettä, eikä voi sillä välin tehdä mitään hyödyllistä, niin (1950-luvulla erittäin kallista) käyttöaikaa kuluu taas hukkaan. Tarvittaisiin automaattinen systeemi, joka voisi samaan aikaan hyödyntää prosessoria suorittamaan jotakin toista ohjelmaa. Eli tarvittaisiin "moniajon" mahdollisuus. Mm. näistä syistä on päädytty luomaan systeemejä, jotka nykyään tunnetaan nimellä käyttöjärjestelmä: Se on ohjelma, jonka avulla muut ohjelmat voidaan käynnistää ja jonka avulla muut ohjelmat pääsevät vuorotellen toimimaan. Nykyisellään moniajo on itsestäänselvyys. Moniajo ei tarvitse montaa prosessoria, mutta se tarvitsee prosessorilta tiettyjä ominaisuuksia, joihin palataan ensi viikon luennoilla. (etiäisenä sen verran että tärkeimpien ominaisuuksien nimet ovat "keskeytyskäsittely" ja "käyttöjärjestelmätila"). Tietotekniikan historian varrella on ilmennyt uusia tarpeita, joita varten on tarvittu uudenlaisia käyttöjärjestelmiä ja vastaavasti prosessoreita, jotka helpottavat näiden uudenlaisten käyttöjärjestelmien toimintaa. Käyttöjärjestelmä on välttämätön ratkaisu tarpeeseen hyödyntää teknologiaa helpommin ja kustannustehokkaammin. Toivottavasti välttämättömyyden ymmärtämistä helpottaa se, että nyt tunnetaan jollain tasolla prosessorin toimintaperiaate - ilman käyttöjärjestelmää se ei nimittäin selvästikään kovin kummoisiin ihmetekoihin kykenisi. Tämän päivän aiheet: -------------------- Tavoiteet olivat: - kerrata, mistä korkean tason kielellä ohjelmoimisessa on kyse. - ymmärtää kuinka ohjelma muuttuu tietokoneen "ymmärtämään" muotoon eli konekielelle (vrt. eilen kerrattu kerrosmalli) - nähdä päällisin puolin moderni esimerkki käskykannasta (x86-64) ja joitakin yksinkertaisia käskyjä. Aloitettiin tutummasta päästä: - Kirjoitin pienen ohjelman Javalla (jota on saatettu oppia Ohjelmointi 1 -kurssilla; on myös hyvin lähelle samankaltainen vaihtoehtoisesti opitun C# -kielen kanssa). Yllättäen ohjelman lähdekooditiedoston nimi oli ``HeiMaailma.java`` ja toimintalogiikka se vanha tuttu. - Mitäs sitten pitää tehdä? Ohjelma pitää kääntää "tietokoneen" ymmärtämään muotoon! Tietokone tässä tapauksessa tosin ei ole fyysinen laite, vaan Javan virtuaalikone (Java Virtual Machine, JVM). Mietitään eilistä kerrosmallia ja mihin tämä äsken nähty siinä sijoittuu. Kerrokset ylimmästä alimpaan: HeiMaailma.java (korkean tason ohjelmointikieli, ihminen ymmärtää) -- kääntäjä javac -- (tuottaa suoritettavan ohjelman ``HeiMaailma.class`` HeiMaailma.class (Javan tavukoodia, eli "konekielinen" ohjelma, ihminen ei ymmärrä mutta yhtä alemman kerroksen koneisto "ymmärtää") Java Virtual Machine (tarjoaa erään "käskyjoukkoarkkitehtuurin"; itse virtuaalikone on "oikeata" konekieltä ja se muuntaa Javan tavukoodin alemman kerroksen koneiston ymmärtämään muotoon eli tässä tapauksessa x86-64 -nimisen arkkitehtuurin konekieleksi; muunnos tapahtuu "lennosta" eli samalla kun ohjelman suoritus etenee) --- Käyttöjärjestelmät-kurssi liikkuu tämän rajan yläpuolella --- x86-64 (ISA, käskyjoukkoarkkitehtuuri) mikroarkkitehtuuri (kahden alimman kerroksen olemassaolo on hyvä digitaalilogiikka tiedostaa, mutta tällä kurssilla näihin ei enää juuri palata) Sitten kirjoitin saman pienen ohjelman C:llä. Miksi? Tavoitteena oli mm. näyttää että C-kielellä ohjelmointi ei sinänsä ole sen kummempaa kuin Javallakaan. Lisäksi päästiin demonstroimaan yhden kerroksen verran matalampaa konehierarkiaa sekä natiivia konekieltä. C-kielinen ohjelma piti kääntää fyysisen koneen (natiivi x86-64 eli Intel Xeon charra.it.jyu.fi -tietokoneessa) ymmärtämään muotoon! Kerrosmalli on nyt muutoin samanlainen kuin edellä, mutta JVM:ää ei ole mukana, koska nyt ohjelma käännettiin fyysisen tietokoneen ymmärtämään muotoon: HeiMaailma.c (korkean tason ohjelmointikieli, ihminen ymmärtää) -- kääntäjä gcc -- a.out (konekielinen ohjelma. gcc:n tuottama ohjelmatiedosto on nimeltään ``a.out``, jos siltä ei pyydä hienompaa nimeä, arvatenkin lisäämällä käännöskomentoon tietyt argumentit.) --- Käyttöjärjestelmät-kurssi liikkuu tämän rajan yläpuolella --- x86-64 (ISA, käskyjoukkoarkkitehtuuri) mikroarkkitehtuuri digitaalilogiikka Ensimmäisen puoliajan lopuksi näytin esimerkin emulaattorista ja päällekkäisistä virtuaalisista koneista: Space invaders (peli, 32-bittisen fyysisen prosessorin konekieltä; toimii MS-DOS -käyttöjärjestelmässä) (sekä käyttöjärjestelmänä FreeDos, "MS-DOS -kopio") JPC emulaattori (ISA, käskyjoukkoarkkitehtuuri... MUTTA kyseessä onkin java-ohjelma, joka vain "esittää" 32-bittistä fyysistä prosessoria, ts. tarjoaa ISA-rajapinnan isännöimilleen ohjelmille; tällaisen nimi on "emulaattori") JVM (virtuaalikone, kuten ekassa esimerkissä) (sekä käyttöjärjestelmänä Windows) x86 (ISA, käskyjoukkoarkkitehtuuri; luentosalin tietokoneen prosessori.) Eli meillä voi hyvin olla "tietokone tietokoneessa" ja jonkin ohjelman kannalta on ihan sama onko se oikeassa laitteessa vai emulaattorissa, kunhan joku osaa lukea ja suorittaa sen konekieliset käskyt. [Tauko 10 min] Sitten halusin tehdä monta asiaa yhtä aikaa, enkä ehkä ollut siinä yhtä hyvä kuin moderni käyttöjärjestelmä... Muun muassa halusin: - täydentää ymmärrystä komentoriviparametreista eli -argumenteista ylipäätään sekä erityisesti Javassa (vaikkeivät ne "Javamaisia" ole koskaan olleetkaan) ja C:ssä. - varmistaa, että hahmotetaan mitä tarkoittaa ohjelman peräkkäisyys ja suoritusjärjestys (ohjelma etenee lähdekoodin mielessä "ylhäältä alas" ellei muuta järjestystä määrätä kontrollirakenteiden avulla) - näyttää, kuinka ohjelmat kääntyvät peräkkäisiksi konekielisiksi käskyiksi, "nippu käskyjä" lähdekoodin kutakin kohtaa varten. [jälkihuomio: kontrollirakenteet tuottavat konekielisiä käskyjä toki esim. sekä ennen että jälkeen silmukan toistettavaa osaa; jos koodin optimointi on käytössä, voi yksittäisten käskyjen järjestys lomittua hiukkasen; nyt nähtiin vasta perusesimerkki.] - muistutella, mitä muuta kuin peräkkäisyyttä tarvitaan järkevien ohjelmien tekemiseen, mm. muuttujat, silmukat ym., ehtolauseet, aliohjelma-/metodikutsut. Kirjoitin siis ohjelman, johon lopuksi tuli kaikki edellämainittu eli: - argumenttien käsittely (luonnostaan sanon argumentteja usein jostain syystä komentoriviparametreiksi) - muuttuja - for-silmukka - ehtolause - aliohjelma ja aliohjelmakutsu. Ohjelma rakentui luennolla HeiMaailman pohjalta, mutta arkistoa varten nimesin lopullisen version uudelleen ``HeiKaikki.java`` ja ``heikaikki.c``. Ideana on siis verrata ohjelmia rivi riviltä, ja havainnoida erot C- ja Java-kielisten versioiden välillä. Ainakin minun mielestäni ne ovat pieniä, jopa "kosmeettisia". Jatkossa on tarkoitus tehdä demo, jossa nähdään sitten ne varsinaisemmat erot. Toivottavasti C-pelkokerroin on kuitenkin nyt pienentynyt alustavasti... Ja sitten vielä käänsin ohjelman symboliseksi konekieleksi, jota koetettiin alustavasti vähän katsella. Muun muassa havaittiin: - yleisnäkymä assembler-syntaksista: konekieliset käskyt näkyvät peräkkäin kirjainlyhenteinä (nostin esimerkeiksi "call" joka liittyy aliohjelman kutsumiseen, "cmpl" jossa "cmp" viittaa vertailemiseen, "jg" joka on lyhenne sanoista "jump if greater") Kirjainlyhenteiden perässä on usein yksi tai kaksi "jotakin muuta" asiaa", joista voitaneen jo tässä vaiheessa paljastaa että kyseessä on käskyn "operandit". Ne ovat esimerkiksi vakioarvoja tai niiden rekisterien nimiä, joita käskyn tulee käsitellä. - aliohjelma muodostaa oman konekielisen käskypötkönsä; "pääohjelma" taas on erillinen käskypötkö, joka kylläkin näyttäisi alkavan ja päättyvän ihan samalla tavalla kuin aliohjelmakin. - totesin alustavasti, että aliohjelmien alussa ja lopussa tapahtuu jotakin, johon tullaan palaamaan myöhemmin. Tässä vaiheessa riittää tällainen "päällisin puolin havainnointi". Asiaan sukelletaan (hieman) tarkemmin ensi viikolla. Yhteenveto: ----------- Mitä ohjelmissa tarvitaan: - tietorakenteita (olioita/struktuureja) - algoritmeja (metodeja/aliohjelmia) - muuttujia (jotta tietorakenteita ja algoritmeja voidaan tehdä) - kontrollirakenteita (jotta algoritmeissa olisi järkeä) Tarvitaan siis: - tapa, jolla muuttujia ja tietorakenteita pidetään muistissa - tapa, jolla tietty algoritmi otetaan käyttöön väliaikaisesti (eli siis "aliohjelmakutsu" / "metodikutsu") - tapa, jolla algoritmin parametreja voi vaihdella (eli "parametrin välitys") Tietokoneen käskykannan täytyy mahdollistaa ohjelmointi. Kuinka? Tähän palaamme ensi viikolla. Silloin tutustutaan konekielisiin käskyihin, jotka muodostavat erään "tavan" toteuttaa ohjelmissa tarvitut rakenteet Von Neumann -tietokonelaitteistoa käyttäen. Myös tätä, kieltämättä aika teknistä asiaa tarvitaan, jotta voidaan syvä-ymmärtää tarve tietyille käyttöjärjestelmän tehtäville. Ihan lopuksi vilautin nykyaikaisen Intel -prosessorin (esim. Xeon) manuaaleja. Äkkiseltään en hätäpäissään löytänyt niitä kohteita, joita yritin löytää, mutta ainakin voitiin todeta, että manuaali on kohtalaisen kokoinen (viisi osaa, joissa yhteensä tuhansia sivuja). Kovin yksinkertaisesta laitteesta ei siis nykyään enää ole kyse, mutta kurssilla tähän asti nähdyt perusperiaatteet ovat ilman muuta edelleen voimassa: mm. ohjelmat ovat käskykannasta löytyvien käskyjen pötköjä, joissa jokainen käsky tekee aina vain yhden varsin yksinkertaisen toimenpiteen rekisterejä ja muistia hyödyntäen. Ohjelmoijan näkökulmasta näyttää siltä, että prosessori toistuvasti noutaa ja suorittaa seuraavan käskyn, yksi kerrallaan.