ITKA203 Käyttöjärjestelmät, luento 12/14, Ti 28.6.2011 ====================================================== Info: - Tähän asti palautetut demot (demo1-3, ei vielä demo4) on merkitty Korppiin. (Tarkistakaa, jos omalta kohdalta ei näy merkintää.) - Demo4 eli "miniharjoitustyö" on julkaistu. Katsottiin jonkinlainen pikaohje alkuun pääsemiseksi. Lyhyesti hieman palautetta demoista ----------------------------------- (Huomenna käytännön esimerkit parista palautetusta demovastauksesta) - Vielä kerran muistutettava: tarkkana merkkien kanssa, kun toimitaan shelleissä! - Ohjelmointi ei ole täysin hallussa kaikilla (kuten arvelinkin), vaikka olisi käyty Ohjelmointi 1. Tämä ei ole ohjelmointikurssi, mutta siihen liittyvä, joten huomioidaan jotain pientä: * ensin pitää tietää (edes hieman sinne päin), mitä haluaa tehdä; aika turha lähteä kirjoittamaan koodia, jos ei ole käsitystä siitä mitä haluaa saavuttaa; ts. kun kirjoittaa jotakin koodia niin pitää ymmärtää mitä se kirjoitettu pätkä tai sana tarkoittaa ja osata vastata itselleen kysymykseen: "miksi kirjoitin tähän nyt näin?" * alusta (so. tietokone, käyttöjärjestelmä, ohjelmointikieli, tietorakenteet, valitut kirjastot) on hyvä tuntea (siihen toivottavasti tämä kurssi auttaa). Uudesta alustasta pitää osata lukea käyttöohjeet (siihen tämä kurssi toivottavasti antaa jonkinlaista pohjakäsitteistöä). * kynä ja paperi voivat toimia ideoiden kehittelyssä paljon paremmin kuin näppäimistö! Ensin funtsitaan ja sitten vasta kajotaan koodiin. * kovin monimutkaisesti ei välttämättä kannata lähteä ratkaisemaan ohjelmointitehtävää... yksinkertaisuus on parasta. * ohjelma kannattaa kääntää ja ajaa aina mahdollisimman pienen muutoksen jälkeen, ettei ongelmien tullessa ole ehtinyt hukkua muistikuva siitä, mitä tulikaan muutettua. Tämän päivän aiheita -------------------- Asioita, joita olisi voinut mainita aiemmin, mutta mainitaan nyt: - Java-virtuaalikoneen tavukoodi ja disassembly; metodin suoritus, "this-viite". Operandipino, esim. käskyt aload, astore. - linkittäminen * yleiskäyttöiset aliohjelmakirjastot ilmeisen perusteltuja: Esim. on suuri työ tehdä tehokas laskenta- tai multimediakirjasto. Kannattanee siis käyttää sellaista uudelleen eri sovellusohjelmissa mahdollisuuksien mukaan. * linkitys (linking): kirjaston aliohjelmien muistiosoitteet "ilmoitetaan" ohjelmalle * staattinen linkitys (static linking): kirjasto mukana ohjelmatiedostossa, kutsut voivat olla suoraan (suhteellisiin) muistiosoitteisiin. * dynaaminen linkitys (dynamic linking): kirjasto erillään ohjelmatiedostosta; kutsut muistiosoitteisiin, jotka voidaan tuntea vasta kun ohjelmaa ajetaan.. "ilmoitetaan" osoitteet esim. hyppykäskyillä, joiden osoitteisiin kutsut kohdistuvat ja joihin lopulliset osoitteet saadaan laskettua käynnistyksen yhteydessä: dynCall1: jmp ?? dynCall2: jmp ?? ... dynCallN: jmp ?? ... call dynCall2 Ymmärtänemme tässä vaiheessa että tällainen välihyppy ei vaikuta millään tavoin itse aliohjelman suoritukseen, koska hyppykäsky ei muuta pinon tai rekisterien tilaa. - dynaamiset (jaetut) kirjastot: perusidea ja käyttöjärjestelmän rooli. * miksi dynaaminen linkitys hyvä? mm. modulaarisuus - voidaan päivittää kirjasto kerrallaan, jakaminen - voidaan ladata kerran ja liittää usean eri prosessin virtuaalimuistiavaruuteen (jolloin säästyy keskusmuistia) * "Unix-maailmassa" nimenä shared object (.so -tiedostot) * "Windows-maailmassa" nimenä dynamically linked library (.DLL -tiedostot) * Linkittäminen käynnistyksessä (järjestelmän vastuulla) tai tarvittaessa ajon aikana (ohjelmoijan tai suoritusalustan vastuulla; käyttöjärjestelmä tarjoaa palvelut kirjaston koodin liittämiseksi ohjelman virtuaalimuistiavaruuteen) + käynnistyksen yhteydessä näppärää; ohjelmoijan ei tarvitse huolehtia kirjastojen etsimisestä. + käännösvaiheessa ohjelmatiedostoon jää riittävät tiedot kirjaston löytämiseksi. + ajon aikana mahdollista mm. valita kirjastojen välillä; aina ei tarvita kaikkia kirjastoja tai niiden versioita. - Mainitaan tässä Windowsin API eli "käyttäjän portti käyttöjärjestelmän palveluihin" Windows-maailmassa. (Tähän astihan on nähty Unixin/Linuxin syscall interfacea). * Sovellus kutsuu Windows API:n DLL:stä löytyvää aliohjelmaa * DLL suorittaa varsinaisen käyttöjärjestelmäkutsun. [Tauko 15 minuuttia] [jonka aikana tehtyjä huomioita (toivottavasti motivoivia kurssin aiheisiin): - Komentorividebuggeri joskus ainoa tapa päästä käsiksi ongelmanratkaisuun (tehdas kiinassa, pääteyhteys käytettävissä); tämä oli erään läsnäolijan tuttavalle parin päivän sisällä tapahtunut tilanne. - Muistinpa myös pari viikkoa sitten jutelleeni kaverin kanssa, jonka firma on tällä hetkellä rekrytoimassa kahta nimenomaan Linux-asiantuntijaa. ] Vuoronnuksesta --------------- Tavoitteita vuoronnukselle (tai jopa yleisemmin jollekin järjestelmälle): - käyttöaste (utilization): kuinka paljon prosessori pystyy tekemään hyödyllistä laskentaa vs. odottelu tai hukkatyö - tasapuolisuus (fairness): kaikki saavat suoritusaikaa - tuottavuus (throughput): aikayksikössä loppuun saatujen tehtävien määrä - läpimenoaika (turnaround): suoritukseen kulunut aika - vasteaika (response time): odotus ennen toimenpiteen valmistumista - odotusaika (waiting time): kokonaisaika, jonka prosessi joutuu odottamaan Kaikki tavoitteet ovat ilmeisen perusteltuja, mutta ne ovat myös silminnähden ristiriitaisia: esim. yhden prosessin läpimenoaika saadaan optimaaliseksi vain huonontamalla muiden prosessien läpimenoaikoja (ne joutuvat odottamaan enemmän). Prosessista toiseen vaihtamiseen kuluu oma aikansa (täytyy huolehtia mm. tilannetiedon tallennuksesta ja palautuksesta jokaisen vaihdon yhteydessä). Siis käyttöaste heikentyy, jos pyritään vaihtelemaan kovin usein ja usean prosessin välillä. Käyttöjärjestelmän algoritmit ovat jonotuksiin ja resursseihin liittyviä valintatehtäviä. Vrt. pilvenpiirtäjän hissit, liikenteenohjaus tai lennonjohto. Operaatiotutkimus (operations research) on vakiintunut tieteenala, joka tutkii vastaavia ongelmia yleisemmin. Kannattaa huomata yhteys käyttöjärjestelmän ja muiden järjestelmien tavoitteiden sekä ratkaisumenetelmien välillä! Esimerkkinä joitakin käyttöjärjestelmän vuoronnusmenettelyjä: - FCFS (First come, first serve): prosessi valmiiksi ennen siirtymistä seuraavan suoritukseen; "eräajo"; historiallinen, nykyisin monesti turha koska keskeytykset ovat mahdollisia ja toisaalta moniajo monin paikoin perusvaatimus. - Kiertojono (round robin): tuttu aiemmasta esittelystä: prosessia suoritetaan aikaviipaleen loppuun ja siirrytään seuraavaan. Odottavista prosesseista muodostuu rengas tai "piiri", jota edetään aina seuraavaan. - Prioriteetit: esim. kiertojono jokaiselle prioriteetille, ja palvellaan korkeamman prioriteetin jonoa useammin tai pidempien viipaleiden verran. (vaarana alemman prioriteetin nääntyminen):: Prioriteetti 0 [READY0] -> NULL Prioriteetti 1 [READY1] -> PID 24 -> PID 7 -> PID 1234 -> PID 778 -> NULL Prioriteetti 2 [READY2] -> PID 324 -> PID 1123 -> NULL ... Prioriteetti 99 [READY99] -> NULL - Dynaamiset prioriteetit: kiertojono jokaiselle prioriteetille, mutta prioriteetteja vaihdellaan tilanteen mukaan: * prosessit aloittavat korkealla prioriteetilla I/O:n jälkeen (oletetaan "nopea" käsittely ja seuraava keskeytys; esim. tekstieditori, joka lähinnä odottelee näppäinpainalluksia) * siirretään alemmalle prioriteetille, jos aika-annos kuluu umpeen, ts. prosessi alkaakin tehdä paljon laskentaa * lopputulemana kompromissi: vasteajat hyviä ohjelmille, jotka eivät laske kovin paljon; hintana on se että runsaasti laskevien ohjelmien kokonaissuoritusaika hieman pitenee (pidennys riippuu tietysti järjestelmän kokonaiskuormasta eli paljonko prosesseja yhteensä on ja mitä ne kaikki tekevät; jos prosessori olisi muuten "tyhjäkäynnillä", saa matalinkin prioriteetti tietysti lähes 100% käyttöönsä). Prosessorin lisäksi muitakin resursseja täytyy vuorontaa. Esim. kovalevy (disk scheduling): - esim. kaksi prosessia haluaa lukea gigatavun eri puolilta levyä - gigatavun lukeminen kestää jo jonkin aikaa - lukeeko ensin toinen prosessi kaiken ja sitten vasta toinen pääsee lukemaan mitään ("FCFS"), vai vaihdellaanko prosessien välillä lukuvuoroa? - kun lukuvuoroa vaihdellaan, kuinka suurissa pätkissä (lohko vai useampia) ja millä prioriteeteilla... - kovalevyn vuoronnukseen (disk scheduling) liittyy fyysisen laitteen nopeusominaisuudet: esim. kokonaisuuden throughput pienenee, jos aikaa kuluu lukupään siirtoon levyn akselin ja ulkoreunan välillä; peräkkäin samalla uralla sijaitsevaa tietoa pitäisi siis suosia, mutta tämä voi laskea vasteaikaa muilta lukijoilta. Arvatenkin tarvitaan taas jonkinlainen kompromissi. Reaaliaikajärjestelmä (real time system) on sellainen järjestelmä, esimerkiksi tietokonelaitteisto ja käyttöjärjestelmä, jonka pitää pystyä toimimaan ympäristössä, jossa asiat tapahtuvat "reaaliajassa". Esimerkkejä "reaaliajasta": - robottiajoneuvo kulkee eteenpäin, ja sitä vastaan tulee este; esteen havaitseminen ja siihen reagoiminen ilmeisesti täytyy tapahtua riittävän ajoissa, koska muuten tapahtuu törmäys. - rumpukoneohjelman on tarkoitus tuottaa äänisignaalia millisekunnin mittaisissa aikaikkunoissa; äänikortti ilmoittaa tulostuspuskurin olevan pian tyhjä, jolloin rumpukoneohjelman on pystyttävä kirjoittamaan seuraava pätkä riittävän ajoissa, koska muuten äänikortin on pakko puskea tyhjä tai puolivalmis puskuri kaiuttimiin, joista kuuluu tällöin ikävä rasaus. - kuuraketin nopeussensori huomaa suunnan kallistuvan vasemmalle; ohjausjärjestelmälle on riittävän pian saatava ohjauskomento korjausliikkeestä, koska muuten kallistus saattaa kärjistyä katastrofaalisesti eikä matkustajille käy hyvin. Reaaliaikajärjestelmän yleisiä vaatimuksia: - determinismi (determinism); olennaiset toimenpiteet saadaan suoritukseen aina riittävän pian niitä tarvitsevan ilmiön (esim. prosessorin keskeytyksen) jälkeen - vaste (responsiveness); olennaiset toimenpiteet saadaan päätökseen riittävän pian käsittelyn aloituksesta - hallittavuus (user control); käyttäjä tietää, mitkä toimenpiteet ovat olennaisimpia - tarvitaan keinot kommunikoida nämä käyttöjärjestelmälle, mikäli kyseessä on yleiskäyttöinen käyttöjärjestelmä (ja dedikoitu järjestelmä olisi varmaan alun alkaenkin suunniteltu käyttäjiensä sovellustietämyksen perusteella) - luotettavuus (reliability); vikoja esiintyy riittävän harvoin/epätodennäköisesti - vikasietoinen toiminta (fail-soft operation); häiriön tai virheen ilmetessä toiminta jatkuu - ainakin jollain tavoin. Esim. vaikka robottiajoneuvon vaste oli kertaalleen liian pitkä ja se törmäsi esteeseen ja meni osittain rikki, niin ohjausta pitäisi edelleen jatkaa ettei vauhdissa tule lisää vaurioita. Edellä olevassa "riittävä" tarkoittaa reaaliaikailmiön luonteesta riippuen eri asioita. Joissain sovelluksissa esim. mikrosekunti on riittävän lyhyt aika, toisissa minuutti. Normaali interaktiivinen tietokoneen käyttö ei edellytä "reaaliaikaisuutta" siinä mielessä että determinismi- ja vastevaatimukset eivät ole lukkoon lyötyjä eivätkä kriittisiä esim. WWW-sivujen lataamisen ja katselun tai tekstinkäsittelyn kannalta. Kriittisemmäksi tilanne muuttuu, jos laitetta käytetään esim. multimediaan; esim. toimintapelien elämyksellisyys voi vaatia riittävän nopeata kuvan ja äänen päivitystä. Reaaliaikaiseen käyttöjärjestelmään liittyy termi pre-emptiivisyys (preemption/pre-emption) mikä tarkoittaa että prosessin toiminta voi keskeytyä kun suuremman prioriteetin prosessi tarvitsee palvelua. Pre-emptioksi voidaan sanoa jo sitäkin kun prosessi ylipäätään voi keskeytyä kesken laskennan (siis aika-annoksenkin loppumiseen); reaaliaikajärjestelmissä pre-emption rooli on kuitenkin merkityksellisempi - mm. keskeytyskäsittelyjä ja muita käyttöjärjestelmän toimenpiteitä (joita ei välttämättä tarvitsisi keskeyttää ei-reaaliaikajärjestelmässä) täytyisikin voida keskeyttää, jos tulee "se tärkeä keskeytys".