luentosuunnitelma_2016.txt 103.93 KiB
-*- coding:utf-8 ; mode:org -*-
Käyttöjärjestelmät, kevät 2016.
Tämä on suunnitelma, joka muuttuu ajankäytön ja muun
perusteella. Pohjana luentojen eteneminen viime vuonna, jolloin
kokonaisuus oli jo aika perushyvä.
* Luentojen toteuma 2016:
** Luento 1: Aloitus, yleisinfo ja suoritusvaatimukset
Luennon päätavoite oli kuvailla kurssin tekniset vaatimukset ja muu
perusinfo. Varsinaiseen asiaan ehditään hyvin keskiviikkona.
- Esittelyt: opettajat, opiskelijat, opiskelijoiden pääaineet (suurin
osa tietotekniikalta, noin puolet tästä määrästä
tietojenkäsittelytieteeltä, lisäksi fyysikalta, matematiikalta sekä
englannin ja suomen kielen opiskelijoita. Opiskelijoiden
pääasialliset käyttöjärjestelmät omassa käytössä: suurimmalla osalla
Windows, mutta Linuxeja ja Mac OS X:iä myös runsaasti
käytössä. Lisäksi salista löytyi ehkä Windowsia useammin myös
Android (Linux-ytimen päällä sekin) ja myös Sailfish (joka toimii
monen vaihtoehtoisen alustan päällä). Linkit kahden viimeksi
mainitun yleisarkkitehtuurikuviin:
https://source.android.com/security/
https://sailfishos.org/about/
Linuxia käydään kurssilla läpi eri kanteilta.
- Perinteinen ryhmäkuva, tällä kertaa ilman teknisiä tai muita
ongelmia. Okei, tämä koreografia oli harjoiteltu... Kaikki, mitä
"koreografiassa" nähtiin, liittyi yksityiskohtiin, joiden parissa
kurssilla pyöritään alusta loppuun, muiden asioiden muassa.
- Käydään läpi, mistä kaikki kurssiin liittyvä löytyy (kaikkiin löytyy
linkki kurssin nettisivulta):
* Luentomoniste
* Osaamistavoitteet
* Demot ja niiden palautusjärjestelmä (HUOM: toistaiseksi vielä
viime vuoden versiot - muutokset tulleevat olemaan hyvin pieniä;
päivitetään ministi jotain jossain vaiheessa, mikäli tarvetta
ilmenee). Seuraavalla luennolla tulee opastus ensimmäisiin
demoihin, joten sinne asti voi olla ihan hyvä vielä malttaa ja
käyttää aikaa vaikkapa esitietojen kertaamiseen, erityisesti
Ohjelmointi 1:n osalta.
Demojen miettiminen ryhmässä on aina suotavaa, mutta jokaisen
tulee palauttaa tiedosto omalla tunnuksellaan jo teknisistä
syistä. [Lisäksi jokainen vastatkoon omalta kohdaltaan siitä, että
aivan itselle kertyy käytännön osaamista, vaikka frendi jeesaa! On
se myös frendin vastuulla!]
* Aikataulut ja salit: Korpissa.
Ryhmäohjauksia mikroluokissa vain käyntiin pääsemiseksi; sen
jälkeen henkilökohtaisesti varattavia aikoja Tomilta; ohjeet
Korppi-varauksiin tulevat listalle. Pääsiäisen alusviikolla täysi
tauko opetuksesta; opiskelu ei ole kiellettyä ;). Luennoitsijanne
naputtaa kyseisen viikon väitöskirjaansa, eikä toivottavasti
paljon muuta teekään.
Luennot ovat iltapäivästä - tehdään yhteinen ratkaisu, pidetäänkö
niissä tauko vai jätetäänkö tauko pois ja lopetetaan aiemmin: Tänä
vuonna ei pidetä taukoa! Luennot päättyvät täten klo 17:45,
kulloisenkin luentosalin tietokoneen kellon mukaan.
* Materiaalin reaaliaikainen tilanne -> YouSourcessa. Päivitysten
julkaisu useimmiten 1-2 tunnin kuluttua luennon päättymisestä.
- Käytiin läpi määrälliset vaatimukset, jotka ovat jo näkyvillä myös
nettisivulla ja palautusjärjestelmässä: Pakolliset demot ja
tentti. Vapaaehtoiset demot ovat "porkkana" ja "täky" syvällisemmän
osaamisen hakemiseen; kevään kurssin aikana niistä saa
bonuspisteitä.
- Tomin ohjauksista: Henkilökohtaiset ajanvaraukset Korpin kautta
(tiedotetaan ja ohjeistetaan, kun on varattavissa). Varaus ajoissa
sen mukaan kuinka vaativiin "ongelmiin" tarvitsee apua. Kysymykset
hyvä olla mietittynä, että aika saadaan paikan päällä käytettyä
tehokkaasti. Kysyä saa paitsi demoista niin kurssin asioista
muutenkin.
- Tomin "palopuhe" demojen tekemisestä. Olennaisimmat kohdat taisivat
olla: Ohjeet on syytä lukea ja ymmärtää ennen palautuksen tekemistä.
(Vastausten ei tarvitse olla täydellisiä - tarkistus on harkinnan
mukaan, voidaanko vastauksen perusteella ns. "epäillä" ettei ole
ymmärretty asiaa. On suorastaan epäkohteliasta palauttaa
lähdekoodia, joka ei käänny syntaksivirheen takia! Palautettavan
tiedoston muoto on tärkeä, joten ohjeet on tosiaankin luettava.
** Luento 2: Luentomuoto, taustamateriaali, demo-ohjeistus, varoitukset(!)
Tästä luennosta alkaen mennään kaikki asiat juurta jaksaen käytännön
esimerkkejä näyttäen ja auki selittäen. Tavoite on, että viimeistään
demojen 1 ja 2 jälkeen opiskelijat uskaltautuvat myös itse kokeilemaan
samoja juttuja omatoimisesti. Turvallisuus- ja mukavuussyistä tämän
luennon varoitukset on syytä ensin sisäistää.
Mini-info:
- Ensimmäinen mahdollisuus aloittaa demoja mikroluokassa ohjaajan
avustamana on heti huomenna (to 17.3.2016) mikroluokassa Lakes
(AgB213.1) klo 8:30-12:00 välisenä aikana. Konsepti on:
* sali on meille varattuna aamupäivän
* mie päivystän siellä, josko paikalle tulee opiskelijoitakin.
* avustan henkisesti ja teknisesti, mikäli tarvetta
ilmenee. Tehtävien luonteen vuoksi niitä tehdään joka
tapauksessa itsenäisesti lukien ja kokeillen myös paikan
päällä.
* Tomikin tulee, jos Tomi ehtii.
* ei tarvitse ilmoittautua.. tule sopivassa välissä paikalle, jos
tuntuu, että alussa tarvitsee tukea. Kokemuksen perusteella
oletukseni on, että mikroluokka ei täyttyisi ääriään myöten
missään vaiheessa - saa nähdä miten tänä vuonna käy..
* lisää mikroluokkapäivystystä luvassa niin kauan kuin näyttää,
että "massaohjaukset" ovat tarpeen. Varattu tässä vaiheessa sali
Africa (AgB112.1) pe 18.3.2016 klo 8:30-10:00 ja
14:15-15:45. Mikroluokkatouhu jatkuu pääsiäistauon jälkeen,
mikäli tarpeen.
* tarkoitus on, että myöhemmin olisi vain henkilökohtaiset
varaukset Tomin ohjaukseen Agoran 4. kerroksen avotilassa
(max. 3 henkeä yhdenaikaisesti). Näistä ilmoitetaan, kun Tomilla
on aikoja saatavilla.
- Etenkin etäopiskelijoille, mutta myös muille, meillä on käytössä
kaksi vertaistukikanavaa: yksi virallinen ja yksi epävirallinen:
* Sähköpostilista itka203_kevat2016_keskustelu@korppi.jyu.fi on
virallinen. Viestit arkistoituvat listan jäsenille, mutta eivät
julkisesti.
Tarkoitus: kysykää apua kaverilta -> kaverit vastaa -> seuraavat
kaverit oikaisevat, jos edellinen vastaus ei ollut aivan nappiin
-> opettajat saattavat kommentoida ehtimisensä mukaan.
Lista on erillinen, jotta informaatioähkyä välttävä opiskelija
voi halutessaan poistua omatoimisesti listalta. Viralliset
tiedotteet tulevat sen toisen listamme kautta, joka myös
arkistoituu julkisesti.
* IRC-kanava ircnetissä, jonka nimi on tässä "kryptattuna"
seuraavan muotoinen: risuaitamerkki + kurssikoodi pienillä
kirjaimilla. Sinne ei haluta ulkopuolisia, ja siksi
kryptaus. Luennolla näytetään esimerkki. HUOM: IRC-palvelu EI
ole Jyväskylän yliopiston tukema palvelu, eikä se ole kurssin
tiedotuskanavana virallinen.
Tarkoitus: jutelkaa pizzan tilauksen lisäksi tarvittaessa
kurssinkin asioista -> yleensä ollut porukkaa hengaamassa, joten
usein reaaliaikainen vastaus ongelmakohtiin -> nieminen idlaa
kanavalla ja logaa keskustelua + vastaa ehkä ennen toukokuuta,
jos on vastatakseen.
Yksi täkäläinen IRC-ohje: http://linkkijkl.fi/ohjeita/irc-ohje/
Sitten itse asiaan:
- Luentomuoto ja kurssin työkalut alusta alkaen ja esimerkit näyttäen:
pääteyhteys, bash-shell ja tekstipohjaiset
työkaluohjelmat. Oppikirja, kurssimoniste ja internetin ihmeellinen
maailma. Käytännön esimerkit.
- Ensimmäinen vilkaisu "jyrkempään" taustamateriaaliin:
AMD64-manuaalit, POSIX. Mitä ihmettä ja miksi?
- Miten lähdetään tekemään demoa 1: Alkuvaroitukset ja toisaalta
rohkaisu.
- HUOM: Windows-pääteyhteysohjelman (esim. KiTTY) todennäköinen
ääkkösongelma ja sen korjaaminen: Omissa asetuksissa todettava
etäkoneen merkistö; meidän tapauksessa UTF-8
- Miten homma jatkuu demossa 2: Screen-ohjelman käyttely. Demossa
tulee paljon muutakin. Mennään siihen luennoilla pääsiäistauon
jälkeen.
- Esitietojen varmistaminen: Mitä ohjelmointi 1 -kurssilta pitäisi
muistaa ( ks. https://trac.cc.jyu.fi/projects/ohj1/wiki/sisallys )
** Luento 3: Yleiskuvaa, tavoitteita, esitietoja ja motivoiva räjähdys.
- Yleisiä kommentteja demoista 1 ja 2 (näköjään yhtä luentoa aiemmin
kuin viime vuonna, mutta samat asiat varmaan on syytä käydä läpi
ilman yllätyksiä:))
+ (muistakaa ekan demon varoitukset; pitää tietää mitä tapahtuu,
ennen kuin laittaa sen tapahtumaan;)
+ jos pelottaa, voi tehdä kokeiluja palvelimella
itka203-testi.it.jyu.fi missä ei voi häiritä jalavalaisia /
halavalaisia. [demotaan lyhyesti luennolla]
+ välttäkää tarpeetonta monimutkaisuutta - esimerkiksi komento
"echo `ps -u nieminen`" antaa echo-ohjelman tulosteen eikä
tehtävänannossa pyydettyä ps-ohjelman tulostetta!! Voi olla,
että "mystinen" ilmiö rivinvaihtojen puuttumisen suhteen saattaa
selittyä tällä asialla, joka onkin vain väärä käsitys -
korjataan käsitystä ja koettakaa palauttaa demoa 1 uudelleen,
jos se on hylätty rivinvaihtoilmiöiden vuoksi. Koetetaan
konkretisoida luennolla.
- Demon 2 sisällöstä: Moniajo, ps ja top -ohjelmat. Lisää viimeistään
demossa 2 vastaan tulevia termejä: Prosessi,
prosessi-ID. lapsiprosessi, vanhempiprosessi, prosessipuu.
- Lukekaahan Tomin kommentit demoista ym. sähköpostilistalta. Löytyy
myös Korpin sähköpostiarkistosta, jos olet ilmoittautunut kurssille
esim. vasta eilen...
Mennään luentomonisteen puolelle:
- Sisällysluettelon pääotsikot suhteessa kansainvälisiin
osaamistavoitteisiin. Samoja ovat.. jatkokurssien opettajat
aika-ajoin kyselevät, mitä tällä kurssilla käsitellään. Päädyn
lupaamaan noin yhden luennon mittaisen ensijohdannon aika monesta
tärkeästä asiasta, joissa myöhemmin mennään syvemmälle.
- Johdanto: Kerrokset ja rajapinnat. Käyttöjärjestelmän rooli
informaatioteknologian kokonaiskuvassa. Käyttöjärjestelmäkurssin
rooli IT-alan oppisisällössä ja suhde muihin osaamiskohteisiin.
- Esi- tai ennakkotiedot: Palautellaan mieleen Ohjelmointi 1 -kurssia:
alkeistietotyypit, määrämuotoiset tietorakenteet ja
taulukot. Ilmeneminen C:n lähdekoodissa (ei kovin erilaista kuin
esim. C#:ssa tai Javassa, joiden syntaksi tarkoituksella jäljittelee
C:tä).
- Pintapuolisia esi- tai ennakkotietoja kurssien Algoritmit
1&2. -puolelta. Arkihavaintoja abstrakteista tietorakenteista:
tietue/olio, taulukko, lista, jono, pino, puu.
- Lukujärjestelmistä - tavallaan "esitieto", joka tavallaan käydään
läpi Ohjelmointi 1:n sisällössä, mutta melko varmasti tarvitsee
kertausta. Laitteiston lähellä toimittaessa välttämätön
ymmärtää. Erityisesti binääri-, heksa- ja oktaaliluvut.
- Päätettiin luento videoon, joka löytyi ensimmäisenä Google-haulla
"Ariane 5 test launch". Kurssin asiat eivät ole rakettitiedettä,
kuten luennolla pari kertaa mainitsin, mutta rakettienkin kanssa
toimittaessa ne täytyy ymmärtää, mm. lukujärjestelmät ja
tallennustilan rajallisuus laitteistossa. Videolla paukahtaa
puolisen miljoonaa euroa nätisti, koska 16 bitin mittaiseen
tallennustilaan yritettiin laittaa luku, joka olisi tarvinnut
vähintään 17.
Näihin kuviin, näihin tunnelmiin. Kerratkaa tai opetelkaa ensimmäistä
kertaa binääriluvut, heksaluvut ja oktaaliluvut!! Ensi viikolla
katsotaan heksoja!
** Luento 4: Tietokonelaitteisto
Tällä viikolla (luennot 4-5) vaelletaan viime viikolla selatun
kerroskuvan matalimmilla tasoilla, lähellä tietokonetta ja prosessorin
rajapintaa.
Aluksi:
- Tomi mainostaa alussa Linkin järjestämää tekstieditorijumppaa.
- Tomi kertoo havainnon tai pari demoista tähän asti.
Välttämätön päällekkäisyys kurssin Tietokoneen rakenne ja
arkkitehtuuri kanssa (joka ei välttämättä mahdu samaan
sivuainepakettiin tämän kurssin kanssa):
- Tietokoneen perusrakenne (CPU, muisti, IO-laitteet, väylä)
- CPU:n välttämättömät osat (kontrolliyksikkö, ALU, rekisterit,
sisäiset väylät); vähintään käskyosoiterekisteri (IP), jokin
rekisteri laskutoimituksille sekä loogisia ehtoja kuvaavia
lippubittejä.
- Nykypäivä: symmetrinen moniprosessorijärjestelmä / multicore
[klusterit? pilvipalvelut? virtualisointi? - pääasiassa
jatkokurssien aiheita; samoin rinnakkaislaskenta GPU:lla eli
grafiikkaprosessorilla. Mainittakoon nämä kuitenkin ohimennen.]
- muistihierarkia (rekisterit, välimuistit L1, L2,.. , keskusmuisti)
lokaalisuusperiaate mainittu jo myös.
POSIX-vartti:
- Mikä on POSIX? Kuka sen on tehnyt? Mitä se sanoo esimerkiksi tällä
luennolla tai aiemmin nähdyistä asioista?
+ Tsekataan alun yleiskuvaukset ja rajaukset - POSIX ei ota kantaa
laitteistorajapintaan eikä käyttöjärjestelmän sisäiseen
rakenteeseen; kyseessä siis nimenomaan rajapintadokumentaatio. C,
minimalistiset kirjastot, shell ja tietty minimijoukko
apuohjelmia. Vain tekstiä; ei mitään grafiikkaan liittyvää.
+ Base definitions Intro: (mm. XBD Sec. 1.7 "Portability"),
Modulaarinen rakenne, laajennukset ja marginaalihuomioiden
formaatti.
** Luento 5: Tiedosto, lähdekoodi, kääntäminen, konekieli, debugger
Pyöritään luennoilla sen jälkeen hetken verran laitteistorajapinnassa
niin konkreettisesti kuin pystytään. Lähdetään sitten hiukan nousemaan
sieltä kohti ohjelmistorajapintoja asteittain.
- Demo 3:n esittely; tehdään samoja asioita, joita siinä demossa on
tarkoitus omin käsin toistaa ja toivottavasti myös miettiä läpi..
ympäristömuuttujat, argumentit, kieliasetukset, C-ohjelman
kääntäminen.
- Konekielisen ohjelman suoritus. "Hei maailma" taas kerran, tällä
kertaa C-kielellä. Toteutus:
+ tehdään shellissä hakemisto tämän vuoden esimerkkikoodeille
+ vaihdetaan hakemistoon
+ editoidaan yhdessä screen-ikkunassa ja kokeillaan toimintaa
toisessa
+ raapustellaan koodi sisään alusta lähtien
+ kokeillaan kääntämistä ja ajamista
- Lähdekooditiedoston sisällön katselua hexdumpilla (ja ehkä myös
POSIXin määräämällä oktaalivedostajalla "od"). Normaali
tekstitiedostohan se vain on..
- Katsotaan tiedoston metatietoja (jotka on tallessa eri paikassa kuin
tiedoston sisältö - komennot "ls -l" sekä "stat"); myös tiedoston
nimi ja osoite hakemistopuussa on erillinen sen sisällöstä, eikä
nimellä ja sisällöllä ole teknisesti tekemistä keskenään.
- Tutkitaan mm. rivinvaihtojen ja skandinaavisten kirjaimien
kuvaamista tekstitiedostossa. Mainittakoon UTF-8 -merkistökoodaus
(yksi Unicoden koodaus). Ehkä myös ASCII sekä POSIXin minimaalisin
merkistökoodaus.
- Jotta ohjelma voidaan ajaa, se pitää kääntää C-käntäjällä. Katsotaan
käännetyn, suoritettavan ohjelmakooditiedoston (ELF-formaatti)
sisältöä hexdumpilla ja etsitään sieltä kohta, jossa "Hello world"
löytyy selväkielisenä.
- gdb -debuggeriohjelma: bitti bitiltä, tavu tavulta, helloworldin
pääohjelmassa suoritettavat konekieliset käskyt ja vasemmassa
laidassa muistiosoitteet, joissa ne ovat tallennettuna silloin, kun
ohjelma on käynnissä. (Huom: tässä kohtaa puhutaan vahvasti
laiterajapinnasta, johon POSIX _ei_ ota kantaa; niinpä työkalut ovat
sidoksissa GNU-tuotoksiin, tiedostoformaatit Linuxiin, ja konekieli
AMD64 prosessoriarkkitehtuuriin, jotka meillä yliopiston
palvelimelta löytyvät)
- (Kenties.. ja toki kyllä..) palautettiin ohjelmistoon perinteinen
luennoitsijan elvistelysetti.. eikäs kun yksi esimerkki kurssin
opeista, joka saattaa joitakuita motivoida. Mainitaan muitakin
käyttökohteita reaalimaailmassa.
** Luento 6: Ohjelman argumentit ja virhekoodi, ympäristö, debuggeri, konekieli
Info: Seuraava luento sattuu erityispäivän päätteeksi...
- Tutkimuksen avoimet ovet on kaikille suositeltava tapahtuma:
https://www.jyu.fi/it/uutiset/tiedekunta/avoimetovet
- Pyritään aloittamaan luento 16:15 - 16:30, mutta varmistetaan, että
käydään ensin nauttimassa tapahtuman tarjoiluista. Ilmoittautukaahan
mukaan; huomennakin ehtii vielä ilmoittautua.
Asiaan...
Ohjelman toimintaympäristö: argumentit, ympäristömuuttujat (demo 3:n
asiaa).
- Lavennetaan "hei maailmaa" käyttämään argumenttejaan.
- POSIX-vartti? Mitä POSIX sanoo seuraavista: shellin syntaksi,
komennon/sovelluksen virhekoodi, ympäristömuuttuja, argumentti
(littyvät demoihin 1-3).
Jatketaan "Hei maailma" -ohjelmasta. Kokeillaan huvin vuoksi ja
löytämisen ilon kannalta.
Konekielisen ohjelman suoritus. "Hei maailma" jatkuu. Uusia
esimerkkejä debuggerilla:
- Askeltaminen lähdekoodirivi kerrallaan, "step"
+ mitä tapahtuu, kun askelletaan ohjelman "lopun" ohi eli
main()-aliohjelman returnin ja viimeisen aaltosulun jälkeen?
(havaittiin, että päädytään C:n standardikirjaston puolelle,
josta järjestelmäämme ei nyt ole asennettu lähdekoodia tai
debuggaustietoa, joten debuggeri havaitsee että se ei voi nyt
paljoa enempää näyttää ja antaa standardikirjaston hoitaa
ohjelman lopputoimet.)
+ katsottiin AMD64-manuaalia:
* Idea konekielisten tavujen muodostumisesta [Huom: luennolla
äkkiseltään tehty "arvaus" oli epätarkka, kuten oletinkin,
ts. tarvittaessa tutki asiaa itse suoraan manuaalista]
* Esimerkki käskyn esittelystä, "MOV"
- Askeltaminen konekäsky kerrallaan, "stepi" (step instruction).
Havaintoja:
+ Tulostusrivin kohdalla alustakirjasto tekee paljon vaikka
mitä.
+ Debuggerissa voi pyytää tällaisen toisten tekemän
ei-kiinnostavan aliohjelman suorittamista sen loppuun saakka
komennolla "finish".
- Askelletaan heimaailman assembler-versio käsky kerrallaan ja
tarkkaillaan muutoksia rekistereissä kunkin käskyn jälkeen:
+ GDB:n käsky "stepi" askeltaa konekielinen käsky kerrallaan,
"disassemble" näyttää koodin ja kohdan, missä ollaan menossa.
+ prosessin konteksti eli prosessorin rekisterien sisällöt: gdb:n
käsky "info registers" näyttää kaikki sovellusohjelman käytössä
olevat yleis- ja toiminnanohjausrekisterit.
Onko prosessorissa näiden lisäksi muita rekistereitä? Kyllä on,
joitain kymmeniä kappaleita. Manuaali kertoo näistä totuuden ja
luentomoniste kiteyttää suomeksi oleellisimmat pääkohdat.
+ Katsotaan luentomonisteen listaa x86-64 -prosessorin
yleisrekistereistä.
[Videon lopussa ylimääräisiä kysymyksiä assemblerista, jos sattuu
kiinnostamaan... virallinen osio päättyi puolentoista tunnin
kohdalla.]
** Luento 7: Prosessi, virtuaalimuistiavaruus, osoitteen tulkinta, MMU
Tänään lyhyempi luento, johtuen Tutkimuksen avoimet ovet -tapahtumasta.
- Luennon alussa oli erikoispäivän kunniaksi pieni esimerkki shellin
käyttämisestä tiedonlouhintaan liittyvässä tutkimuksessa:
+ Alustava kokonaiskuva ennen näkemättömästä datasetistä: minkä
muotoinen tiedosto, kuinka paljon, miten jakautunutta (karkeasti
ottaen)
+ Erotinmerkin muuttaminen (tässä pilkku -> välilyönti), mikäli
halutaan ladata käsittelyyn ohjelmalla, jolle alkuperäinen
erotinmerkki ei käy. Vastaavasti voisi muuttaa myös
esim. desimaalierottimen.
+ Shellin perustyökaluilla pystyy tekemään paljon muutakin
hyödyllistä ensivaiheessa, ennen siirtymistä varsinaisen
tutkimusohjelmiston käyttöön.
+ Todellisessa tilanteessa data voi tulla asiakkaalta hyvinkin
kummallisessa muodossa, jota ei suoriltaan pysty lataamaan
työkaluihin, eikä asiakkaan edustaja välttämättä itse edes
tiedä, mikä tiedostomuoto on. Ensimmäinen vaihe voi siis
hyvinkin olla "reverse engineering" -tyylistä.
- C:llä, assemblerilla ja debuggerilla vielä hetki:
+ Vastauksia yleisökysymyksiin:
* Miksi debuggeri näyttää rivien alussa muistiosoitteet
disassembly-tulosteessa? Vastauksessa käytiin läpi tätä sekä
muita disassemblyn ominaisuuksia.
* Ovatko "disassembly /r":n näyttämät konekieliset tavut
mukana "executablessa" eli suoritettavassa ELF-muotoisessa
ohjelmatiedostossa? Kyllä ovat.
* Edellinen kysymys johti luontevasti esimerkkiin debuggerin
komennosta "x" (eli "eXamine"), jolla voi tutkia ladatun
ohjelman muistia nimenomaan halutun muistiosoitteen
kohdalta. Esimerkki: Varmistettiin, että osoitteeseen
0x400000 on ladattu ohjelmatiedoston alku eli jo aiemmalla
luennolla nähty pötkö, joka alkaa ELFiä käyttävissä
järjestelmissä aina samoilla neljällä tavulla 0x7f, 'E',
'L', 'F'.
+ Relevantti kysymys (ja vastaus!) prosessien virtuaalimuistista.
* Jokaiselle prosessille luodaan oma virtuaalinen
muistiavaruus, eli osoitteisto 0..MAKSIMI, jotka prosessorin
muistinhallintayksikkö (MMU) kartoittaa automaattisesti
fyysisiksi osoitteiksi. Yksi käyttöjärjestelmän tehtävä on
tiedottaa prosessorille kunkin prosessin muistikartta eli
osoitteiden muuntaminen virtuaalisista fyysisiksi. Tähän
palataan kokonaisen luennon verran myöhemmin.
* Ohjelman tyypilliset alueet (koodi, data, keko, pino)
sijoitetaan yleensä tiettyihin alueisiin prosessin
virtuaalimuistia.
+ Kysymys aiheesta "Second level address translation (SLAT)", joka
liittyy virtualisointiin. Käytettiin pari minuuttia keskusteluun
etäkäyttökoneidemme (mm. jalava, halava, itka203-testi, ...)
todellisesta luonteesta: Ovat isossa räkkilaitteessa toimivia
virtuaalikoneita, joita voi luoda muutamalla klikkauksella
tarvittaessa lisää.
- Sitten täsmennetään tekninen ymmärrys käyttöjärjestelmän
kutsurajapinnasta (System call interface):
+ Käyttöjärjestelmäkutsu exit() matalan tason C-apukirjastosta.
+ Suora Linuxin käyttöjärjestelmäkutsu, myös tuttavalliselta
nimeltään "exit()". Ensimmäinen toteutus C:n epästandardina
inline-assemblynä. Ei jatketa tällä tiellä yhtään
pidemmälle... Toimii samalla tavoin vain yhdellä kääntäjällä
(meillä GNU C), yhdellä käyttöjärjestelmällä (meillä Linux) ja
yhdellä prosessoriarkkitehtuurilla (meillä x86-64).
+ Puhdas Assembler-ohjelma. Motivoidaan kerroksittaisten
abstraktioiden käyttöä.
- Käyttöjärjestelmäkutsun toimintaperiaate (esimerkki helloasm.s):
+ AMD64:n konekielikäsky 'syscall' keskeyttää prosessin oman
suorituksen ja "siirtää kontrollin" käyttöjärjestelmän koodin
puolelle. Käyttöjärjestelmä tekee sitten, mitä haluaa -
toivottavasti sen, mitä sen rajapintadokumentaatiossa
ilmoitetaan. Käyttäjän prosessi jatkuu sen jälkeen, kun
käyttöjärjestelmä on toteuttanut pyydetyn palvelun. Tietysti jos
palveluna pyydetään prosessin itsensä päättymistä eli kutsu on
exit(), niin paluuta suoritukseen ei koskaan enää pitäisi olla.
+ Luennoitsija osasi tehdä Helloworldin tarvitsemat
käyttöjärjestelmäkutsut write() ja exit() katsomalla tästä
varsin helppokäyttöisestä, Googlen kautta helposti löytyneestä,
kokoelmasta, mitä missäkin rekisterissä pitää olla siinä
vaiheessa, kun syscall-käsky tehdään nykyisessä Linuxissa:
https://filippo.io/linux-syscall-table/
+ Käyttöjärjestelmäkutsu on erittäin primitiivinen toimenpide, ja
puhtaassa apukirjastoja käyttämättömässä
assembler-ohjelmoinnissa välttämätön. Nyt kun sen toiminta on
kertaalleen nähty, hyväksytään se, että päällä on esimerkiksi
C-kielellä tehtyjä matalan tason apukirjastoja sekä lisäksi
esimerkiksi POSIX-yhteensopivuuskirjasto, jos jokin
käyttöjärjestelmä pyrkii olemaan kyseisen standardin mukainen.
- Yleisökysymys: Jos Linuxissa tiedosto numero 1 ohjautuu
standarditulosteeksi, niin ohjautuuko tiedosto numero 2
standardivirhetulosteeksi? Kylläpä vain. Yleensä tietenkin on
syytä käyttää C-standardin nimiä "stdout" ja "stderr", eikä
minkään tietyn järjestelmän määrittämää kokonaislukunumerointia.
** Luento 8: Konekieli ja käyttöjärjestelmäkutsu, käyttäjätila, käyttöjärjestelmätila
Luennon lopuksi demo 4:n ensiesittely tosi lyhyesti. Seuraavalla
luennolla sitten tarkemmin.
Edellinen loppuun:
- Tavujärjestys (byte order), jos jotakuta on ihmetyttänyt (AMD64:ssä
little-endian)
- ohjelman jäljitys strace -apuohjelmalla, joka näyttää kaikki tehdyt
järjestelmäkutsut. Ero C-kirjastojen kanssa käännetyn koodin ja
puhtaan assembly-käännöksen välillä. Vastaavia jäljitystyökaluja
lienee olemassa muissakin käyttöjärjestelmissä kuin esimerkissämme
Linuxissa.
- Merkkijonon ilmeneminen laiteläheisessä ohjelmoinnissa ja siten
esim. C-kielessä: muistiosoite nollaan päättyvän tavujonon alkuun.
+ varmistutaan asiasta debuggerilla - komento "x/s"
+ Jos 2016 ei yleisöstä tule tätä kysymystä, vastataan siihen
silti: Miten debuggeri tietää merkkijonon pituuden? Sama kysymys
olisi, että miten tietokone tietää merkkijonon pituuden? Vastaus
on: eivät ne tiedä sitä. Ei ne tiedä mitään, vaan niillä on
käytössään peräkkäisiä muistiosoitteita ja jokaisen osoitteen
kautta pääsee käsiksi kerrallaan yhteen, kahteen, neljään tai
kahdeksaan tavuun (riippuen katsotaanko 8-, 16-, 32- vai
64-bittistä lukua käsittelevää konekielistä käskyä; jotkut
käskyt käsittelevät vielä näitäkin pidempiä tavujonoja)
+ Katsotaan vielä hiukan AMD64-prosessorimanuaalia. Pääosiot ovat
"1: Sovellusohjelmoijan käsikirja", "2: Järjestelmäohjelmoijan
käsikirja" sekä "3: Käskyreferenssi". Viikko sitten
silmäiltiinkin jo hiukan käskyn MOV referenssiä.. Katsotaan
vielä joku toinen yleinen, vaikkapa SUB ja CMP.
+ Katsotaan vielä käyttöjärjestelmäkutsun eli SYSCALL-käskyn
selitys pseudokoodeineen. Ristiviittaukset johtavat myös Osan 2
(System Programming) puolelle, ja sieltä takaisin
SWAPGS-käskyyn.
Linuxin uusimman version toteutus käyttöjärjestelmäkutsun
"vastaanottopuoleksi", arvatenkin GNU Assemblerilla
toteutettuna:
http://lxr.free-electrons.com/source/arch/x86/entry/entry_64.S#L103
Eli tasan tarkkaan se, mitä prosessorin käsketään tehdä
välittömästi sen jälkeen, kun käyttäjän prosessin SYSCALL on
takana päin nyky-Linuxissa. Tämä osio vaatii mm. tiettyjen
rekisterien tilan tallentamista, joten se on pakko toteuttaa
konekielellä. Järkevää tämä on tietysti vain symbolisena,
ihmisen ymmärtämänä, assemblerina, jonka syntaksi mukailee
prosessorin dokumentoitua käskykanta-arkkitehtuuria.
+ Aliohjelman ja silmukoiden suorittamiseen konekielessä palataan
demossa 5, kun ensin on katseltu välissä lisää C-kieltä.
Yhteenveto tietokoneen perustoimintaperiaatteesta: prosessori
suorittaa yksinkertaisen käskyn, joka muuttaa kontekstia
(ts. rekisterien sisältöä) -- vähintäänkin käskyosoiterekisterin
sisältönä tulee olemaan aina seuraavaksi suoritettavan käskyn osoite.
Johtopäätös: konekieli, assembly ja käyttöjärjestelmäkutsu ovat
tavattoman yksinkertaisia ja "putkiaivoisia" rajapintoja. Niiden
käyttäminen ja alustasta riippumattomien ohjelmien tekeminen
edellyttää korkean tason kieliä sekä kerroksittaista apukirjastoa,
jonka välttämättömät ominaisuudet esim. POSIX määrittelee tietyllä
abstraktiotasolla. Ts. "yksinkertainen != helppo".
Pidetään konkretia mielessä, mutta käytetään jatkossa pääasiassa
POSIXin määräämiä palvelukutsuja. Osa niistä on yksi-yhteen Linuxin
kutsurajapinnan kanssa, koska molemmat pohjautuvat samaan
historialliseen pohjaan (ikiaikainen unix). Osa voi kuitenkin tarvita
lisäoperaatioita yhteensopivuuskirjaston koodissa. Täydellinen totuus
on Linuxin ja GNU C-kirjastojen nykyversioiden lähdekoodissa; me
luotamme POSIXissa sovittuun sovellusrajapintaan, ja katsotaan sitten,
tuleeko mahdollisesti ongelmia suorakäyttökoneidemme "jotakuinkin"
POSIX-yhteensopivan Linux-jakelun kanssa.
Yleisökysymysten pohjalta pari "teaseria" tulevan viikon asioista:
- Kysymys keskeytyksistä: suora vastaus... tällä tai ensi viikolla
päästään käsittelemään ulkoisia keskeytyksiä, jotka valaisee asian
taustoja. Todelliseen toteutukseen tarttuminen tulee vaatimaan
spesifikaatioiden lukemista, jonka osaaminen on yleinen tavoite
koulutuksessamme kandi- ja maisteritasoilla.
- Kysymys moniydinprosessorin käyttöasteen hyödyntämisestä. -> Saattaa
liittyä säikeistykseen. Kysyjän ongelma näyttäytyy siten, että
tietty Javalla toteutettu sovellus tuntuu käyttävän hyvin vähän
prosessoriaikaa, vaikka sitä pitäisi kuusiytimisessä prosessorissa
olla käytettävissä enemmän. Eri asia on, että osaako käytetty
sovellus ns. säikeistää oman toimintansa kunnolla, ja osaako
käytetty Java-virtuaalikoneisto hoitaa säikeet tehokkaasti eri
ytimille. Säikeistä tullaan puhumaan jatkossa noin luennon verran,
mistä (jälleen) saa peruskäsityksen ongelmaan liittyvästä
koneistosta, mutta varsinainen ratkaisu todennäköisesti vaatii
enemmän selvittelyä alustan toteutuksessa mahdollisesti olevista
pullonkauloista.
Ohjelman lataamiseen liittyvät tiedostomuotoasiat:
- ELF-tiedoston formaatti (katsotaan speksiä päällisin puolin
PDF:istä - 32bit ja 64bit);
- Havainto: Myös ELF-spekseissä on C-kielellä määriteltyjä "typedef
struct{...sisältö...} TyypinNimi" -rakenteita. Käyttöjärjestelmän
konkreettisen toiminnan ymmärtäminen edellyttää jonkinlaista kuvaa
C-ohjelmoinnista, ei kiertotietä!
- verifioidaan vaikka helloasm-ohjelmasta, että ELF-dokumentissa
kuvaillut tiedot ovat oikeilla paikoillaan suoritettavassa
objektitiedostossa ja toisaalta myös debuggerin mukaan käynnistetyn
ohjelman muistissa. Ajan säästämiseksi jätettiin "uskon asiaksi" ja
oman kokeilemisen varaan. Kyllä ELF-tiedosto sisältää vilkaistun
speksin mukaiset asiat, jotta on toiveita, että se oikeasti
toimiikin.
- selväkielisempi listaus ELFin sisällöstä: objdump -x a.out tmv.
Havaitaan mm. selväkielisten symbolien taulukko. Ohjelman vaatima
sijaintipaikka muistissa osoitteessa 0x400000, aloituskohdan paikka
jne. Miksi 0x400000 eikä 0? Muistelisin lukeneeni, että tällä
sopimuksella yritetään välttää pahimpia virheitä "Null pointer
reference" -ilmiössä eli vahingossa nollaan tai lähelle osoittavien
muistiosoitteiden halutaan mieluummin kaatavan ohjelman kuin tekevän
odottamattomia asioita. Kartoittamattomalle alueelle osoitteen
0x400000 alapuolelle osuva muistiviittaus aiheuttaa välittömästi
prosessorin suojausvirheen. (Uskalias yksilö voi toki sopimuksen
vastaisesti ladatuttaa ohjelmansa pienempään tai isompaan
osoitteeseen - se on vain yksi kokonaisluku
ELF-tiedostossa... Luennoitsijan harraste-ekskursiot pienten
"demoscene"-ohjelmien maailmassa sisältävät mm. latausosoitteen
vaihtamiseen sopivasti.)
Demo 4:n alustava esittely: Kyseessä on "minimaalinen suomenkielinen
tutoriaali C-kieleen, olettaen että lukija tuntee jonkin oliopohjaisen
C:hen perustuvan kielen, esim. C# tai Java.
Saa alkaa tekemään demoa 4. Siihen tullee menemään eniten aikaa
kaikista demoista (jos se tehdään ajatuksella, kuten tarkoitus
olisi!). Palautettava osio on jälleen paljon pienempi kuin arvosanaan
1 tähtäävä minimiymmärrys, saatikka arvosanaan 5 tähtäävä
kokonaisymmärrys. HUOM: Historia on osoittanut, että Ohjelmointi 1 ja
jopa Ohjelmointi 2 on ollut mahdollista kahlata läpi ilman kykyä
ratkaista tässä demossa vaadittua pientä algoritmista "pähkinää". Ei
kannata hätääntyä, jos ei meinaa onnistua... vaan mitä kannattaa
tehdä? Kysyä apuja!
Ja muistakaa Tomin huomio aiemmalta luennolta: kyllä se on sangen
epäkohteliasta palauttaa koodi, joka ei edes käänny syntaksivirheiden
vuoksi. Eli nyt, kiitos, kunnioittakaa demon tarkastajaa sen verran,
että palautatte version, joka kääntyy (ja parhaimmillaan tietysti myös
tekee sen, mitä pyydetään).
** Luento 9: C-kieli, linkitys, aktivaatiopino.
(DONE: Yleisön pyynnöstä demotehtävien tekstiosuudet on nyt julkaistu
JYU:n verkon ulkopuolelle tuolla, niin tarvii harvemmin säätää VPN:n
kanssa: http://users.jyu.fi/~nieminen/kj16/demovedokset/ )
Demon 4:n asioiden tarkempaa esittelyä suoraan demoesimerkkinä olevan
koodipaketin pohjalta:
- C-kieli, esikääntäjä ja makrot
- objektitiedosto, kirjasto, kääntäminen, lataaminen ja linkittäminen
(staattinen & dynaaminen, ts. omat ohjelmamoduulit & libm.so
-matematiikkakirjasto ja muut, tuhannet, libjotakin.so:t)
- useita C-koodisia ohjelmamoduuleita, jotka käännetään erillisiksi
objekteiksi ja linkitetään lopuksi yhteen.
- makefile ja make-apuohjelma: idean esittely suhteessa graafiseen
IDEen. [POSIX-huomio: Uskotaan, että POSIX määrittelee make
-apuohjelman olemassaolon ja peruskäyttötavan. Käytetään kuitenkin
suosiolla maken GNU-toteutusta. POSIXin "rationale" -osiosta löytyy
perustelut, miksi näin on ihan suotavaa tehdä]
- ABI eli Application Binary Interface; lataaminen ja linkittäminen;
lopullisten osoitteiden asettaminen ja pyydettyjen kirjastojen
sisällyttäminen ohjelman muistiavaruuteen. Jaetut eli dynaamisesti
ladattavat kirjastot.
- Erittäin hyvä kysymys jaettujen kirjastojen (.so /.DLL)
"järkevyydestä": Luennoitsija väittää, että jaetuissa kirjastoissa
on enemmän plussia kuin miinuksissa, mutta samalla vakuuttaa, että
mitään väitettä ei kannata ottaa kritiikittömästi vastaan. Tosiasia
on, että aina pitää tehdä tilanteen mukaiset ratkaisut. Toinen
tosiasia on, että käytännössä yleiskäyttöisistä kirjastoista
pyritään tänä päivänä useimmiten tekemään mieluiten jaettuja
objekteja (Windows-nimeltään dynaamisia kirjastoja).
Isompi ohjelma, jossa on vaikkapa aliohjelmakutsuja ja silmukoita:
- Askellettiin demo 4:n esimerkkikoodia lähdekoodirivi kerrallaan
debuggerilla. Havainnoitiin kutsupinoa, jonka tilanteen saa gdb:ssä
näkyviin komennolla "backtrace" tai lyhennettynä "bt". Muita nimiä
ainakin aktivaatiopino, suorituspino.
Aliohjelmien ja pinon käyttö (osin jo myös demon 5 aihepiiriä):
- muistiavaruus ohjelman näkökulmasta: koodi (nähty jo aiemmin), pino
(nähdään nyt), data (ohjelman tekemisen yhteydessä alustettu), keko
eli dynaamiset eli tarpeen mukaan varattavat pienet tai isommatkin
muistialueet.
- aliohjelmakutsu, kutsupino
- debuggerin näkymä kutsupinoon, 'backtrace'-komento näyttää pinoon
kullakin hetkellä kertyneet aliohjelma-aktivaatiot.
- klassinen pinokehysmalli, aktivaatiotietueen rakentuminen pinon
päälle: kutsuva koodi pinoaa parametrit, call-käskyn suoritus pinoaa
automaattisesti paluuosoitteen, kutsuttu koodi pinoaa edeltävän
aktivaatiotietueen kantaosoitteen (BP) talteen, kiinnittää oman BP:n
ja varaa omille paikallisille muuttujilleen tilaa vähentämällä
SP:stä sen verran kuin paikallinen data tarvitsee
tavuja. Ylösalaisin piirretyssä kuvassa (muistiosoite 0 kuvan
ylälaidassa) pino kertyy visuaalisessa mielessä ylöspäin.
- Huomautus aktivaatiopinosta: Pinoon tallennetuista BP-osoitteista
muodostuu viittausketju, jonka kautta löytää aina pykälää alemman
aktivaatiotietueen. Pääohjelmassa tässä kohtaa on nolla eli
"NULL-viite", mistä tiedetään että pinon pohja on löytynyt. Tämä on
yksi konkreettinen esimerkki abstraktin "listamaisen" tietorakenteen
toteutuksesta muistiosoitteilla, jotka niin sanotusti linkittävät
mielivaltaisen kokoisia tietueita aina "seuraavaan" eli tässä
tapauksessa aiemmin kutsutun aliohjelman aktivaatiotietueeseen.
- Monisteen sarjakuvassa on esitetty kutsuvaiheen
operaatiot. Paluuvaiheen operaatiot on tehtävä käänteisessä
järjestyksessä. Monisteen tekstissä nämä on kuvailtu, ja demo 5:n
kohdalla nähdään debuggerin kautta konkreettinen toteutus AMD64:llä.
- Lisähuomautus: Aliohjelman kutsuminen ja sieltä palaaminen tulee
tietenkin määritellä konekielen tasolla laitteisto- ja
käyttöjärjestelmäkohtaisessa ABI-sopimuksessa (Application binary
interface), jotta konekielelle käännetyn ohjelman on mahdollista
käyttää konekielisiä jaettuja kirjastoja. Yhden ohjelman sisäisiä
kutsuja saa kukin tietysti tehdä ihan miten haluaa, joten
esimerkiksi koodin automaattinen optimointi saattaa tehdä aivan
kummallisen näköisiä kutsuja, joita on hankala ymmärtää ja
debuggailla disassemblyn perusteella. Kääntäjän vivut "-g -O0"
tekevät ymmärrettävämpää jälkeä. Demossa 5 esimerkkikoodissa on
ylimääräinen aliohjelmakutsu, joka ei tee mitään muuta hyödyllistä
kuin estää kääntäjää optimoimasta liikaa.
** Luento 10: Ohjelman jälki, aktivaatio, rekursio. Historiakatsaus.
Kerrataan tässä kohtaa yleisökysymys, joka viikko sitten tuli vasta
varsinaisen luentoajan jälkeen, videoinninkin loputtua. Tämä tulee
ihan pian tarkemmin, mutta otetaan silti jo alustava näkemys asiaan:
- muistihierarkian käytännön toiminta: laitteisto tosiaankin hoitaa;
sovellukselle päin näkyy peräkkäisiä tavun eli 8 bitin mittaisia
muistipaikkoja, joilla on omat, peräkkäiset osoitteensa. Vilkaistaan
kurssin loppupuolelle (lukuun Muistinhallinta): AMD64:ssä on
nelitasoinen hierarkinen "kartasto", jonka kautta konkreettinen
osoitteentulkinta virtuaalisesta fyysiseksi tapahtuu.
Idean tasolla meille riittää ajatella yksitasoista ns. sivutaulua,
jollaisen osaaminen on yleensä ollut tenttikysymyksenäkin. Eli ikään
kuin ajateltaisiin vain AMD64:n viimeistä taulukkotasoa, jonka nimi
oikeassa manuaalissakin on "Page table". Idean tasolla riittää myös
ajatella paljon lyhyempiä muistiosoitteita kuin esim. AMD64:ssä
oikeasti on.
Joka tapauksessa muistiosoitteen bittijonon alku ilmoittaa, mille
sivulle osoitus kohdistuu, ja loppuosa, esim. 12 bittiä ilmoittaa
tarkan osoitteen kyseisen sivun sisällä. Fyysinen muisti on jaettu
sivukehyksiin.
Sivutaulujen (ja tarvittaessa monitasoisten hakutaulukostojen)
luonti on käyttöjärjestelmän muistinhallintaosion vastuulla. Se
tekee sen prosessorin ja MMU:n manuaalin määrittelemillä
keinoilla. Toki itse taulut ja "kartastot" ovat määrämuotoista
dataa, joka sijaitsee tietokoneen muistissa (käyttöjärjestelmän
hallitsemalla alueella), missä kaikki muukin. Esim. "AMD64 System
Programmer's Reference" kertoo kaiken siitä, miten näitä tauluja
käytetään.
Perinteinen "kaikenlaskija" -esimerkki demonstroimaan aikakatkaisun
tarvetta.
Demo 5:n olennainen sisältö, eli aliohjelma-aktivaatio ja konekielinen
ohjelman suoritus asiana loppuun:
- Ohjelman jälki (engl. "trace"; mm. Stallingsin kirjan terminologiaan
vedoten) eli varsinaisten suoritettujen käskyjen ketju. Tietyssä
muistipaikassa oleva konekielikäsky voi sisältyä jälkeen useita
kertoja (toistuvat silmukat, useasti kutsutut
aliohjelmat). Toisaalta tietty konekielikäsky ei sisälly jälkeen
lainkaan (esim. tiettyä aliohjelmaa ei tarvitse kutsua tai tietty
ehto ei koskaan täyty jossakin ehtolauseessa).
- Reunahuomautus: Kaikkein tiukimmat laadunvarmistusmenettelyt
vaativat muiden seikkojen ohella, että testien koodikattavuus eli
"code coverage" on 100%. Tämä tarkoittaa, että testiohjelman jäljen
tulee kulkea jokaisen konekielisen käskyn läpi vähintään kerran. Eli
testikeisseissä on oltava oikeita ja vääriä syötteitä sekä
simuloituja toimintahäiriöitä niin paljon, että kaikki if-then-else
-vaihtoehdot ja catch-lohkot käydään testin aikana läpi. Tämä on
kallista puuhaa, joten 100% koodikattavuus on järjetön muiden kuin
potentiaalisesti ihmishenkeä uhkaavien ohjelmistojen testaamisessa
(mm. siviililentokoneiden ohjaus, tietyt lääketieteelliset
instrumentit).
- Aliohjelmakutsu siten kuin demo 5:ssä käsitellään.
- Rekursio (Kokonaisluvun kertoma rekursiivisesti): saman aliohjelman
aktivaatiot päällekkäin pinossa.
- Jälki, laitekeskeytykset ja reaaliaika: Nykyjärjestelmissä
sovellusohjelma ei tiedä, mitä kahden konekielikäskyn välissä
tapahtuu ja kauanko siinä kestää. Käyttöjärjestelmän koodi voi estää
estää tai sallia uudet keskeytykset, joten "atomisen toimenpiteen"
toteutuminen sovellusohjelmassa edellyttää käyttöjärjestelmäkutsun
tekemistä.
Ja sitten:
Katsaus tietokoneiden ja käyttöjärjestelmien symbioottiseen
historiaan. Jotta voidaan katsoa nykypäivästä eteenpäin, täytyy
tietää, mistä tähän ollaan tultu ja miten!
Ensimmäiset tietokoneet 1940-1950 -luvuilla eivät moniajoa
mahdollistaneet, mutta siitä se kehitys sitten havaittujen ongelmien
ja ratkaisujen kautta lähti... ensimmäisenä ohjelmointikielten ja
kääntäjien rakentelulla, suojatun tilan ja käyttöjärjestelmätilan
toteuttamisella prosessorin ominaisuutena sekä keskeytysten,
mm. aikakatkaisun löytymisestä prosessorin piirteenä, joka keskeyttää
sovelluskoodin ja siirtää prosessorin käyttöjärjestelmätilaan aina,
kun laitteistossa tapahtuu jotakin uutta.
Lähes 70-vuotisen historiikin kautta perusteltakoon tarpeet
vuorontamiseen, moniajoon, muistin ja muiden laiteresurssien
hallintaan sekä muihin toimenpiteisiin, joihin käyttöjärjestelmää
nykypäivänä tarvitaan. Merkkipaaluja tietokoneiden ja
käyttöjärjestelmien kehityksessä vuosien varrella. Kehitys
nykymuotoisia käsitteitä ja toimintamalleja kohti tapahtui erityisesti
1960-luvun aikana:
- hukka-ajan poisto: keskeytykset, I/O:n odotus ja aikakatkaisu
- Prosessorin täytyy voida toimia ainakin kahdessa eri tilassa:
suojatussa ja rajoitetussa (tietyt muistiosoitteet ja
I/O-toimenpiteet kiellettyjä) käyttäjän tilassa ja
rajoittamattomassa käyttöjärjestelmän tilassa; tilojen välinen
siirtymä täytyy olla mahdollista - erityisesti meneillään olevan
suorituksen keskeyttäminen esimerkiksi aikakatkaisuna täytyy olla
mahdollista. Myös käyttäjtilan ohjelmalla täytyy olla mahdollisuus
pyytää siirtymää käyttöjärjestelmän palveluun ("system call")
jolloin prosessorin tilan on vaihduttava.
** Luento 11: Prosessi, "säie", resurssit, haaroitus ja käynnistys
Mihin jatkokursseihin seuraavaksi käsiteltävät aiheet johtavat? No
kaikkeen ohjelmistotekniikkaan, mutta ks. esimerkiksi seuraava tämän
vuoden kesäkurssi Korpista:
https://korppi.jyu.fi/kotka/course/student/generalCourseInfo.jsp?course=196089
Huomatkaa esitietokysely, jos ilmoittaudutte kys. kurssille!!
Ihan pari historiallista artikkelia:
- lokaalisuusperiaatteen historiaa lähdemateriaalista vilkuillen
(kirjallisuusviite kiinnostuneille, lisämateriaalia, ei pakollinen:
http://denninginstitute.com/pjd/PUBS/CACMcols/cacmJul05.pdf
... edistyneenä osaamistavoitteena on oppia löytämään ja lukemaan
tieteellisiä artikkeleita vuosien varrelta)
- katsottakoon läpi myös alkuperäinen UNIXin, C-kielen ja putkitusta
tukevan shellin uutuuksia hehkuttava artikkeli "The UNIX
time-sharing system" vuodelta 1974.
Sitten periaatteessa luentomonisteen järjestyksessä etteenpäin...
Prosessorin suoritussykli:
- käskyn ja operandien nouto, suoritus, tulosten tallentaminen JA
mahdollinen ohjelman itsensä aiheuttama (syscall-pyynnöllä tai
laittoman/mahdottoman käskyn seurauksena) tai ulkopuolelta tuleva
keskeytys. Keskeytys on mahdollinen minkä tahansa käskyn jälkeen,
jos sen aiheuttaa ulkopuolinen, kontrolloimaton, lähde. Käytännössä
ainoa koodi, joka voi tapahtua ilman keskeytyksiä, on alkupuoli
käyttöjärjestelmän keskeytyskäsittelijästä - kunnes kyseinen koodi
itse sallii uudet keskeytykset. Luentomoniste kertoo hieman lisää
yksityiskohtia.
- "FLIH", eli mitä keskeytyksen tullessa tapahtuu prosessorissa ennen
seuraavan käskyn noutoa.
Yhdenaikaisuus, Prosessi:
- prosessin käsite yhteenvetona aiemmasta: muistiin ladattu ja
käynnistetty, suorituksessa oleva 'kuva' ohjelmasta.
- Yllätys-POSIX-vartti: Miten POSIXin Base Definitions -osion
termimäärittelyissä kuvaillaan termi "Process"? Vautsi... Pystytään
jo ymmärtämään suurin osa tästä kuvailusta tähän asti käsiteltyjen
esitietojen kautta! Määrittelyssä tulee jo mukavasti esille "säie",
mikä tarkoittaa yhtä ajan suhteen etenevää suorituskohtaa
ohjelmassa. Prosessilla on POSIXinkin mukaan aina vähintään yksi
"säie", joka alkaa ohjelman alusta ja päättyy ohjelman
loppuessa. Säie muodostaa yhden konekielisen jäljen, eli peräkkäin
suoritettujen käskyjen sarjan. Tässä päästään jo pakosti uumoilemaan
seuraavaa asiaa, eli että prosessilla voi olla yhden sijasta
useampia säikeitä.
Prosessilla on vanhempi, mahdollisesti myös lapsia ja sisaruksia -
riippuen mikä prosessi on pyytänyt luomaan uusia. Sillä on
identiteetti (vähintään ID-numero) sekä käynnistävän käyttäjän ja
mahdollisesti ryhmän identiteetit (vähintään ID-numerot). Lisäksi
sillä on oma muistiavaruus, joka sisältää koodi-, data-, pino- ja
kekoalueen sekä dynaamisten kirjastojen koodialueita. Nykyisin myös
käyttöjärjestelmän tarvitsemat alueet on liitetty jokaisen prosessin
virtuaalimuistiavaruuteen.
Mitä muuta liittyy prosessiin?
- resurssin käsite: laitteiston osat, tiedostot ja yhteydet,
mukaanlukien prosessorin käyttöaika ja rajallinen keskusmuisti, ovat
resursseja, joita käyttöjärjestelmä allokoi prosessien käyttöön
niiden pyynnöstä; aiemmin mainittujen lisäksi näihinkin tietoihin on
päästävä käsiksi prosessikohtaisten tietojen kautta. (Näkökulma
käyttöjärjestelmään resurssimanagerina).
- Prosessit käyttöjärjestelmän tietorakenteena: prosessielementti
("Process Control Block", PCB) ja prosessitaulu ("process table" /
"process array") tai prosessilista (kuten Linux-toteutuksessa on).
- Linuxin task_struct -tietorakenne, eli noin 450 koodiriviä
(versiossa 4.4) määritelmiä siitä, mitä tietoja yhteen prosessiin
kuuluu. Kiinteä linkki version 4.4 lähdekoodiin:
http://lxr.free-electrons.com/source/include/linux/sched.h?v=4.4#L1378
Havaintoja: osa on kokonaislukuja, mutta suuri osa on osoittimia
laajempiin tietorakenteisiin, joille on varattu muistia jostain
toisesta kohtaa muistia. Suuri osa myös riippuu
konfigurointivaiheessa valituista ominaisuuksista (#ifdef
CONFIG_JOKIN_OMINAISUUS_MUKANA ... #endif).
Kyseessä on normaali C-kielen tietorakenne, jonka sisäiset kentät
ovat muistissa tallessa peräkkäisessä järjestyksessä. Huomaa mm.
rakenteen määrittelyn lopussa oleva kommentti, joka muistuttaa, että
x86-koneiden osalta nykyisellään viimeiseksi kirjoitetun kentän on
todellakin oltava viimeinen, eikä sen jälkeen saa lisätä mitään
muuta.
Liukulukuja ei käyttöjärjestelmäkoodissa juurikaan ole. Esim. ajat
mitataan kokonaisina nanosekunteina eikä osittaisina sekunteina tai
muuta, mikä edellyttäisi muita kuin kokonaislukuja.
- Prosessin tilat ja tilasiirtymät, tilakaavio.
- Vuorontaja ja vuorottelu: prosessoriajan jakaminen. "Kiertojono" eli
Round Robin. Odottelujonot blokatuille prosesseille.
- Kontekstin vaihto laitteiston ja käyttöjärjestelmän
yhteistoimintana.
Koko kontekstin vaihtaminen (kaikki rekisterit + muistikartta)
vaatii aikaa, joka on pois hyötylaskennasta - optimointina
esim. pidemmät aikaikkunat ja modernien prosessorien "kevyet
vaihdot". Harvemmat vaihdot prosessien välillä -> isompi
"throughput". Pakollisena kompromissina tulee pidemmät vasteajat tai
huonompi tasapuolisuus.
- Prosessin luonti haaroittamalla eli kloonaamalla vanhempiprosessi
(unix-pohjaisen käyttöjärjestelmän tapa luoda uusia prosesseja):
Esimerkkinä ihan itse käännetty minimalistinen shell, joka odottaa
komentoriviä ja osaa käynnistää käyttäjän pyytämän ohjelman.
[ Tällä kurssilla tutkitaan unixmaista tapaa luoda prosesseja; jos
Windows-maailman variaatio sattuu kiinnostamaan,
käyttöjärjestelmäkutsun CreateProcess() rajapinta löytyy tuolta:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx
]
Prosessielementin kloonaus fork():illa ja korvaaminen ladattavan
ohjelman tiedoilla exec():issä vaatii "maistelua", miettimistä ja
parin unen näkemistä. Tätä voi harrastaa vaikkapa vapun ohessa, joka
tapahtuu vuonna 2016 tässä välissä ennen seuraavaa luentoa.
** Luento 12: IPC: signaalit, viestijono. Säikeet
Alussa paikkaus viime fiikon fork() ja exec() -kuvaan. Rauhallisempi
katsanto minish.c -esimerkkiin eli minimalistiseen shell-ohjelmaan.
Millainen sää luentosalin ja Agoran ulkopuolella vallitsee tällä
hetkellä? Komennetaanpa shellissä:
curl wttr.in/Jyvaskyla
Mitäs? Joku on tehnyt hauskan palvelun, josta opiskelija vinkkasi
irkissä. cURL on POSIXin määrittämä apuohjelma, joka noutaa Internetin
yli URLin mukaisen vastauksen palvelimelta ja ohjaa sen
standardiulostuloon... "man curl" kertoo lisää. Tämä on standardimpi
tapa yksittäisiin WWW-palvelinkyselyihin kuin mm. demo-ohjeissamme
käytetty "GNU Wget". Kapeaan terminaali-ikkunaan ei välttämättä mahdu
koko tuloste, joten luentosalissa seuraava voi olla parempi komento:
curl wttr.in/Jyvaskyla 2>/dev/null | head -7
Tämä komento putkittaa curl'in tulosteen head'ille, jonka avulla voi
tulostaa vain argumenttina annetun määrän ensimmäisiä riviä. Nyt curl
voi joutua lopettamaan tulostuksensa kesken, kun head ei haluakaan
enää lisää syötettä. Curl toteaa tämän virheilmoituksena
standardivirhevirtaan, josta ei tässä komennossa olla kiinnostuneita,
joten virhetulosteet ohjataan operaattorilla '2>' kankkulan kaivoon
eli /dev/null'iin johon ohjatuilla tavuilla ei tehdä mitään.
Asiaan.
Katsotaan vielä kertaalleen viimeviikkoista minish -shelliä, ja
yliopitaan se, sekä siihen liittyvät fork() ja exec()
-palvelut. Monisteen kuva fork() ja exec() -kutsuista on myös korjattu
viime luennon jälkeen. Oli nimittäin vähän jäänyt sisältöä matkalle
ulkoasupäivityksen yhteydessä.
Ja sitten uutta...
Prosessien (ja säikeiden) välinen kommunikointi eli IPC, alustavasti:
- engl. Inter-process communication. Yksi tärkeistä tehtävistä, joihin
käyttöjärjestelmää tarvitaan. Alustavia esimerkkejä (joihin ehkä
palataan):
+ signaalin lähettäminen pääteyhteyden näppäilyllä "päällimmäiselle"
ohjelmalle, jolle syötteet ohjautuvat.
+ signaalin lähettäminen kill -komennolla shellistä. Signaalien
listaaminen. Esimerkkisovellus: dd -apuohjelman tilannetiedon
kysyminen (ei toiminut luennolla jostain toistaiseksi
tuntemattomasta syystä; manuaali lupaa, että dd:n pitäisi osata
napata SIGUSR1 - kumma juttu.. selvitellään..)
+ yksi erilainen IPC-tapa, viestijono (message queue):
koodi 2016/esimerkit/l12/ -hakemistossa: chattomyself.c
+ toisin kuin ennakkoon määritellyillä kokonaisluvuiksi
koodautuvilla signaaleilla, viestijonolla voi välittää laajempia
viestejä. Nimensä mukaisesti viestijonossa on mahdollisuus
jonoihin perustuvaan odotteluun. Lähettäjän ja vastaanottajan on
molempien osattava löytää sama jono, ja ensimmäisen prosessin
täytyy pyytää käyttöjärjestelmää luomaan uusi jono.
Säie vs. prosessi:
- Säie on yksi ajassa etenevä suorituskohta prosessin koodissa, joka
muodostaa konekielisten suoritusten "jäljen" ja vaikutuksia dataan.
- Prosessilla voidaan aina ajatella olevan vähintään yksi
säie. (ks. esim. POSIXin Base definitions -luvun määritelmä termille
"Process")
- Jos alusta (ts. käyttöjärjestelmä ja apukirjasto) tukee useampia
yhdenaikaisia säikeitä, niitä voi luoda prosessille tarpeen mukaan,
esim. POSIXin säielaajennoksen kutsulla
pthread_create(). Lähdekoodissa säie ilmenee aliohjelmana, jonka
päättymistä voi jäädä odottelemaan esim. POSIXin kutsulla
pthread_join() tai säikeen voi jättää suorittamaan tehtäväänsä
"taustalle" tarvittaessa vaikka koko prosessin päättymiseen saakka,
tai niin pitkään kuin säikeen operaatio ylipäätään kestää.
- Suorituksen vuorottelun mielessä säie ja prosessi ovat hyvin
samantyyppisiä käsitteitä: periaatteessa kaikki säikeiden avulla
tehtävät asiat voitaisiin hoitaa myös luomalla prosesseja.
- Säie on kuitenkin yhden sovelluksen sisäisiin tarpeisiin paljon
kevyempi konsepti: se tarvitsee olennaisesti vain prosessorin
kontekstin, pinomuistin ja muut suorituskohtaan liittyvät tiedot -
kaikki muu, mukaanlukien koodi, keko, globaali data, avatut
tiedostot, ym. ovat yhteiset säikeen omistavan prosessin kanssa.
- mihin säikeitä voi käyttää? Esim. ohjelman sisäiset "tausta-ajot"
(esimerkiksi videon toistaminen selaimen välilehdessä samalla kun
käyttäjä voi klikkailla muita välilehtiä keskeytyksettä; suurten
tiedostojen lataamiset ja tallentamiset), seinäkelloajan minimointi
rinnakkaislaskennalla.
- Toimintojen nopeuttaminen säikeistämällä edellyttää eri säikeiden
suorittamista konkreettisesti yhtäaikaa rinnakkaisilla
prosessoriytimillä. Yhdenaikainen tausta-ajo onnistuu tietysti
yhdelläkin prosessorilla normaalin prosessien vuoronnusmenettelyn
tapaan.
- esimerkki: taulukon täyttäminen peräkkäisillä luvuilla
koodit 2016/esimerkit/l12/ -hakemistossa: saikeiden_tarve.c saikeet.c
- tämän maanantain cliffhanger: "kilpa-ajotilanne" eli race condition:
vuoronnus voi milloin vain keskeyttää säikeen (tai prosessin) ja
antaa suoritusvuoron toiselle:
koodi 2016/esimerkit/l12/ -hakemistossa: race.c
** Luento 13: Kilpa-ajo, lukot, deadlock, semafori
- Millainen sää ulkona? (aurinko paistaa ja lämmintä on)
Teinpä itselleni näppärän alias-komennon viime viikon
wttr.in-palvelun käyttöön. Aliakset ovat POSIXissa määritelty tapa
tehdä itselle tosi lyhyitä komentokorvikkeita shellin
interaktiivisen käytön tehostamiseksi.
Tarkennetaanpa viime kerralla epäselviksi jääneet asiat:
- Mitä reittiä näppäimistöllä generoidut signaalit (esim. Ctrl-C,
Ctrl-Z, Ctrl-D, ...) menevät ohjelmille?
(Alempana on TLDR-versio.) Pidempi vastaus arvailtuna meidän
käyttämän bashin manuaalin osiosta "JOB CONTROL" lisättynä pienellä
nettiseikkailulla... Jos itse ymmärsin oikein (korjatkaa, jos olen
jonkun mielestä pahasti väärässä), niin homma kiteytyy näin: (1)
painallushan tapahtuu asiakaskoneella, jonka pääteohjelma ensinnäkin
lähettää, mitä haluaa. Yleensä jonkun muinoisen standardin mukaisina
tiettyinä ohjausmerkkeinä, jotka nyt on vaan numeroiksi koodattuja
kuten muutkin näppäinpainallukset (2) ssh-palvelin ohjaa
näppäinpainallukset shellille, jonka se on käynnistänyt ja jolle se
kommunikoi (3) jos siinä välissä on "screen"-apuohjelma, niin se
nappaa painallukset ja oletusarvoisesti "syö" Ctrl-A:n omaksi
ohjausnapikseen. Muut painallukset ohjautuvat sen screen-ikkunan
shellille, joka käyttäjällä on valittuna. Screen on aikoinaan
käynnistänyt tuon shellin, ja osaapi sille ohjata syötteensä (4)
screenissä aktiivinen shell tutkii näppäinkoodin, ja joidenkin
osalta se generoi signaaleja, jotka se lähettää
ns. "foreground"-prosessille, eli sellaiselle, joka on shellissä
"päällimmäisenä" suorituksessa tällä hetkellä.
Mainitusta "JOB CONTROL" -osiosta löytyy lisätietoa siitä, miten
bashissä voi laittaa komentoja taustalle ("background"-prosessiksi),
ja nostaa etualalle tarpeen mukaan. Muihin prosesseihin ei ole
vaikutusta. Jos ei shellissä ole mitään prosessia etualalla, se
tulkitsee näppäinpainalluksen itselleen. Bash itse ei esimerkiksi
reagoi Ctrl-C:hen eikä Ctrl-Z:aan. Tyhjän rivin alussa se tulkitsee
Ctrl-D:n kirjaimellisesti muinoisen numerokoodauksen mukaan
ohjausmerkiksi "HUP - hangup" ja toteaa, ettei käyttäjä halua enää
jutella. Rivin keskellä Ctrl-D tulkitaan GNU:n getline()-funktion
mukaisesti editointikomennoksi, jolla poistetaan kursorin alla oleva
merkki.
TLDR-kiteytys: Painat Ctrl-C, niin shellissä "meneillään oleva"
ohjelma saa signaalin, jolla sitä pyydetään loppumaan. Ctrl-Z:lla
sellaisen, jolla sitä pyydetään menemään toistaiseksi jäähylle.
- Miksi dd ei toiminut, vaan oli "huono esimerkki"?
Jotain oli mennyt pahasti kuralle siinä shellissä, josta ajoin
dd:tä. Miksi? Halusin käyttää ajan luentomonisteen ja esimerkkien
parissa, joten jätin selvittämättä. Todennäköisesti olin painanut
jotakin tosi väärää näppäintä epähuomiossa, tai sitten jokin
esimerkkikoodi laittoi systeemejä sekaisin vanhempiprosessia
myöten. Esim. minish ei välttämättä ole maailman parhaiten
käyttäytyvä, vaikka se perusvaatimuksensa täyttääkin.
Ongelma poistui, kun suljin kyseisen shellin ja käynnistin
screenistä uuden.
Esimerkki on siis edelleen yhtä hyvä kuin ennenkin, joten katsotaan
se uudelleen ilman ihmettelyä.
- Miksi järjestelmässä on "Zombie"-prosesseja, jotka eivät lähde pois
edes komennolla "kill -9 1234"?
Tähän nyt tajusin vastauksen jo kun luentosalin ovi meni perässäni
kiinni: Zombie on esim. Linuxin käyttämä nimi prosessin tilalle,
joka monisteessame on geneerisesti "Exit". Prosessin suoritus on jo
päättynyt, mutta se on mukana prosessitaulussa, kunnes sen
vanhempiprosessi tarkistaa prosessin lopputilanteen. Ts. jos jossain
on paljon "Zombieita", niin niiden vanhempiprosessi käyttäytyy
jotenkin huonosti, eikä ole tehnyt tarvittavaa wait() kutsua, tai
sitten prosessi on siirretty jotenkin väkipakolla vanhemmalta
toiselle, ennen kuin se on päättynyt. Vanhemman lopettamisen pitäisi
tuhota automaattisesti kaikki lapset, vaikka ne olisivat olleet
Zombieita. Vanhemmattomaksi joutunueet Zombiet lienee aika
mahdotonta siivota ajamatta järjestelmää alas, ja ne implikoivat,
että jokin softa toimii haaroittamisen suhteen väärin. [Vastauksen
voi lukea Walking Dead -kontekstissa, vaikka ilmeisesti viime
luennon kysymys koski Linuxia. Asiaan? Ei vielä..]
- Miksi säie-esimerkin koodi toimi ensin hitaammin, ja seuraavilla
yrityksillä nopeammin?
Kotimatkalla hokasin pari mahdollista/todennäköistä selitystä:
+ Voi olla, että fiksu järjestelmä pitäisi prosessoreja hitaammassa
"virransäästelytilassa", kunnes tehdään havainto, että näinä
aikoina tarvitaan nopeampaa laskentaa.
+ ylipäätään meidän jalava ja halava ovat virtuaalikoneita, joten
siinä on vielä isomman koneen "load balancing" mukana pelissä:
paukkuja laitetaan niille koneille, joissa havaitaan
laskentatarvetta.
+ fiksusti tehty adaptaatio molemmissa tapauksissa toimii hiukan
jälkijunassa aiheuttavaan ilmiöön nähden, koska aivan lyhyisiin
ilmiöihin ei kannatakaan reagoida.
+ tarkempi vastaus ei selviäisi ihan hetkessä :), mutta tämä
"alkuhidastelu" on meidän järjestelmässä ihan toistettavissa
oleva havainto, kuten tänäänkin nähtiin.
TODO: aiemman kysymyksen tarkennus: "Jos mulla olisi vanhan mallinen
rinnakkais-/sarjaportti, miten tekisin/asentaisin sille laiteajurin
Linuxiin"? -> I/O -luennolle yhdeksi aiheeksi Linuxin laiteajurin
tekeminen (tai ainakin jonkinlainen lähtökohta...)
Sitten luentomonistetta eteenpäin. Luku 9 seuraavana edessä.
Prosessien/säikeiden välistä kommunikointia (inter-process
communication, IPC):
- IPC: signaalit; käytiin viimeksi tarkoin läpi
- IPC: viestit; käytiin viimeksi päällisin puolin läpi POSIXin
mukainen esimerkki
- IPC: jaettu muisti; katsotaan luentomonisteen kuvan tasolla läpi
- IPC:tä vähän lisää (käsitteiden ja käyttöjärjestelmäkutsujen nimien
tasolla): viestit, putket, RPC, socketit, verkkoprotokollat.
Ja nyt.. jatketaan suoraan viime luennon cliffhangerista...
Yhdenaikaisuuden ongelmia ja ratkaisuja:
- esimerkki: "kilpa-ajotilanne" eli race condition, lukotustarve
koodi repossa: 2016/esimerkit/l13/race.c
- mutex, mutual exclusion; poissulku.
- esimerkki: mutexin tekeminen POSIXin säiemutexilla.
koodi repossa: 2016/esimerkit/l13/race_fixed_mutex.c
- mitä tapahtuu kokonaissuoritusajalle lukituksen kanssa?
+ jos lukituksia tarvitaan paljon, käytännössä kaikki aika menee
lukkologiikkaan ja jonotuksiin, ei hyötylaskentaan.
+ Saatiin yleisöstä myös muita hyviä tarkennuksia! (ks. video)
Kun on lukkoja, niin on niihin liittyviä vaaroja:
- lukituksesta aiheutuva synkronointiongelma: deadlock, triviaali
esimerkki "lukkiutuva vappu" (nimiä vaille sama kuin luentomonisteen
"ruokailevat nörtit")
koodi repossa: 2016/esimerkit/l13/vappu_deadlock.c
koodi repossa: 2016/esimerkit/l13/vappu_ei_lukkiudu.c
- "ruokailevat filosofit" on klassinen esimerkki, jossa on enemmän
kuin kaksi prosessia ja resurssia. Rutkasti (ei-pakollista)
lisätietoa löytyy Internetin ihmeellisestä maailmasta, esim. tämä
lähteineen: http://en.wikipedia.org/wiki/Dining_philosophers_problem
Wikejä pitkin löytyi myös mm. seuraava vapaa ja ilmainen oppikirja
synkronointiaiheista: http://greenteapress.com/semaphores/
- esimerkki: mutexin toteutus binäärisellä POSIX-semaforilla.
koodi repossa: 2016/esimerkit/l13/race_fixed_sem_mutex.c
- semafori käsitteenä (+historia) ja tietorakenteena.
Esihistoriasta (1960-luku)
esim. http://www.cs.utexas.edu/users/EWD/ewd00xx/EWD35.PDF
Nykypäivästä esim. WoK-haku sanalla "semaphore"
Reunahuomautus: "lukekaa sitä matikkaa" ;)
- jaetun resurssin ja kriittisen alueen käsite;
Helatorstain ja viikonlopun cliffhanger:
- Perusesimerkki tuottajaprosessin ja kuluttajaprosessin tarpeesta:
animaation tuottaminen ja pakkaaminen yhdenaikaisena "liukuhihnana".
** Luento 14: Tuottaja-kuluttaja. Muistinhallinta, virtuaalimuisti
Viime viikon aihe loppuun:
Esimerkki moniarvoisen semaforin käytöstä:
- esimerkki: tuottaja-kuluttaja -probleemi sekä sen ratkaisu kolmella
semaforilla
koodi repossa: 2016/esimerkit/l14/tuottaja_kuluttaja.c
"ASCII-sarjakuva" repossa: 2016/esimerkit/l14/tuott_kulutt_rengaspuskuri.txt
Vaatii omakohtaista miettimistä! Tämäkin esimerkki on tarkoituksella
yliyksinkertainen, vaikka siinä onkin mukana olennaiset osuudet:
semaforien alkuarvojen asettaminen ja oikeellinen järjestys
semaforikutsuille. Osaamistavoite on ymmärtää, mikä on semafori ja
miten rengaspuskuria käyttävä tuottaja-kuluttaja toteutetaan
semaforilla.
- Pienoishuomioita prosessien/säikeiden synkronoinnista:
+ Onnistuu semaforeja vastaavalla "vahvuudella" mm. myös
viestinvälityskutsuilla ja ns. "monitoreilla"; kauan sitten
tutkittu, todettu ja julkaistu asia.
+ Nykyisissä oliokielissä helppoa: Javassa heitetään avainsana
"synchronized" kentälle ja C#:ssa ilmeisesti (tsekattu lyhyesti
nettifoorumeilta) tyyliin
"[MethodImpl(MethodImplOptions.Synchronized)]" tai "lock {
/*lukituksen tarvitsevaa koodia tässä*/ }".)
+ Deadlock ja muut ongelmat aina mahdollisia myös uudemmissa
oliokielissä! Varovasti aina! Yhdenaikaisuus vaatii erityistä
tarkkuutta suunnittelussa.
+ Synkronointia ei pidä käyttää, jos ei sitä tarvita! Mutta pitää
tunnistaa kohdat, joissa välttämättä tarvitaan. Erityisesti
täytyy tietää aivan yksittäisen muuttujan tasolla, onko se
mahdollisesti jaettu usean säikeen kesken.
+ Säikeitä kannattaa alkaa käyttämään omissa ohjelmissa tarpeen
mukaan, muistaen tarkkaavaisuuden ja potentiaaliset
ongelmatilanteet!
[ lämmittelytauko auringossa, 5 min ]
Sitten monistetta eteenpäin...
Muistinhallinta:
- tavoitteet:
+ maksimaalinen kapasiteetti, riittävä nopeus. Perusidea: pidetään
tällä hetkellä käyttämättömät tiedot hitaassa mutta isossa
muistissa, tuodaan tarvittaessa lähemmäs. Eli hyödynnetään
lokaalisuusperiaate -havaintoa.
+ suojaus, eri oikeudet eri muistialueilla. Looginen eriytys
segmentteihin: koodi, data, pino, keko (dynaamiset oliot)
- käytettävissä: muistihierarkian mukaiset muistit, prosessori, MMU
Sivuttava virtuaalimuisti:
- sivutus
- osoitteen tulkinta, osoitteenmuunnos virtuaalisesta fyysiseksi
- prosessorin sivutaulu: sisältää fyysisen sivukehyksen indeksin sekä
yksittäisinä bitteinä sivukohtaiset suojaus- käyttöhistoriatiedot ja
tiedon, onko sivu muistissa vai kovalevyllä.
** Luento 15: Heittovaihto. Unixin tapa ilmentää moni asia tiedostona
Muistinhallinta. Jatketaan suoraan siitä, mihin maanantaina jäätiin:
- heittovaihto (swap), working set:
+ Siinä missä laitteisto hoitaa prosessorin sisäiset välimuistit,
käyttöjärjestelmä pystyy ottamaan vastaavalla periaatteella
avuksi myös käytännössä rajattoman kokoiset massamuistit.
+ prosessorissa on ominaisuudet (sivutaulun automaattisesti
päivittyvät bitit), joilla heittovaihto on mahdollista toteuttaa.
- sivuvirhe (page fault) / sivunvaihtokeskeytys ja sen käsittelijä
- käyttöjärjestelmän tietorakenteet: prosessikohtaiset sivutaulut ja
kehystaulu.
- Korvausalgoritmi, esim. least-recently-used
(LRU). Käyttöjärjestelmän operaatiot "swap out" ja "swap in"
-vaiheissa.
Välimuistin ruuhkautuminen eli "cache trashing" tarkoittaa välimuistin
ulkopuolisen väylän tai pahimmillaan heittovaihdon suhteellisesti
tiuhempaa käyttöä, joka tuhoaa suorituskyvyn - välimuistien osaltakin
dramaattisesti, mutta heittovaihdon osalta jopa rampauttavasti).
- Esimerkki: (jälleen simppeli "koeputkiesimerkki", jotta perusilmiö
näkyisi mahdollisimman hyvin):
koodi repossa: 2016/esimerkit/l15/cache.c
- Miten tällaisilta vältytään?
+ Suunnitellaan algoritmit suoraviivaisiksi ja mahdollisimman
vähän operaatioita vaativiksi aivan normaaliin tapaan; lisäksi
selvitetään, millä tavoin alla oleva alusta käyttää muistia,
eikä tehdä "luonnonvastaista" koodia.
+ Yhdenaikaisten prosessien/säikeiden ja putkien käyttö
mahdollistaa peräkkäisten dataoperaatioiden rakentelun
modulaarisesti (operaatiot vaihdeltavissa keskenään; peräkkäiset
operaatiot tapahtuvat yhdenaikaisesti, kun data on vielä
edeltävän operaation jälkeen lähemmässä muistikomponentissa)
+ (ja niin edelleen. Lisää jatkokursseilla, joissa puhutaan
enemmän ohjelmistojen ja järjestelmien suunnittelusta.)
Esimerkki muistin kartoituksesta ja muiden kuin tavallisten
tiedostojen ilmenemisestä tiedoston näköisinä, normaalissa
hakemistopuussa, unixmaisessa käyttöjärjestelmässä; aasinsilta
tiedostojärjestelmiin:
- Esim. prosessin 1234 muistikartan saa Linuxissa nähtäville
tulostamalla erikoistiedoston nimeltä /proc/1234/smaps
- Kokeillaan esim. käynnistää aiempi "lukkiutuva vappu", ja
tutkitaan muistikarttaa kaikessa rauhassa säikeiden ollessa
ikuisessa jumissaan.
- Katsotaan myös jotain oikean ohjelman karttaa,
esim. emacs-tekstieditorin. Havaitaan lukuisa joukko kirjastoja
Luennoilla on aiemmin nähty esimerkkejä muistakin erikoistiedostoista,
esim. /dev/urandom -tiedoston lukeminen saa käyttöjärjestelmän
generoimaan satunnaislukuja. Tiedostoon /dev/null voivat kaikki
käyttäjät "kirjoittaa", mutta siihen ohjattu data ei mene mihinkään,
vaan erikoistiedosto "nielee" tavut. Muita vastaavia, joita
unixmaisista usein löytyy:
+ /dev/random yrittää tuottaa "aitoa satunnaisuutta"
tarkkailemalla ulkopuolisesta ympäristöstä riippuvia tekijöitä,
kuten nettiyhteyksiä. *Älä käytä turhaan yhteiskäyttökoneella*,
koska generointi hidastuu kaikkien tarvitsijoiden
osalta. Ulkoisia ilmiöitä tapahtuu harvakseltaan "uskottavan
satunnaisuuden" aikaansaamiseksi. Normaalitarpeisiin lue
/dev/urandom -tiedostoa ("u"=="unlimited"), joka toimii kuten
C:n rand()-funktio. Tiukempiin kryptografiatarpeisiin tällainen
pseudosatunnaisuus ei ole välttämättä riittävä.
+ /dev/zero tuottaa loputtomiin nollatavuja luettavaksi.
+ /dev/sda vastaa ensimmäisen koneeseen liitetyn fyysisen
kovalevyn tavuja ilman tiedostorakennetta; voi käyttää
esim. täydellisen varmuuskopion tekemiseen tai
palauttamiseen. Tietenkin käyttö on sallittu vain ylläpitäjän
oikeuksilla. Kopiointi myös edellyttää järjestelmän
käynnistämistä esim. muistitikulta siten, että kovalevy ei ole
kopioinnin aikana kytketty tiedostoineen.
+ /dev/tty on jopa POSIXin määräämä. Se toimii erikseen jokaiselle
prosessille, ja sitä tulee voida käyttää syöttöihin ja
tulostuksiin samoin kuin päätettä
+ Hakemiston /dev/ listaaminen näyttää monia muitakin
tiedostonimiä, jotka itse asiassa vastaavat fyysisiä
I/O-laitteita. Useimmat ovat saatavissa vain
järjestelmänvalvojan oikeuksilla, ja niitä on tarkoitus käyttää
sovelluksissa käyttöjärjestelmäkutsujen kautta sen sijaan että
suoraan esim. päätteeltä.
Esimerkki:
- kahden eri ohjelman jakama muistialue
POSIX-käyttöjärjestelmäkutsuja käyttäen; toinen aasinsilta
tiedostojen käsittelyyn (jaettu muistialue näyttäytyy ohjelmalle
ja muillekin tiedostona!)
koodit repossa (+krediitit alkuperäiselle tekijälle):
2016/esimerkit/l15/shm_msgclient.c
2016/esimerkit/l15/shm_msgserver.c
2016/esimerkit/l15/README_shm_example.txt
- Todetaan esimerkissä oleva kilpa-ajotilanne (korjaamisen voi tehdä
erittäin vapaaehtoisena, hieman vaativampana,
harjoitustehtävänä...; sigesim.c:n malliin olisi syytä myös
käsitellä TERM-signaali, jotta serveri osaa poistaa jaetun
muistialueen loppuessaan lopetussignaalin
johdosta. Oletuskäsittelijä ei voi tietää, että prosessi on
pyytänyt yhteisen muistialueen.)
- Katsotaan, että muistialue näkyy tiedostona hakemistossa /dev/shm
... POSIXin vaatima kauttaviivalla alkava nimi on vaan lisätty
Linux-toteutuksessa /dev/shm:n perään.
- Ja juu.. elä anna hakkerin tehdä tätä jaetulle muistillesi:
echo Hei vaan hei | dd of=/dev/shm/foo1423 bs=1 seek=4 conv=notrunc
- Telmitäänpä hetki tämän esimerkin ja tietoturvakysymysten äärellä,
ja varmistutaan että Ohjelmistoturvallisuus ja
Tietoverkkoturvallisuus ovat tarpeellisia jatkokursseja...
** Luento 16: I/O, kovalevy, tiedostojärjestelmä. Vuoronnusmenettelyjä, RT, skriptit
Kurssin viimeisen viikon startti. Mikä on tilanne?
- Vuoden 2016 "mallitentti" on julkaistu:
http://users.jyu.fi/~nieminen/kj16/tentti_itka203_2016-05-15_malli.pdf
katsotaan sitä tarkemmin keskiviikkona, kun otsikkona on mm.
"kertaus ja tärpit"
Tällä luennolla käydään vielä läpi luentomonisteen viimeisten
lukujen asioita, jotka ehtivät tenttiin. (Kysymyspaperit menevät
monistukseen huomenna). Loput jää sitten tulevaisuuden haasteeksi
itse kullekin.
- Demo 6 lyhyt esittely. Pittäis olla aika "läpihuutojuttu", jos
tähän asti ollaan kartalla.
- Demojen aikatauluista, ennen kuin tarvitsee kysyä: kaikki
pakolliset oltava tehty ennen kuin kurssista saa arvosanan.
Tentissä voi käydä yrittämässä tällä viikolla, vaikkei ole vielä
kaikki palautukset järjestelmässä. Vapaaehtoisia bonusdemoja ei
ole resursseja tarkastaa enää myöhemmin kesällä; se porkkana
olkoon voimassa 14 vrk. ensimmäisestä tentistä, eli 2.6.2016 asti.
Sitten katsotaan, mihin asti tänä vuonna ehditään... reilu tunti
aikaa...
Lisää tiedostonhallinnan käyttäjänäkökulmaa:
Esimerkki:
- Tiedostojen käyttöoikeudet rwx / ugo. Shell-ohjelma
chmod. Oktaaliluvut.
(HUOM: yliopistomme verkkolevyt eivät sisäisesti tue POSIXin
käyttöoikeusmääritelmiä; omat kokeilut kannattaa tehdä siis
esim. itka203-testi.it.jyu.fi -palvelimella, joka ei muutenkaan
ole kytketty verkkolevyyn, tai sitten jalavan tai halavan /tmp
-hakemistossa. Viimeksi mainitusta siivoa lopuksi
kokeilutiedostosi pois, etteivät jää muiden vaivoiksi
yhteiskäyttöiseen järjestelmään... kyllä /tmp kuulemma kait myös
siivotaan aika ajoin myös jonkinlaisella automaattivälineellä...)
Tiedostonhallinnan sovellusnäkökulma:
Esimerkki:
- Tiedostojen käyttöä POSIX-käyttöjärjestelmäkutsuilla ja C:n
alustakirjaston kutsuilla; tiedoston avaaminen ja luominen,
kirjoittaminen, sulkeminen. Käyttöoikeuksien asettaminen.
koodi repossa: 2016/esimerkit/l16/hellofile.c
Esimerkki:
- Oman "cat -apuohjelman" raakile; tiedoston avaaminen, lukeminen ja
kirjoittaminen tavu kerrallaan, sulkeminen C:n alustakirjaston
kutsuilla.
koodi repossa: 2016/esimerkit/l16/liit.c
Aasinsilta kohti tiedostonhallintaa ja tiedostojärjestelmiä muuttuu
oikeaksi sillaksi, kun käsitellään välissä vielä I/O -laitteiston
piirteitä, esimerkkinä kovalevy, joka soveltuu tiedon pitkäaikaiseen
säilyttämiseen tiedostoihin ja hakemistoihin organisoituna.
I/O ja Tiedostonhallinta käyttöjärjestelmätoteutuksessa:
- Tavoitteita: datan organisointi, osoitteistaminen, puumainen
hierarkia ("kansiot"). [kyseessä on todellisuudessa pikemminkin
suunnattu graafi eikä puu, koska hakemistoista voi olla ns. linkkejä
muihin hakemistoihin ja muissa hakemistoissa sijaitseviin
tiedostoihin. Puu on kuitenkin ehkä hyvä ensimmäinen analogia.]
- Käytettävissä olevat laitteet: prosessori, I/O -portit, laitteiden
aiheuttamat keskeytykset; rajapinnan takana hyvin erilaisia
laitteita
- I/O -ohjelmiston kerrosmainen rakenne: laiteriippumaton osuus,
laiteriippuva osuus.
- I/O -kutsun kulku ohjelmistokerrosten läpi (karkea yleiskuva).
- DMA.
Tiedostojärjestelmien toteutuksesta fyysiseen massamuistiin:
- kovalevyn rakenne
- lohkot muistissa ja levyllä; lohkot yleensä isompia kuin levyn
sektorit
- käyttöjärjestelmän yleiset tavoitteet (läpivienti, tasapuolisuus,
vasteajat jne.) voimassa myös I/O:n osalta. Lisäksi saatavuus- ja
säilyvyyskysymykset; vikasietoisuus.
- RAID
- käytännön penkaisua shellin kautta:
+ komennot ``df`` (POSIX) ja ``mount`` (ei POSIX), ``du`` (POSIX).
reunahuomio: Mistä tietää, mikä on POSIXia ja mikä ei? Tietysti
standardin tekstistä. Komento joko on siellä tai ei. Tietyn
tiedostojärjestelmän toiminta ei ole standardin vaan kunkin
käyttöjärjestelmän omien laajennosten varassa. Unixmaisissa
tiedostojärjestelmän kiinnittäminen hakemistopuuhun tapahtuu
kuitenkin usein mount() -järjestelmäkutsulla ja shellissä mount
-apuohjelmalla. Irrottaminen umount() -järjestelmäkutsulla ja
umount -apuohjelmalla. POSIX vetää siis määrittelynsä rajan
selvästi laiteriippumattoman ohjelmiston ominaisuuksiin
(ts. tiedostojärjestelmän ja massamuistien olemassaolo,
osoitteistaminen).
+ inode / POSIXin "sarjanumero" : komennot ``ls -i`` (POSIX) ja
``stat`` (ei POSIX).
- esimerkki: vanhan unixin tiedostojärjestelmän toteutuksesta
yleiskuva, inodet ja levylohkot, isot tiedostot hierarkkisena
lohkolistana
- journalointi: kirjataan ensin ylös, mitä levylle aiotaan kirjoittaa;
sähkökatkon sattuessa menetetään vain meneillään olleen kirjoituksen
tiedot, mutta tiedostojärjestelmän rakenne ei muilta osin
korruptoidu, koska kesken jäänyt kirjoitustransaktio voidaan
peruuttaa seuraavan käynnistyksen yhteydessä.
- levyoperaatioiden vuorontaminen on oma haasteensa. Internetin
ihmeellinen maailma kertoo meille paljon hakusanalla "disk
scheduling" (tieteelliset artikkelitietokannat kertovat tietysti
uusimpia tutkimustuloksia yleistiedon lisäksi)
Havainto: myös laitteita on vuoronnettava! Magneettisen kovalevyn
vuorontaminen on sidoksissa fyysisen laitteen ominaisuuksiin
(pyöriminen, lukupään sijainti) ja tiedostojärjestelmän
organisointiin levyn pinnassa.
--- tähän ehdittiin 2016. Loput ei tule tenttiin.
*** Lisäesimerkki -- kurssin mielessä kokonaisuudessaan liian syvällinen:
Kurssin opiskelijan harrastusprojekti: muinoisen rinnakkaisportin
keskeytyskäsittely.
- Tietoja portista: http://retired.beyondlogic.org/spp/parallel.htm
Tässäpä olikin hieno testi luennoitsijan omalle
tiedonhakukyvylle :). En voinut käyttää tähän kovin paljon aikaa,
mutta tässä ensimmäiset, ei välttämättä aivan oikeaan osuvat,
tulkintani:
- Jos ymmärsin oikein, laitteelle täytyy lähettää merkki,
ikäänkuin se olisi "printteri" (mitä se ei tässä tapauksessa
kuitenkaan ole:)). Sitten täytyisi tallentaa aikaleima hetkellä,
jolloin "ikäänkuin printteri" ilmoittaa keskeytyksellä, että se
on "tulostanut" edellisen merkin ja on valmis vastaanottamaan
lisää. Fyysisen laitteen luonteesta johtuen ei voi ennalta
tietää, millaisen ajan päästä tämä keskeytys tulee.
- Ensimmäisellä googletuksella tuli vastaan tällainen softa:
http://parapin.sourceforge.net/
- Tämä Parapin on ilmeisesti tehty Linuxin versiolle 2.6, jota ei
pahemmin tueta enää 2016. Ytimen rakenteessa voi olla tapahtunut
muutoksia, jotka edellyttäisivät softan porttaamista uuteen
versioon.
Seuraava perustuu ajatukseen, että Parapin tai vastaava toimisi
nykyisessä Linuxissa (tai käyttötarkoitus on sellainen, että
laitetta hallinnoivaan koneeseen voisi tietoturvallisesti asentaa
version 2.6).
Ohjelmiston dokumentaatiossa ensinnäkin on linkki selkeästi hyvään
johdantokirjallisuuteen:
- Rubini & Corbet: "Linux Device Drivers":
http://www.xml.com/ldd/chapter/book/ (ilmainen online)
http://shop.oreilly.com/product/9781565922921.do (ostoversio)
Jos esim. tuon Parapin-ohjelmiston ominaisuudet eivät riitä, niin
kirjan perusteella saanee yleiskuvan siitä, miten Linuxin
ajurijärjestelmä ja keskeytyskäsittelijät toimivat :), jotta voi
modata esimerkin perusteella oman ajurin.
Kyseinen Parapin -ohjelmahan on juurikin esimerkki
rinnakkaisporttia käyttävästä ajurista. Siinä näyttäisi kyllä
olevan lähes kaikki ominaisuudet, joita kysymyksen esittäjä
tarvitsee harrastusprojektissaan.
Parapinin voi äkkivilkaisun perusteella kääntää Linuxin ajuriksi,
joka toimii yhteistyössä normaalin "parport" -ajurin
kanssa. Keskeytyskäsittelijässä näyttäisi olevan callback-funktio,
johon ilmeisesti voi ajurin ylösajon kohdalla saada oman
C-aliohjelman ajettavaksi aina kun tietty rinnakkaisportti
keskeyttää. Keskeytyksen kohdalla voisi *ehkä* tehdä jotain
"quick-and-dirty" -tyyppistä, kuten::
static void rakentele_aikaleima_jotenkin(char *buf){...}
static laheta_porttiin_taas_uusi_operaatiopyynto_jotenkin(void *id){...};
void oma_koukkufunktio(int irq, void *dev_id, struct pt_regs *regs){
char[20] aikaleima;
rakentele_aikaleima_jotenkin(aikaleima);
printk(KERN_INFO "Laite sanoi tiks kellon ollessa %s\n", aikaleima);
laheta_porttiin_taas_uusi_operaatiopyynto_jotenkin(dev_id);
}
Ja sitten, teoriassa, jos tällaisen saisi pyörimään, niin ytimen
lokitiedosta voisi käydä ajoittain nappaamassa rivit, joilla lukee
"Laite sanoi tiks", tyyliin shell-komento ``dmesg | grep "Laite
sanoi tiks"`` ja jäsentää riveiltä aikaleimat.
Tai sitten tuo oma käsittelijä voisi tehdä jotain
hienompaa. "Oikea unixmainen ajuri" näyttäytyisi tietenkin
loppukäyttäjälle tiedostona, esim. "/dev/munlaite/tilanne", josta
käyttäjä voisi lukea tekstimuodossa aikaleimoista johdetut
yhteenvetotiedot (jotka ovat käsittääkseni harrastusprojektin
lopullinen käyttötarkoitus).
Kevyellä tai raskaalla toteutuksella joka tapauksessa tuossa
harrastuksessa joutuu lueskelemaan oppikirjallisuutta ja
esimerkkikoodia, että saa homman pelittämään :). Hieno harrastus
siis!! :)
TODO: Heläytetään löytynyt oppikirja ehkä myös luentomonisteen
lisälukemistolistaukseen.
-------------- tähän asti on tultu keväällä 2016 --------------
* Viime vuoden toteuma; lienee hyvä suunnitelma myös vuodelle 2016:
** Luento 17: Tarvittavat paikkaukset. Yhteenveto. Kertaus ja tärpit
Agendalla olisi:
*** Tomin terveisiä demoista:
- demot 1, 2 ja 3 mennyt hyvin ja ohjeaikataulussa:
+ demosta 1 läpi 137, hylkykertoja 26, syy yleensä "oudot
rivinvaihdot", jollaisia ei suoraviivaisesti ohjeiden mukaan
toimimalla oikein pysty tulemaan..
+ demosta 2 läpi 117, hylkykertoja 17, syy yleensä jokin
puuttuva tai erilainen tuloste kuin pyydettiin
+ demosta 3 läpi 108, hylkykertoja 4 (syy ympäristömuuttujan
puuttuminen)
+ demosta 4 läpi 70, hylkykertoja 26 (yleensä useita ongelmia;
pienillä on mennyt läpi, mutta vähintään merkin poistamisen)
* ei-kääntyviä ohjelmia tänä vuonna vain 2.
* varottava "1:llä ohi" virheitä.
* yksinkertaisuus on hyve.
* kynä ja paperi!
+ demosta 5 läpi 38, hylkykertoja 41 (pienillä mennyt läpi,
ts. noin 2-3 ongelmakohtaa läpi, useampi -> ei vielä läpi)
* selkeitä ongelmia ymmärryksessä on, jos esim. kuvittelee
paikallisten muuttujien sijaitsevan koodialueella tai
toisin päin.
* suurin muistiosoite, joka on taulukolla käytössä?
* bitit ja tavut sekaisin? "tavu==8 bittiä" Montako tavua
varattu tilaa 6:lle 8-tavuiselle int:lle? Ei varmaan 6*8*8
tavua!
* kummallisiakin lukuja, joille Tomi ei keksinyt selitystä..
* muistin olemuksesta ei vielä ole selkeää, yksinkertaista
mielikuvamallia.
* Missä muuttujan "samoja" arvo oli aluksi?
+ demosta 6 läpi 39, hylkyjä 6 (hyväksymisperusteena, että
ohjelma vähintäänkin toimii niinkuin tehtävänannossa on
- Hyvin harva on käyttänyt hyödykseen Tomin varattavia
ohjauksia. Toivottavasti sessioista on kuitenkin ollut hyötyä.
*** Käsittelemättä jäivät edistyneempi vuoronnus ja skriptaus
Vuoronnuksesta ja vuoronnusmenettelyistä lyhyesti:
- yksinkertaisimmillaan FCFS (first come first serve), "eräajo"
- moniajossa yksinkertaisimmillaan Round-robin
- prioriteetit, esim. prioriteettikohtaiset kiertojonot;
monimutkaistaa vuorojen jakamista - tarvitaan monipuolisempi
vuoronnusalgoritmi; vaarana mm. nälkiintyminen (matala prioriteetti
ei ehdi saada juuri lainkaan aikaa)
- dynaamiset prioriteetit
- reaaliaikajärjestelmät ja -vaatimukset, prioriteetit ja
pre-emptiivisyys, watchdogit
- kompromissit esim. vasteaika vs. throughput
- mikroydinmallissa käyttöjärjestelmän omien säikeiden vuoronnus ja
prioriteetit vaikuttavat kokonaisuuden toimintaan
Eräs IPC:henkin liittyvä yksityiskohta:
- Käyttöjärjestelmän suorituksesta ja moduulijaosta; kernel mode
vs. user mode.
- Käyttöjärjestelmän ajonaikaisesta rakenteesta: monoliittinen
vs. microkernel
+ vuoronnus, kutsurajapinta ja IPC-menettelyt tarvitaan
käyttöjärjestelmätilassa, mutta muut palvelut voivat tapahtua
joko käyttöjärjestelmätilassa tai käyttäjätilassa;
palveluprosessit voivat kommunikoida ja synkronoida toimintonsa
IPC-menettelyjen kautta.
+ Käytännössä yleensä hybridi, jolla haetaan kompromissia
(mm. modulaarisuus, turvallisuus ja toimintavarmuus vastaan
suorituskyky).
- Uusinta tutkimusta aiemmista aihepiireistä? Katsotaan vähän vaikka
WoKista ja ACM digital librarysta hakusanoilla "deadlock", "process
synchronization", "microkernel" (tai muita tähän mennessä nähtyjä
avainsanoja).
- Yksi esimerkki microkerneliksi suunnitellusta ytimestä on "Plan 9
from Bell Labs": http://plan9.bell-labs.com/plan9/
Johdattelua skriptaukseen:
- katsotaan läpi muutama etäkäyttökoneelta ja/tai netistä löytyvä
skripti erilaisiin tarkoituksiin, esim.:
+ ohjelman käynnistäminen tietyssä ympäristössä tai tietyin
lisäargumentein, esim. yliopiston palvelimilla komento "c99" on
skripti, joka tekee esivalmisteluja ja käynnistää varsinaisesti
gcc -kääntäjän.
+ järjestelmäpalveluiden käynnistys/pysäytys, kokonaisjärjestelmän
ylösajon operaatiot; esim. yliopiston palvelimilla skripti
/etc/rc.sysinit tapahtuu käynnistyksessä; mm. yhdistää
hakemistopuuhun tiedostojärjestelmiä, aloittaa heittovaihdon ym.
+ monisteessa luetellaan useita muita shell-sovelluksia
- shellin perusrakenteita (demotehtävän 6 tasolla); esimerkkinä c99:n
käynnistysskripti, jossa on muuttujia, for-silmukka, case-ehdot,
tulosteen ohjaus virhetulosteeksi.
*** Mitä siis ehdittiin tänä vuonna
Yleiskuva luentomonisteeseen - luvut 1-12, 14 ja 15. Koodiliitekin on..
*** Sitten kertaus ja tärpit!
Tentin kysymystyypit ja yleinen rakenne julkaistiin noin 5 vuorokautta
ennen tätä luentoa.
Yleiskuvaa:
- kysymyksiä on muutamaa eri tyyppiä: väittämiä, termien yhdistämistä
niitä kuvaileviin määritelmiin tai
ominaispiirteisiin. Esimerkkiskenaarioihin tai mallikoodeihin
perustuvia väittämiä ja "mikä on lopputulema"
-tyyppisiä. Vastauksena joka kohdassa on kirjain, järjestetty jono
kirjaimia tai lukuarvo.
Kysymyksissä pitää olla tarkkana, koska jokainen sana vaikuttaa
luonnollisessa kielessä ja jokainen merkki vaikuttaa
ohjelmointikielen syntaksissa!
Alkuperäisessä, muotoilemattomassa mallitentissä on kysymysten
lisäksi mallivastaukset sekä pohdintaa.
- alkupuolella erillisiä osaamistavoitteita on useampia, joten
aihepiirit saattavat vaihdella enemmän tenttikerrasta toiseen.
- on myös "kestotärppejä" eli aihepiirejä, joista tullaan kysymään
joka tentissä (joskin eri kysymyksiä ja mahdollisesti tahallaan eri
tavoin toimivan esimerkin kanssa, joten mallivastausten opettelu
ulkoa ei auta, vaan koodien ja algoritmien toiminta pitää ymmärtää):
+ erityisesti shell-komentojonot, minish-toteutus,
assembler-ohjelma, pino ja aktivaatio debuggerissa, sivutaulut ja
osoitteenmuunnos.
- Tehtävissä tarkoituksella "harhautuksia", joten vastaaminen
edellyttää ymmärtämistä ja annetun esimerkin tarkkaa läpilukua.
Ei muuta kuin onnea (...eipäs kun osaamista) -- tenttiin!
Keskustelua, jos aikaa on!!
* Tänä vuonna (2016) ei ole allokoitu luentosalia tentin jälkeen kuten viimeksi:
** Palauteluento ekan tentin jälkeen (vapaaehtoinen/täydentävä)
Koska salia ei ole, tämä tullee nyt vaan meilitse, kunhan ensimmäisen
tentin arvostelu on tehty.
*** Agenda:
- Arvio vastauspapereihin kirjatuista ja jälkikäteen ilmoitetuista
kommenteista kysymyksiin liittyen. Alustavat kommenttini niistä,
ennen kuin ehdin meditoida asian ympärillä enemmän.
- "Vapaa sana" -vastaukset (anonymisoituina) ja omat kommenttini
niistä.
- Yleistä palautetta demojen tarkastuksessa havaittujen ilmiöiden
pohjalta (pääasiassa tulevia opintoja ja alalla toimimista
silmälläpitäen)
- Kysymyksiä, kommentteja, keskustelua.
*** Sähköpostilistalla esittämäni toimintasuunnitelma:
Kysymysmuoto oli uusi, ja silloin on "bugien" riski suuri. Saa nähdä,
miten tässä käy.. että onko sitä hommaa nyt enemmän vai vähemmän kuin
avoimissa kysymyksissä, ja saadaanko järkevän näköistä
arvosanajakaumaa. Mikäli arvosteluperusteita täytyy justeerata,
tehdään muutokset tietenkin opiskelijan eduksi, jos niitä päädytään
tekemään. Ei ollut vielä lupaus, ennen kuin vastausten kokonaisuus ja
koko populaation arvosanajakauma on selvillä.
113 perinteisen "esseetentin" tarkastaminen kestäisi itselläni useita
työpäiviä, missä ajassa luultavasti ehdin suorastaan tekemään
automaattisen tarkistimen, johon [tämänkertaisen tenttimuodon]
vastaukset voi syöttää. Optista lukijaa ei (vielä tässä
vastausmuodossa) pysty käyttämään, mutta pikaisen testin perusteella
yhden vastauspaperin manuaalinen syöttäminen kestää 30 sekuntia, mikä
on kokonaisuuden kannalta olematon aika. Sieltä saapi sitten nähtyä
myös kysymysten osalta, onko jokin ollut selvästi vaikeampi /
mahdottomampi kuin jokin toinen.
*** Arvio tavoista, joilla arvostelua korjataan tarvittaessa:
- Kysymyksen poistaminen arvostelusta kaikkien osalta ei tarkemmin
ajatellen ole oikeudenmukaista. Monitulkintaisuus on varmasti
hienovaraisissa nyansseissa, joita ei ole tullut ajatelleeksi
kysymyksen tekijä, eikä luultavasti suurin osa
vastaajistakaan. Olisi paha, jos suurimmalta osalta kumoutuisivat
pisteet tapauksessa, jossa monitulkintaisuuden havaitseminen vaatii
syvällisempää eforttia.
Miten sitten voisi toimia? Tämän hetkinen suunnitelmani:
+ Moniselitteiseen kysymykseen hyväksytään kaikki oikeiksi
tulkittavat vastaukset, +0.5 pistettä
+ Muissa kuin väittämäkysymyksissä ei kuitenkaan hyväksytä
vastauksia, jotka ovat tulkinnasta riippumatta vääriä (niistä
edelleen miinuspisteitä)
+ Tyhjä kohta, jossa on mainittu moniselitteisyydestä, tulkitaan
oikeaksi vastaukseksi, koska löytyy ymmärrystä osoittaa
monitulkinnallisuus. Tästä +0.5 pistettä.
+ Tyhjä kohta, jossa ei ole mainittu moniselitteisyydestä, tulkitaan
edelleen ohitetuksi. Edelleen 0.0p.
Uskoisin, että näin (1) ei rokoteta ketään turhaan, (2) ei vähennetä
pisteitä tyypeiltä, jotka ovat luottaneet kysymykseen omana
supertärppinään (3) ei myöskään palkita "tuulituloksella" niitä,
jotka eivät ole osanneet vastata suuntaan saati toiseen.
Toimintamalliehdotusta saa kommentoida. Lopullinen arvostelu tapahtuu
automaattisesti; tieto perustelun olemassaolosta kirjataan
arvosteluskriptiin.
(sanoinko skripti? juu, samalla python-skriptillä tullaan
arvostelemaan, millä kysymykset on generoitu
kysymyspankista... pittää vaan liittää tietorakenteisiin vielä
lippuattribuutti, oliko kysymys havaittu
huonoksi.. kysymys.isBadQuestionOMG())
*** Tentin osallistujien esitykset monitulkintaisiksi kysymyksiksi:
Mahdollisesti tai todennäköisesti arvosteluun vaikuttavia huomioita:
- Tehtävä 1: Tapahtui reaalimaailman "off-by-one" -virhe.. [luennolla
sanoin muuten "one-off", joka on tietysti väärä sana tähän
tarkoitukseen. Off-by-one on oikea termi...] olin heti niin
tyytyväinen ensimmäiseen kysymykseen, että sitä en juurikaan
ajatellut enää uudempaan kertaan, vaan tarkka läpikäynti lähti
kysymyksestä 2, koska "se ensimmäinenhän on jo varmasti OK, kyllä mä
sen tiedän". No ei se ihan ollut. Opiskelijoiden havaintoja:
+ "moniselitteinen, koska ei voida tietää puhutaanko koko
lähdekoodista vai tarkoitetaanko vain sitä, että prosessin omat
säikeet toimivat prosessin koodin sisällä, sillä ne eivät
välttämättä käytä koko koodia"
+ "A, jos siis tarkoitetaan sitä koodia ohjelmoijan kirjoittamana
tekstipötkönä, ei sitä, ettäkö säikeet suorittaisivat aina samaa
kohtaa koodista. Tässä mahdollinen monitulkinnallisuus?"
+ "Valtavan epämääräinen sana 'koodi'"
Mielessäni tarkoitin koko ajan "prosessin koodialue on sen säikeille
yhteinen", enkä tulkinnut tehtävänantoon päätynyttä tekstiä siten
kuin se oli ("prosessin koodi on sen kaikille säikeille
yhteinen"). Siis tuo "koodi" voi olla paljon kaikkea: lähdekoodi
(hyvin todennäköisesti eri lähdekoodi jokaisella säikeellä),
käännetty binäärikoodi (jossa todennäköisesti eri osio jokaisella
säikeellä), prosessin virhekoodi, salauskoodi..
- Tehtävä 7: Kysymyksenasettelu meni pieleen, joten arvostelu vaatii
tältä osin jonkin oikeudenmukaisen korjauksen. Havaintojen yleiskuva:
+ Esimerkissä menin ja sanoin että skenaariossa on 10
intensiivisesti laskevaa sovellusta. Nämähän pyörähtää 50Hz
kellolla läpi 5 kertaa sekunnissa jokainen. Väliin mahtuu myös
satunnainen muu prosessi viimeistään 0.2 sekunnin sisällä,
vaikka se tulisi kiertojonon perältä. Ei tämä nyt ihan
megaluokan viive olisi ihmisen näkökulmasta. Eri asia olisi
reaaliaikajärjestelmä, jossa on pakko kelata jonoa
nopeammin. Mutta tällaista ei nyt ollut spesifioitu tehtävän
esimerkkiskenaariossa.
+ lisäksi sanamuoto voisi olla "painottaa vähän" tai "vähän
laskentaa vaativia". Luonnollinen kieli on ikävästi
moniselitteistä; onneksi on ohjelmointikielet syntakseineen :)
Alustava suunnitelma siis, että A, B ja "perusteltu tyhjä"
hyväksytään kaikki oikeina vastauksina (+0.5p). Tyhjä ilman
perustelua normaali 0.0p
- tehtävät 21--22: Tässä on muutaman opiskelijan kanssa keskustelu /
väittely kesken, että oliko kyseessä oikeasti osaamistavoitteita
mittaava kysymys vai "liian paha kompa" tiedostopäätteestä .tex tai
sen puuttumisesta johtuen. Jonkinlainen ratkaisu tästä tulee, mutta
toistaiseksi auki.
Mahdollisesti on höllennettävä väärän vastauksen miinuspisteitä
tämän osalta. Mutta tyhjäksi tätä ei varmasti ole jättänyt kukaan,
jolla oikea osaaminen löytyy. Huolimattomuus on sitten asia
erikseen, ja pittää pohtia, kuinka paljon sitä sitten saisi sallia.
- Tehtävä 28: Tapahtui perinteinen "viime hetken tarkennus", joka ei
ollut loppuun asti harkittu. Note to self: älä tee viime hetken
tarkennuksia. Tarkkaavaisen opiskelijan havainto:
+ "Mahdollinen monitulkinta: ohjelmakoodissa sem.arvo on kurssin
mallin mukaan kokonaisluku (joka siis voi olla etumerkillinen
kuten koodissa on 'if (sem.arvo <= 0))', mutta todellisuudessa ei
arvo koskaan laske pakkasen puolelle. Ei voi olla vaikkapa '-2'
vapaata tai täyttä paikkaa.
Näin se on. Toteutus voisi antaa semaforin arvon mennä pakkasen
puolelle, jolloin sen itseisarvo tarkoittaisi jonottavien prosessien
määrää.. Tämä ajatus nyt ei ollut itsellä mielessä, kun "tarkensin"
tehtävänantoa viime hetkellä. Uusinnoissa tämä väite tulee muotoon,
jossa etumerkistä ei puhuta.
Tällä kertaa tässäkin hyväksyttävä A ja B sekä kommentoitu tyhjä.
- Tehtävä 29: Edellisen kohdan vuoksi mahdollisesti myös
moniselitteinen. Tutkitaan ennen kuin hutkitaan.
- Tehtävä 45: En vielä tiedä toimintamallia, ennen kuin nähdään kaikki
vastaukset. Opiskelijan havainto:
+ "B, koska käyttäjä voi itse määrittää tiedoston nimen"
Nythän on niin, että voi määrittää.. mutta tiedostoon voi määrittää
useita nimiä ns. kovina linkkeinä. Asia on mielestäni kyllä
kirjoitettu auki aika hyvin monisteen nykyiseen versioon. Samoin se,
että nimi ei ole osa tiedoston sisältöä eikä myöskään i-solmun
sisältöä. Itse asiassa monisteen lopullisessa versiossa on
suorastaan kursiivilla (harvoissa ja valituissa paikoissa käytetty
tehokeino!) seuraava täsmällinen ilmaisu: "tiedoston nimi määräytyy
hakemistotiedostoon kirjatun merkkijonon perusteella!"
Voi olla, että evidenssi ei tule riittämään tämän tehtävän
arvostelun muuttamiseen.
Havaintoja, jotka eivät välttämättä aiheuta toimenpiteitä:
- Lukuisia yksittäisiä havaintoja; erityisesti sellaisten
ääritapausten pohdintaa, joihin asti johdantokurssilla ei
päästä. Olin jo aikeissa ennen tenttiä meilata, että "elvistely on
sallittua, jos sille on oikea osaamispohja olemassa". Tulen käymään
näiden muutamien "Agoran elvisten" tiuhaan kommentoidut
vastauspaperit läpi erikseen, ja jos kommentit ovat tarkoin
analysoituna valideja niin antaa mennä vain... Vastauspaperien
yleiskuva (ilman tarkempaa tarkastelua) voisi viitata siihen, että
nämä ovat osaamisensa aiemmin hankkineita, joiden arvosanat
painottuvat yläpäähän joka tapauksessa.
Tämä sinänsä miellyttävä "gurujen" kanssa operointi ei vaikuta
johdantokurssin tietojen pohjalta tehtyihin vastauksiin.
*** "Vapaaehtoinen vapaa sana" -kysymyksen vastaukset:
- "Varsin selkeä kurssi. Osaamistavoitteet selkeytti ja mallitentti
helpotti varsinaiseen tenttiin lukua, kun näki vähän sokeita
pisteitään. Lisäksi se, että näki kysymystyypit ennakolta helpotti
ja nopeutti tenttiä. Ihana tavoite: opiskelija *uskaltaa* ja osaa
käyttää selliä. Siinä on pieni kynnys, kyllä."
Kiitos positiivisesta palautteesta. Voin kertoa, että mietin
tavoitteita tarkoin, ja tuo "uskaltaa" on olennainen osa, vaikka
mielestäni tärkeintä kyseisessä tavoitteessa onkin "aiheuttamatta
vaaraa omille tiedoille tai häiriötä muille käyttäjille tai
järjestelmälle" :)
- "Harmi kun kaikki mielenkiintoinen ja tärkeä tiivistyi n. 5
viimeiseen luentoon. Pehmojohdanto oli parasta viihdettä vähään
aikaan. Luennot aina yhtäaikaa eikä jaksanut käydä siksi
paikalla. Kiva kun demoilla ei kovaa kiirettä."
Kiitos rakentavasta palautteesta, jossa oli positiivisiakin
osioita :). Itse olen sitä mieltä, että alusta lähtien kaikki oli
tärkeää. Mielenkiintoisuus on subjektiivista. Omasta mielestäni
alkupuolen asia on huikean mielenkiintoista, mutta kuten monisteen
johdannossakin totean, henkilökohtaiset mielenkiinnon kohteet
vaihtelevat varmasti. Tarkoitus oli, että alkupuolella tulisi
tekninen pohja ymmärtää ilman suurempaa käsienheiluttelua
loppupuolen asiat, joissa ns. "korjataan hedelmät" (termi, jota joku
matematiikan luennoitsija aikoinaan käytti siitä, kun alkupuolen
teoreettisilla tuloksilla aletaan viimeisillä luennoilla tehdä
jotakin hyödyllistä :))
Pehmojohdanto ilmaantui viimevuotisen yksittäisen palautteen
perusteella, ja sen on tosiaan tarkoitus olla
viihteellinen. Tulevaisuudessa siirrän sen ehkä kuitenkin
liitteeksi, jolloin pääteksti menisi ensimmäisillä sivuilla suoraan
tekniseen asiaan.
- "Vaikeata on, kun tulee miinuspisteitä. Kurssin alussa olleet demot
olivat liian helppoja, niin kuljin vähän löysin rantein. Pistä
seuraavalla kerralla assembler-jutut heti ja skriptit lopuksi, niin
lähtee oikeammalle raiteelle.
Kurssin asiasisältö on kokonaisuutena OK ja materiaali oli hyvää.
Sellaista toivoisin, että jos keräsin nyt vahingossa liikaa
miinuksia, enkä pääsekään läpi, niin voisitkohan tiedottaa
epäonnistumisesta heti? Muuten en ennätä valmistautua uusintaankaan.
Mukavaa oli, että tenttitilaisuudessa on kunnolla aikaa."
Kiitos jäsennellystä palautteesta, hyvistä huomioista ja
kohteliaista lisäyksistä :).
Miinuspisteiden osalta on ehkä katsottava kaikkien 113 tenttijän
tulokset ja tehtäväkohtaiset pisteet, ja mietittävä, onko se -0.5
pistettä liikaa arvaamisen kitkemiseksi. Väittämätehtävissä
odotusarvo arvaamalla olisi 0, ja nyt kun on myös "yhdistä lauseita"
ym., joissa oikean vastauksen arvaustodennäköisyys on mallia 25%,
niin arvaamisen odotusarvo oikeastaan on negatiivinen.
Voi olla, että pienemmälläkin miinustuksella saataisiin
minimaaliseksi riski päästä arvaamalla läpi. Maito on tietysti jo
maassa siinä mielessä, että arvosteluperuste (-0.5 väärästä) oli
tiedossa tenttiä tehtäessä, joten jokainen tenttijä on tehnyt oman
riskiarvionsa sen tiedon varassa. Tällä perusteella tätä ei ehkä
uskalla jälkikäteen enää muuttaa tämän kurssikerran
osalta. Katsotaan ja analysoidaan tulokset, ja tehdään sitten
toimenpiteitä.
Erityisesti katsotaan, että arvosanajakauma käy järkeen. 113 hengen
populaatio on uskoakseni riittävän suuri arvioiden tekemiseen ja
vertaamiseen aiempiin kurssikertoihin, vaikka kysymykset nyt
erityyppisiä olivatkin.
- "GNU/Linux; kernel ja käyttis ovat eri asia, kernel ei yritä
toteuttaa POSIXia"
Hyvä täsmennys. Asiahan on selvä, mutta on saattanut jäädä sanomatta
juuri noilla sanoin. Kirjataan se jatkossa materiaaliin noilla
sanoin. Uskon kuitenkin, että tällä kurssikerralla saatiin riittävän
useaan otteeseen käsiteltyä kirjastojen kerroksia ja ytimen
kutsurajapintaa, joten kokonaisuuden jälkeen pitäisi olla kyllä
selvää, mihin kirjasto loppuu ja ydin alkaa, ja mihin kerrokseen
POSIXin toteuttaminen sijoittuu.
HUOM: Jos muistat laittaneesi tenttipaperiin jotakin, mitä tähän ei
ollut kaivettu, niin ilmoita!! Koska olen mielestäni ottanut kaikki
papereissa olleet kommentit tähän.
[Seuraavat löytyivät tarkemmassa läpikäynnissä luennon jälkeen]:
- "Tulin tähän tenttiin koska olin unohtanut poistaa ilmoittautumiseni
ajoissa. Tarkoitus oli tulla tekemään koe vasta 12.6., eli tähän
tilaisuuteen ei oltu valmistuttu. Ompas käsiala huonontunut kun
tässä opinahjossa on vuoden viettänyt."
Propsit siitä, että tulit paikalle tenttitilaisuuteen, johon olit
ilmoittautunut! Onnea ja osaamista seuraavaan yritykseen
12.6. Käsiala kannattaa pitää kunnossa. Pidemmän päälle joutuu melko
todennäköisesti draftailemaan suunnittelukaavioita, mindmappeja ynnä
muuta, joista kavereiden täytyy saada selvää. Alussa ei vielä ehditä
tuohon opinahjossa, kun on niin paljon koodattavaa :).
- "Tentti oli hyvä."
Noh.. kiva että ainakin joku tykkäsi :) Katsotaan onko tilanne sama
vielä arvostelun jälkeen...
- "Unohdin lukea tenttiin :)"
- "Täytyy vielä vähän treenata..."
- "Valitettavasti tälle kurssille ei jäänyt aikaa, mutta opiskelen
varmaan kesällä ja tentin heinäkuussa :)
Uusinnassapa sitten!
- "Hyvä kurssi. Haastava verrattuna moneen ja taitaa uusintaan tentti
mennä. You are not prepared!"
Kiitos positiivisesta palautteesta. Haastaviahan kaikkien kurssien
pitäisi olla, eihän niissä muuten oppisi uutta :). Next time you'll
be prepared!
- "Tuuletetaan! (toivottavasti tarkastuksen jälkeenkin on syytä siihen)
Tutkitaan ennen kuin hutkitaan. Kyseisen palautteen antaja voi
kylläkin tuulettaa vähintään selkeää läpipääsyä vastausrivinsä
yleiskuvan perusteella. Mallia monta oikein, eikä yritelty arvailla
liikaa.
- "Ei voi mennä läpi. :)"
Hyvä, jos tilanne kuitenkin hymyilyttää hymiön verran :). Uusinnassa
sitten!
- "Monivalinta on yllättävän hyvä tenttimuoto; vääristä vastauksista
tosin rokotetaan ehkä turhan ankarasti, vaikka virhe ajattelussa voi
olla pieni. Kiitokset hyvästä kurssista!"
Kiitos positiivisesta palautteesta sekä perustellusta kritiikistä!
Kyllähän se näin jälkiviisaasti ajatellen on rankka rokotus tuo -0.5
pistettä. Nyt kun sitä ei etukäteen osattu arvata, niin tämän kanssa
on elettävä vielä kesän kaksi uusintaa (ks. perustelut
yllä). Populaation tasolla skaalataan kokonaispisteytystä kaikkien
osalta tarvittaessa, jos tarvetta ilmenee.
- "Mukava kurssi, paljon asioita jotka on hyvä tietää. Tavallaan
hyötyy ja tavallaan kärsii demojen vapaammasta aikataulusta
(soveltuu kyllä hyvin kiireisemmän opiskelijan aikatauluun).
Kiitos positiivisesta palautteesta ja rehellisestä mielipiteestä
aikataulutuksesta. Deadlinet ovat pohdituttaneet paljon vuosien
varrella, ja jokaisessa ratkaisussa on hyviä ja huonoja puolia.
- "Muistutti niin paljon mallitenttiä, että tuntui helpolta. Kohta 28
meni arvailuksi, muut kuvittelen tietäväni."
Näin oli tarkoitukseni, että malliin tutustutaan ja sitten tuntuisi
helpolta. Mutta toivottavasti olit myös tarkkana, koska tehtäviä oli
muutettu malliin nähden! Automaatti sen aikanaan kertoo.
Tehtävää 28 ei olisi kylläkään välttämättä kannattanut arvata :)
Katsotaan nyt, miten kyseisen tehtävän arvostelun kanssa käy
ylipäätään (ks. palauteluennolla läpikäydyt huomiot ylempänä).
- "Kurssi oli loistava, mutta Ohjelmointi 2 ja vaihtoon hakeminen
söivät voimavaroja suoritukselta. Tehtävät olivat paras
osa. Erityisen selkeä opastus ja harjoitteet vähensivät pelkoa
uudelta unixkäyttäjältä"
Kiitos positiivisesta palautteesta. Olen tehnyt paljon töitä
mm. mainitsemiasi piirteitä kohti eli selkeää opastusta ja
pelkokertoimien pienentämistä uusien teknisten asioiden lähestymistä
kohtaan. Toivottavasti vaihtokohde löytyy! Vaihtoon lähteminen on
erittäin suositeltavaa. Muista sopia vaihdossa tehtävistä kursseista
*etukäteen* oman opintoneuvojan kanssa :)
- "Pitäisi katsoa luentotallenteet ainakin kaksi kertaa lisää ennen
kuin tuntisi osaavansa."
Niitä voi onneksi kotona kelailla tylsien osien yli ja katsoa
tuplanopeudella tai hidastettuna tarpeen mukaan :)
*** Yleistä palautetta demoista
Nämä löytyvät demosivustolta (ei varsinaisa spoilereita niille, joilla
demot on vielä kesken):
http://itka203.it.jyu.fi/pages/geneerinen_palaute_opiskelijoille_2015.rst
Käydään läpi luennolla, jos ehditään.