-*- coding:utf-8 ; mode:org -*-

Käyttöjärjestelmät, kevät 2018.

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 2018:

** Luento 1: Aloitus, yleisinfo ja suoritusvaatimukset

Luennon päätavoite on kuvailla kurssin tekniset vaatimukset ja muu
perusinfo. Varsinaiseen asiaankin ehdittiin alustavalla tasolla aivan
lopuksi.

- Esittelyt: opettajat, opiskelijat, opiskelijoiden pääaineet
  (Millainen jakauma 2018? Valtaosa tietotekniikka. TJT hyvänä kakkosena.
  Löytyy myös ainakin fyysikoita. Opiskelijoiden
  pääasialliset käyttöjärjestelmät omassa käytössä (pöytäkoneet,
  tabletit, älypuhelimet)?

- Perinteinen ryhmäkuva vuosia harjoitellulla
  koreografialla... Kaikki, mitä "koreografiassa" nähdään, liittyy
  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ä: 

    Demot on julkaistu toistaiseksi HTML-muodossa (linkki kurssin
    etusivulta).

    Seuraavalla luennolla tulee tarkempi 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!

    Palautusjärjestelmää ei ole vielä ehditty testata tälle vuodelle,
    joten teknisestikään tänään ei ole vielä hyvä päivä palauttaa.

    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!]

  * "Palopuhe" demojen tekemisestä. Olennaisimmat kohdat aiemmilta
    vuosilta havaittuna:

      + 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ä monesta syystä,
        (mukaanlukien puoliautomaattinen rekisteröinti Korppiin),
        joten ohjeet on tosiaankin luettava, jos mielii saada tehtävät
        läpi!

  * Aikataulut ja salit: Korpissa. (Päivittyy kurssin alkuvaiheessa.)

    Ryhmäohjauksia mikroluokissa kenties ainakin käyntiin
    pääsemiseksi. Aikatauluista tiedotetaan.

    Luennot ovat iltapäivästä - tehdään yhteinen ratkaisu, pidetäänkö
    niissä tauko vai jätetäänkö tauko pois ja lopetetaan aiemmin: TODO

  * 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ä.

- Etenkin etäopiskelijoille, mutta myös muille, meillä on käytössä
  kaksi vertaistukikanavaa: yksi virallinen ja yksi epävirallinen:

    * Sähköpostilista itka203_kevat2018_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 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. (IRC-palvelu ei ole
      Jyväskylän yliopiston tukema palvelu, eikä se ole kurssin
      tiedotuskanavana virallinen. Hyödyllinen vertaistukikanava se
      on, ja irc.cc.tut.fi -palvelin ottaa vastaan yhteyksiä niistä
      JY:n koneista, joilla meidän demot tehdään)

      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/

Hieman ehdittiin jopa itse asiaankin luennon lopussa:

- Demo1:n ohje, tavoitteet sekä tarpeelliset varoitukset ohjeen alussa.

- Tekemisen saa aloittaa, kun on sisäistänyt varoitukset!!

** Luento 2: Luentomuoto, 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: 

- Demojärjestelmän käyttöönotto etenee, ilmoitetaan kun on online.

- "Open labrapäivä" -konseptin selitys; ensimmäinen sessio torstaina
  8:30-12 mikroluokassa MaD206.

Pääteyhteys ja siihen liittyvät asiat:

- Luentomuoto ja kurssin työkalut alusta alkaen ja esimerkit näyttäen:
  pääteyhteys, bash-shell ja tekstipohjaiset työkaluohjelmat.

- Näytään, mitä tapahtuu kulissien takana ennen luentoa:
  pääteyhteys, KiTTY-asetukset, screen, komentojen antaminen.

- UNIX-käyttäjätunnuksen aktivointi salasana.jyu.fi -palvelussa.

- Miten lähdetään tekemään demoa 1: Alkuvaroitukset (uudestaan) ja
  toisaalta rohkaisu.

- KiTTY -pääteohjelma (asennettava itselle, jos haluaa tehdä kotoa
  käsin; tehtävien palauttaminen kotoa käsin tulee vaatimaan
  lisukkeen, josta infoa ensimmäisen demotehtävän palautusohjeessa).

- 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

- Komento alussa, sitten argumentit. Kaiken näytetyn tulee sujua
  viikon päästä jokaiselta mikroluokassa tai kotona ilman
  pienintäkään vaikeutta. Demot 1&2 opastavat alusta lähtien.

- Screen-ohjelman käyttöesimerkki

- Lopussa spoileria demo 1:een, useless use of echo ym.

- kill ja kuinka selvitä "nolosta ikuisesta silmukasta".

- Ja sitten vaan tekemään!

** Luento 3: Yleiskuvaa, tavoitteita, esitietoja

Päivän päätavoite on saada omatoiminen lukeminen ja tehtävien
tekeminen käyntiin. Seuraava luento on vasta kahden viikon päästä
(välissä pääsiäistauko).


- Tilanne demojärjestelmän suhteen:  Näyttää hyvälle, alustavat
  kokeilut ovat osoittaneet järjestelmän toimivaksi ainakin, kun
  sitä käyttää nätisti.  Demotehtäville tulee vielä luoda
  palautusmekanismi, puhdistaa kokeilut ja sitten järjestelmä
  julkaistaan.

  HUOM: Palautuslaatikon puute ei edelleenkään vaikuta mitenkään
  demojen tekemiseen - ainoastaan palauttamiseen ja tarkistamiseen. On
  tärkeää aloittaa demot, jos ei vielä ole sitä tehnyt!!

- Huomatkaa open labrapäivä ja Koodaamo

- Ohjeellinen "deadline" noin 1 tehtävä / viikko.
  
Sitten kohti itse asiaa:

- Mainintoja oppikirjoista, esim. OSTEP http://pages.cs.wisc.edu/~remzi/OSTEP/

- Kurssimonisteen luonne. HUOM: Nyt alkakkee sukeltaa monisteeseen!

- Ensimmäinen vilkaisu "jyrkempään" taustamateriaaliin:
  AMD64-manuaalit, POSIX, C99 spesifikaatio. Mitä ihmettä ja miksi?

- Miten homma jatkuu demossa 2: Screen-ohjelman käyttely. Demoissa
  tulee paljon muutakin. Ajatuksella kannattaa tehdä, mutta aloittaa
  pian.


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.

- Esitietojen varmistaminen: Mitä ohjelmointi 1 -kurssilta pitäisi
  muistaa ( ks. https://trac.cc.jyu.fi/projects/ohj1/wiki/sisallys )

- 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ä).

HUOM: Hetimiten demon 1 & 2 ääreen ja lukemaan monistetta, jos ei olla
jo näissä menossa!!

** Luento 4: Tietokonelaitteisto, tiedosto, kääntäminen, konekieli, debugger

*** Infoa keväälle 2018:

- Demojen palautusjärjestelmä viivästyy pienen tietoturvateknisen syyn
  vuoksi. Demoja saa ja pitää edelleen tehdä - seuraavaksi demo 3.

Jonnen ja minun YPE15-opetuskokeilut ("save-the-date"):

- Mikroluokassa tiistaina 17.4.2018; teemana C-kieli.

- Osallistumalla kuittaantuu pakollinen demo 4

- Keskenään identtiset sessiot - voit ilmoittautua Korpissa vaikka heti.

- Muoto on parityö. Parit ratkotaan paikan päällä siten, että
  jokaiselle tulee mahdollisimman vähän ennalta tuttu pari.

- Jos et pysty tulemaan paikalle tai suoritat kurssia eri aikaan,
  tarjolle tulee korvaava itsenäinen tehtävä demo 4:n
  suorittamiseksi. Tehtävä julkaistaan lähisession jälkeen.

- Demo 4:n tehtäväohjeen teksti olisi syytä sisäistää ennen
  mikroluokkasessiota.

- Luennoilla 16.4.2018, 18.4.2018, 23.4.2018 saattaa tapahtua lisää
  kokeiluja.

- Kurssikaverimme muista oppiaineista ovat tarkkailemassa kokeiluja.

- Kysymme osallistujilta palautetta ja toivomme aktiivista
  osallistumista tältäkin osin.

*** Esitietoja

- Pintapuolisia esi- tai ennakkotietoja kurssien Algoritmit
  1&2. -puolelta. Arkihavaintoja abstrakteista tietorakenteista:
  tietue/olio, taulukko, lista, jono, pino, puu.

Lukujärjestelmistä:

- lukujärjestelmät ovat 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.

- Tarkentava kysymys yleisöstä (2017): Negatiivisten kokonaislukujen
  esittäminen?

  Tyypillistä on kahden komplementtiesitys... palataan tähän varmasti
  myöhemmin. Heksana kirjoittaisin koodiin esim. -0x7B, jos
  tarkoittaisin kymmenjärjestelmän lukua -123. MUTTA, jos haluaisin
  ihan kirjoittaa 8 bittiä, jotka tarkoittais esim. etumerkillistä
  -1:tä kahden komplementtiesityksessä 8-bittisessä tallennustilassa,
  niin voisin kirjoittaa 0xff. -2 == 0xfe jne. 

  0xff + 1 (8-bittisenä) = 0x00
  0xff + 3 (8-bittisenä) = 0x02

  Jos olisi 16-bittinen tallennustila, niin -1 olisi 0xffff jne. Aina
  jos kaikki bitit on ykkösiä, niin kahden komplementtiesitys
  tulkitaan luvuksi -1.

  Heksalukuja tarvitaankin yleisimmin juuri silloin, kun nimenomaan
  bittiesityksellä on väliä. Näin ollen "-0x7B" on luultavasti aika
  harvinainen tapa kirjoittaa koodiin vakio "-123"

- Googletellaan löytyisikö aihepiiriin liittyvä video edelleen haulla
  "Ariane 5 test launch". Kurssin asiat eivät ole rakettitiedettä,
  mutta rakettienkin kanssa toimittaessa ne täytyy ymmärtää,
  mm. lukujärjestelmät ja tallennustilan rajallisuus
  laitteistossa. Videolla paukahtaa puolisen miljardia euroa nätisti,
  koska 16 bitin mittaiseen tallennustilaan yritettiin laittaa luku,
  joka olisi tarvinnut useampia bittejä. Oli siinä muutakin, alkaen
  muuttuneista vaatimuksista (tavanomaista ohjelmistoissa) ja
  puuttuvista esitarkistuksista (tavanomainen paikka, josta
  säästetään, kun painotetaan aikatauluja). Lisätietoa, jos
  kiinnostaa:

  http://sunnyday.mit.edu/accidents/Ariane5accidentreport.html

- Kerratkaa tai opetelkaa ensimmäistä kertaa binääriluvut, heksaluvut
  ja oktaaliluvut!! Jatkossa katsotaan heksoja paljon!

Nyt vaelletaan johdannon kerroskuvan matalimmilla tasoilla,
lähellä tietokonetta ja prosessorin rajapintaa.

*** Tietokonelaitteistosta

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. Jäi hyvin alustavalle tasolle;
  palattava aiheeseen myöhemmin tarkemmin!

- Lisää viimeistään demossa 2 vastaan tulevia termejä: Prosessi,
  prosessi-ID. lapsiprosessi, vanhempiprosessi, prosessipuu.

*** POSIX-vartti:

- Mikä on POSIX? Kuka sen on tehnyt? Mitä se sanoo esimerkiksi tällä
  luennolla tai aiemmin nähdyistä asioista?

  + Suositellaan iltalukemiseksi alun yleiskuvaukset ja rajaukset -
    POSIX ei ota kantaa laitteistorajapintaan eikä käyttöjärjestelmän
    sisäiseen rakenteeseen; kyseessä siis nimenomaan
    rajapintadokumentaatio käyttöjärjestelmäkerroksen ja
    sovellusohjelmakerroksen välissä. C, minimalistiset kirjastot,
    shell-komentokieli ja tietty minimijoukko apuohjelmia /
    komentoja. Vain tekstiä; ei mitään grafiikkaan liittyvää.

  + Base definitions Intro: (mm. XBD Sec. 1.7 "Portability"),
    Modulaarinen rakenne, laajennukset ja marginaalihuomioiden
    formaatti.

*** C-kieli ja demo 3

Pyöritään luennoilla kuitenkin hetken verran laitteistorajapinnassa
niin konkreettisesti kuin pystytään. Käytetään apuna mahdollisimman
matalatasoista käyttäjärajapintaa (shell, C-kieli). 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..

Nämä ehdittiin käydä luennon lopussa:

- Esimerkkiohjelmien nouto wgetillä

- (Vielä kerran) editointi yhdessä screen-ikkunassa ja kokeilut
  toisessa.

- C-ohjelman kääntäminen POSIXin määräämällä c99 -komennolla.

- Lähdekooditiedoston sisällön katselua hexdumpilla. Normaali
  tekstitiedostohan se vain on..

- Ääkkösen "ä" UTF-8 -koodaus kahtena tavuna, heksoina 0xc3 0xa4

** Luento 5: Debuggeri, konekieli. Ohjelman argumentit ja virhekoodi

Viime kerralla jäi nämä pois suhteessa vuoteen 2017:

- 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 tarkemmin mm. rivinvaihtojen ja skandinaavisten kirjaimien
  kuvaamista tekstitiedostossa. Mainittakoon UTF-8 -merkistökoodaus
  (yksi Unicoden koodaus).

  Ehkä myöhemmin: 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ä.

Huvin vuoksi ja löytämisen ilon kannalta:

- Tarkastellaan erilaisia tiedostoja heksavedoksena.. vaikkapa
  kuvatiedostoja (JPG, PNG) ...

- Entäpäs tämä: http://users.jyu.fi/~nieminen/kj18/mystery2

Sitten jatketaan "Hei maailma" -ohjelmasta. Edelleen huvin vuoksi ja
löytämisen ilon kannalta...

- 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 esim. POSIX _ei_ ota kantaa; niinpä
  työkalut ovat sidoksissa GNU-tuotoksiin, tiedostoformaatit Linuxiin,
  ja konekieli AMD64 prosessoriarkkitehtuuriin, jotka meillä
  yliopiston palvelimelta löytyvät. Huolellisesti POSIXin mukaiseksi
  tehty C99 -kielinen ohjelma kuitenkin voitaisiin kääntää mihin
  tahansa POSIX-yhteensopivaan järjestelmään, eli se "kelluu"
  abstraktin rajapinnan päällä!)

    + katsottin AMD64-manuaalia:

         * Idea konekielisten tavujen muodostumisesta

         * Esimerkki käskyn esittelystä, "PUSH" .. erityisesti löytyi
           rajapintadokumentaatio sille, miksi "push %rbp" on
           konekielellä nimenomaan heksa 0x55

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.)

- 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".


Ohjelman kytköksiä toimintaympäristöönsä: argumentit ja virhekoodi

- Lavennetaan "hei maailmaa" käyttämään argumenttejaan.

- Tehdään jotain myös virhekoodilla

- TODO tarkista syntymäaikavuosiluku-tehtävä, onko tarkoitus käyttää koko vuotta vai paria alkua
- TODO jatka selittämällä rakenne, ABI, yms

** Luento 6: Prosessi, virtuaalimuistiavaruus 

Ensin tiedotus: demopalautusjärjestelmä on käytössä!

Ohjelman kytköksiä toimintaympäristöönsä: Aiemmin nähty argumentit ja
virhekoodi. Katsotaan vielä seuraavat: 

- standardiulostulo (C:n stdout, vastaa esim. Javan System.out'ia),
  standardivirheulostulo (C:n stderr)

- ympäristömuuttujat (demo 3:n asiaa), voi asettaa shellissä (myös
  skriptissä), exportatut ympäristömuuttujat periytyvät
  lapsiprosesseille eli ohjelmille, jotka kyseinen shell käynnistää.

- samalla metataitoja: kun unohtuu, miten joku juttu toimii jossakin
  kielessä tai alustassa, niin nopein Googlettaja (joka osaa vielä
  soveltaa netin pirstaleisia ohjeita omaan työn alla olevaan
  ongelmaan) on voittaja. Löytyi helposti getenv() -kutsun
  manuaalisivu. Totuus on esim. POSIX-standardissa, mutta nettisivukin
  vaikutti tässä tapauksessa luotettavalta.

- NULL-osoittimen luonne: tarkoittaa "osoitetta ei ole olemassa",
  mutta koodataan kokonaislukuna kuten muutkin
  muistiosoitteet. Saattaa olla kääntäjästä riippuen esim. 0, mutta on
  silti syytä kirjoittaa isoilla kirjaimilla vakiona NULL.

Sitten eteenpäin:

- Askeltaminen konekäsky kerrallaan, "stepi" (step instruction).

- Askelletaan esimerkkikoodia konekielinen 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.

** Luento 7: Osoitteen tulkinta, MMU, käyttöjärjestelmäkutsu

Nämä jäi edelliseltä kerralta:

    - 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.

    - Vilkaistaan luentomonisteen listaa x86-64 -prosessorin
      yleisrekistereistä.

    - Todettiin RIP eli käskyosoiterekisterin muuttuminen
      peräkkäissuoritteisissa käskyissä ja jopa JG (jump if greater)
      ehdollisessa hyppykäskyssä. Ts. prosessorin nouto-suoritus-syklin
      toteaminen.

    - Virtuaalimuistiavaruus on syytä käsitellä alustavasti:

      * 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. Tietyn käyttöjärjestelmän osalta on sovittu
        ABI (Application Binary Interface). Esim. AMD64-prosessorin
        päällä Linuxissa on sovittu käytettäväksi kyseiselle
        prosessorille adaptoitua "SysV ABIa".

Edellinen loppuun:

- Virtuaalimuistiosoitteiden tulkinta alustavasti.

C:llä, assemblerilla ja debuggerilla vielä hetki:

- ohjelman jäljitys strace -apuohjelmalla, joka näyttää kaikki tehdyt
  järjestelmäkutsut.

- 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.

    + Puhdas Assembler-ohjelma. Motivoidaan kerroksittaisten
      abstraktioiden käyttöä.

[Tässä kohtaa luento loppui..]

** Luento 8: C-kieli, linkitys.

Mitkä tunnelmat salissa?

A=huippua! B=OK C=ei niinkään D=hirvittää.

Mini-info keväälle 2018:

- kiitos 55 eilisessä "laboratoriotyössä" käyneelle. Korvaava
  itsenäinen suoritustapa määritellään pian - oletettavasti vaaditaan
  viimeistelty kirjallinen vastaus (ja ohjelmakoodi) kysymyksiin,
  jotka labrassakin aiheuttivat pohdintaa.

- YPE-kokeilut jatkuvat: Paavo ja Jonne vetävät edelleen
  pariluennointina, ja tällä luennolla olisi tarkoitus kokeilla
  Socrative -välinettä.

- Seuraava open labrapäivä ma 23.5.2018 klo 8:30-11:45 luokassa Ag
  B112.2 (Latin). Perjantaina koodaamo normaalisti.

Tarkkaavainen huomio: Monisteen kuvassa 14 pitäisi olla 48-bittisiä
osoitteita, mutta oli 56. Hups.

Korjaus aiempaan ohjeeseen VPN:stä.. Ciscon VPN-softa tarvitaan
Windowsissa, mutta ei Linuxilla eikä Macillä.

VPN:n käyttö hyvä opetella joka tapauksessa, mm. verovaroilla teille
maksetut artikkelitietokannat toimivat yliopiston verkosta käsin!

(luentovideolla tässä lyhyt IRC-demo)



Poimitaan ajatus, johon jäätiin viime kerralla. Eli katsotaan
konekielistä Hello worldiä ja käyttöjärjestelmäkutsun tapahtumista
sovellusohjelmassa:

- 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.

    + 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ä..

      Nyt silmäiltiin päällisin puolin käyttöjärjestelmäkutsun eli
      SYSCALL-käskyn selitys pseudokoodeineen. Kuten mainittu,
      manuaalit ovat hyvää, unettavaa, mutta sivistävää iltalukemista.

    + 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.

Tsekattiin vähän näitä:

- ELF-tiedoston formaatti (vilautettiin speksiä PDF:stä)

- 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ä!

- selväkielisempi listaus ELFin sisällöstä: objdump -x a.out tmv.

- muistin tarkastelu debuggerissa.. lisäesimerkki 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'.

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.

Lopussa YPE-kokeiluna Socrative-kysely. TODO: Täsmennä.

** Luento 9: käyttäjätila, käyttöjärjestelmätila, C-kieli, Aktivaatio, kutsupino, 

Mini-info:

- demo 4 itsenäinen palautustapa on nyt määritelty. Löytyy
  demo-ohjeista (lopussa linkki C-koodiin).

- Palautusjärjestelmässä laatikko auki.

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ä vuonna 2016. cURL on POSIXin määrittämä [EIKÄ ole POSIXin
määrittämä, mistä lie joskus tullut opettajalle moinen aivotuhnu?
Yleisesti käytetty ja alustariippumaton se toki on] 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.

Tärkeä tilannekatsaus: 

- Varmistetaan luentomonisteen sisältö ja tilanne, missä ollaan nyt.

  Tilanne: Jotakuinkin nyt tulisi olla luettu ja ymmärretty sivulle 84
  asti.

Täydennystä edellisiin aiheisiin:

- 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#L107

  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.


Sitten jälleen mukavasti "tutuksi ja turvalliseksi tulleen" demo4:n
mallikoodin ja samalla tapaa tutun tekstimuotoisen debuggerin parissa:

Isompi ohjelma, jossa on vaikkapa aliohjelmakutsuja ja silmukoita:

- Askelletaan demo 4:n esimerkkikoodia lähdekoodirivi kerrallaan
  debuggerilla. Havainnoidaan kutsupinoa, jonka tilanteen saa gdb:ssä
  näkyviin komennolla "backtrace" tai lyhennettynä "bt". Muita nimiä
  ainakin aktivaatiopino, suorituspino.

- Katsotaan vähän vinkkiä demo4:n palautustehtävän
  aloittamiseksi. Entä jos tulee vahingossa "ikuinen silmukka"?
  (Helposti käy...) Ctrl-C, debuggeri ja tarkkaavaisuus koodaamisessa
  auttavat. Älä unohda kynää ja paperia!

- aliohjelmakutsu, kutsupino

- debuggerin näkymä kutsupinoon, 'backtrace'-komento näyttää pinoon
  kullakin hetkellä kertyneet aliohjelma-aktivaatiot.

- askeltaminen konekielikäsky kerrallaan erityisesti rekursion
  päättymisen kohdalla.

** Luento 10: Ohjelman jälki, kutsupino konekielessä, ABI 

Infoja:

- Demojärjestelmä on kokeellinen (ja se on kivaa). Yleisohje: Sivun
  uudelleen lataaminen (refresh, esim. F5 tmv.) voi auttaa, jos
  näyttää kummalliselta. Lipun klikkaamisesta voi ilmiantaa
  pahiksen. Toivottavasti ei ole todellista tarvetta klikata sitä :)

- Vappuaaton ohjelmaa:

  8:30-12:00 Open labrapäivä mikroluokassa (Europe)
  16:15 Käyttöjärjestelmien luento
  17:45 luento päättyy. Ehtii vielä patsaalle vappua viettämään.

- Open labrapäivät myös seuraavana maanantaina. Ja seuraavana.

- Demo4 työn alla. Tämän päivän jälkeen toivottavasti demo5.

Jatketaan demo4:n esimerkkikoodeilla ja luentomonisteen
pinokehyssarjakuvasta.

Esimerkkejä C-kielellä (HUOM: osin kertaavaa!):

- Demo4:n palautustehtävään vähän sommittelua alkuun, esim. seuraavan
  luvun laskeminen (ei spoilata kokonaan kuitenkaan!)

- Mitä tapahtuu, ja mitä voi tehdä, jos vahingossa tulee ikuinen
  silmukka? ("Ctrl-C" painallus, "killall ohjelmanimi" -komento)

- Muistetaan perinteinen "kaikenlaskija" -esimerkki demonstroimaan
  aikakatkaisun tarvetta.

Aliohjelmien ja pinon käyttö (osin jo myös demon 5 aihepiiriä):

- 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.

Demo 5:n olennainen sisältö, eli aliohjelma-aktivaatio ja konekielinen
ohjelman suoritus.

- 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.

** Luento 11: Historiakatsaus, Aikakatkaisu/keskeytys

Ennakoiva havainto:

- 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äjätilan ohjelmalla täytyy olla mahdollisuus
  pyytää siirtymää käyttöjärjestelmän palveluun ("system call")
  jolloin prosessorin tilan on vaihduttava.

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.

- pakollinen maininta: http://www.cs.utexas.edu/users/EWD/ewd01xx/EWD196.PDF
  eli Dijkstran "The structure of the THE-multiprocessing system",
  josta käyttöjärjestelmien jakaminen kerroksiin (julkaisussa
  'System hierachy', nykyään 'layers'), sivutetun virtuaalimuistin
  esiversiot ja semaforit ovat peräisin. (lisämateriaalia)

Sitten periaatteessa luentomonisteen järjestyksessä etteenpäin...

Yhteenveto käyttöjärjestelmän tehtävistä, tavoitemittareista ja
kompromisseista.


Prosessorin suoritussykli, tarkempi kuva:

- 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.

Yleisön kysymys 2017: "Blue screen" (win), "kernel panic" (linux)
tulosteista.. kyseessä käyttöjärjestelmän virhe, josta ei ole
paluuta. kyllä näissä virheilmoituksissa nimenomaan viitataan
käyttöjärjestelmän muistialueisiin (koodiosoite RIP, kernel stack
pino-osoite RSP)

** Luento 12: Prosessi, säie. Tilakaavio, fork(), exec(), shellin perustoiminta

Moniajo, prosessi, "säie", resurssit, haaroitus ja käynnistys.

Esim. vuoron vaihto prosessien välillä sisältää hukka-aikaa:

  P1 |------|              |------|
  P2            |------|
  kj        |---|      |---|      |---|

Tiheämpi kellokeskeytys:

  P1 |---|           |---|
  P2         |---|           |---|
  kj     |---|   |---|   |---|



Prosessi? Kertausta aiemmista havainnoista:

- POSIXin Base Definitions -osion termimäärittely "Process":

  "An address space with one or more threads executing within that
  address space, and the required system resources for those threads."

  Vautsi... Pystytään jo ymmärtämään suurin osa tästä kuvailusta!
  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ä. Lisähuomio POSIXin termimäärittelyssä:

  "Many of the system resources defined by POSIX.1-2008 are shared
  among all of the threads within a process. These include the process
  ID, the parent process ID, process group ID, session membership,
  real, effective, and saved set-user-ID, real, effective, and saved
  set-group-ID, supplementary group IDs, current working directory,
  root directory, file mode creation mask, and file descriptors."

- 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
  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 käyttöjärjestelmäkutsujen tehostamiseksi.

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).

  Tämä ``task_struct`` 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.

Tässä kohtaa tilakaavio. Ja jumppa.


Jatketaan suoraan prosessin olemuksesta:

- 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ä.

- 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.

  (ks. esimerkkikuva tämän luennon alussa)

** Luento 13: Säikeet. Kilpa-ajo, lukot, deadlock.

Muistutus ekasta tentistä:

- ke 16.5.2018 klo 16:15-20:15. Ei tarvitse ilmoittautua. Ikään kuin
  luento. Uusinnat heinäkuu, elokuu. Näihin ilmoittautuminen Korpissa.

- kurssi lähestyy loppuhuipennusta. Demot 1-5 pitäis alkaa olla
  sisäistetty.

- Hmm... Tässä kohtaa pittäis alkaa olla demo6 speksattu... Tulee
  keskiviikkona. Assemblerilla tehdään siinä itse.

Säie vs. prosessi: 

- Säie on yksi ajassa etenevä suorituskohta prosessin koodissa, joka
  muodostaa konekielisten suoritusten "jäljen" ja vaikutuksia dataan.

  Pieni tenttitärppi luennolla tässä kohtaa (paperin käyttö
  jäljityksessä pääkopan tukena).

- 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ä; suurten tiedostojen
  lataamiset ja tallentamiset), seinäkelloajan minimointi
  rinnakkaislaskennalla.

- Laskentatehtävien nopeuttaminen säikeistämällä vaatii 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 2018/l13/ -hakemistossa: saikeiden_tarve.c saikeet.c

- katsottiinpa myös Googlella Java Thread API ja C# vastaava.

- "kilpa-ajotilanne" eli race condition: vuoronnus voi milloin vain
  keskeyttää säikeen (tai prosessin) ja antaa suoritusvuoron toiselle:

  koodi 2018/l13/ -hakemistossa: race.c

- lukitus auttaa: keskinäinen poissulku race_fixed_mutex.c

- deadlock -tilanne, esimerkki huolimattomasta resurssilukituksesta:
  huonon kahvihuoneen simulaattori kahvihuone_deadlock.c ja toimivamman
  kahvihuone_ei_lukkiudu.c

** Luento 14: IPC: signaalit, viestijono. Semafori. Kuluttaja-tuottaja.

Demo 6 esittely.

Vilkaistaan mallitenttiä (sama kuin viime vuonna).

Tästä jatketaan viimeinen viikko tiukasti siihen asti kuin vaan
ehditään:

Prosessien (ja säikeiden) välinen kommunikointi eli IPC:

- engl. Inter-process communication. Yksi tärkeistä tehtävistä, joihin
  käyttöjärjestelmää tarvitaan. Esimerkkejä:

  + signaalin lähettäminen pääteyhteyden näppäilyllä "päällimmäiselle"
    ohjelmalle, jolle syötteet ohjautuvat.

  + signaalin nappaaminen C-kielisessä ohjelmassa:

    koodi 2018/l14/sigesim.c

  + 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 repossa: 2018/l14/chattomyself.c

    (tässä oli "demoefekti" luennolla 15.. todellinen efekti siis se,
    että luennoitsija luuli varoitusta virheeksi ja ettei koodi
    kääntynyt.. vaikka se kääntyikin. Esimerkistä korjattu nyt myös
    varoitukset pois.)

Semafori:

- esimerkki: tuottaja-kuluttaja -probleemi sekä sen ratkaisu kolmella
  semaforilla

  koodi repossa: 2018/l14/tuottaja_kuluttaja.c

  "ASCII-sarjakuva" repossa: 2018/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! Miksi? Tulee
      älyttömästi hukka-aikaa lukituksia hoitavista
      käyttöjärjestelmäkutsuista!! 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. Tarkkana suunnittelussa ja toteutuksessa!

    + Säikeitä kannattaa alkaa käyttämään omissa ohjelmissa tarpeen
      mukaan, muistaen tarkkaavaisuuden ja potentiaaliset
      ongelmatilanteet!


** Luento 15: Virtuaalimuisti, sivutaulut, swap. I/O. Unixin erikoistiedostot. 

Loppusuoralle / lopputaisteluun... Niin monta tuntia aikaa ekaan
tenttiin, että kyllä me siihenkin mennessä vielä paljon hyviä asioita
ehditään oppia.

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ä.

- 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: 2018/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

  - Katsotaan jotain oikean ohjelman karttaa,
    esim. emacs-tekstieditorin. Havaitaan mm. lukuisa joukko
    kirjastoja, joiden tarvitsee olla ladattuna fyysiseen muistiin
    vain yhtenä kopiona, vaikka emacs olisi käynnissä vaikka kuinka
    monena prosessina.


Pari lisäesimerkkiä Unix-tyyppisestä "kaikki ilmenee tiedostona"
-lähestymisestä (näitä on ehditty nähdä jo aiemminkin, kun
signaaliluennolla juteltiin dd -ohjelmasta):

    + /dev/urandom -"tiedostosta" voi lukea loputtomiin satunnaislukuja

    + /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.

    + 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ä.

    + /dev/sda -"tiedostosta" voi lukea (käyttöoikeuksien salliessa)
      kovalevyn koko sisällön bitti bitiltä esimerkiksi koko
      järjestelmän kattavaa varmuuskopiointia varten.

Lisää tiedostonhallinnan käyttäjänäkökulmaa:

Esimerkki:

  - Tiedostojen käyttöoikeudet rwx / ugo. Shell-ohjelma
    chmod nähty jo aiemmin.

    (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ä...)

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 (ajurit).

- I/O -kutsun kulku ohjelmistokerrosten läpi (karkea yleiskuva).

Lopussa vielä http://www.pouet.net/prod.php?which=67941 Sitä nyt vaan
ei voi estää.


* Ja se oli sitten siinä vuodelta 2018! 

Tähän ehdittiin 2018. Loput ei tule tenttiin.

Vuoden 2018 mukaista kurssia voi suorittaa helmikuuhun 2019
saakka. Virallisten tenttikertojen (3 kpl) jälkeen kysy erillistä
tenttimahdollisuutta.

* 2018 pois jätettyä:

** C-kielestä "pienoisgallup"

Alkuun "YPE-hype" (eli omien yliopistopedagogisten opintojeni
hurmoksen herättämä interaktiohetki):

- Muodosta lähimpänä istuvien 2-3 henkilön kanssa keskusteluryhmä;
  keskustelkaa seuraavasta kysymyksestä demo4:n ja tähän asti
  luennoilla käsitellyn valossa:

  + Mikä tällä hetkellä askarruttaa eniten C-kielessä?

    (esim. suhteessa aiemmilta kursseilta tuttuihin kieliin, muihin
    aiempiin ohjelmointikokemuksiin tai ennakko-odotuksiin? Keskustelu
    saa rönsyillä muihinkin suuntiin, kunhan pyörii C:n ympärillä.)

- Keskustelun löydöksiä (luentovideo alkaa tästä kohtaa):

  + "viitemuuttujat", ts. viedään aliohjelmalle **muistiosoite**.

  + miksi Windowsin ja Linuxin (tai ylipäätään eri
    käyttöjärjestelmien) C-ohjelmat eivät ole yhteensopivia keskenään?
    HUOM: Ne *ovat* yhteensopivia, jos niissä (1) ei kutsuta
    käyttöjärjestelmäriippuvaisia aliohjelmia ja (2) ohjelmat
    käännetään uudelleen (ABI määrää mm. miten aliohjelmia kutsutaan
    konekielessä; ABI on käyttöjärjestelmän tekijän valinta ja riippuu
    aina prosessoriarkkitehtuurista.)

  + (on ihan OK, jos tässä vaiheessa "ei osaa vielä muodostaa
    kysymystä". Toivottavasti se on pian mahdollista!)

  + C:n "listat"? HUOM: Lista on teknisesti eri asia kuin taulukko
    (ks. esitietoluku monisteesta!) Kysymyksessä tarkoitettiin
    taulukkoa ``int taulukko[3]`` - miksi se sallii kirjoittaa
    ``taulukko[1000] = 42`` Noh.. C yrittää tehdä mahdollisimman
    "vähän" ja jättää loput ohjelmoijan vastuulle. HUOM:
    käännösvaiheessa voi olla vaikea tietää, mihin
    sijoitetaan. Esim. ``taulukko[i] = 42``. Itse pitää ohjelmoida
    esim. ``if (lkm > maximi) error("") else ...``

    Voi aina tehdä kirjaston, joka hoitaa esim. tarkistukset. 
    ``turvallinen_taulukko_lisaa(taulukko, maksimi, indeksi, arvo);``

    HUOM: C:n taulukko on erilainen (yksinkertaisempi) kuin
    modernimpien kielien automaattisesti skaalautuvat ja rajat
    tarkistavat tietorankenteet.

  + "Eikö ne 1970-luvulla 'tajunneet' tehdä taulukosta
    turvallisempaa"? Historiikeista voi selvitä. Joka tapauksessa voi
    olla suorituskykykysymys.
    - vuosi 2018 tässä moi, ja Jonne: Kyllä tajusivat.  Taulukoiden
      rajojen tarkistus (ainakin 1960-luvulta
      https://en.wikipedia.org/wiki/Bounds_checking#Index_checking),
      poikkeukset (LISP ja PL/I 1960-luvulla) ja roskien keruu (LISP
      1950-luvun lopussa) oli keksitty jo tuolloin, mutta
      valitettavasti K&R C:tä tehdessään halusivat tehdä vain
      "makroassemblerin", joten moiset höpötykset saivat jäädä
      kielestä pois.  Tämä sama pätee seuraavaan kysymykseen.

  + Miksi muistivuotojen hallinta ja muu resurssien vapautus on
    ohjelmoijan vastuulla C:ssä? Vastaus on kysymyksessä: Milloin
    pitäisi vapauttaa? Vaatii ajonaikaisen järjestelmän, joka
    tarkkailee resurssin tarvetta. Uskomukseni on, että ainakin
    osittain tavoite on ollut vähentää alustan
    monimutkaisuutta. Myöskin tutkimus kielten toteutuksessa on elänyt
    omaa raidettaan 1970-luvun jälkeen, kun C syntyi.

  + Mikä on .c, .h ja .o -tiedostojen suhde toisiinsa? Ks. demo3 ja
    demo4 tehtäväohjeet.

Tästä jatkuu itse asia sitten:

- Tavujärjestys (byte order), jos jotakuta on ihmetyttänyt
  (parhaimmillaan on ihmetyttänyt!)? AMD64:ssä on "little-endian"
  -järjestys. Kokeillaan luvulla 0x0123456789abcdef, jonka
  tavujärjestys on helppo varmistaa vaikkapa debuggerin tulosteesta.


** Lisuketta edelliseen

- Näkökulmia viime luennon keskusteluhuomioihin:

  + C on lähtökohtaisesti suunniteltu "laiteläheiseksi" - esimerkiksi
    lähdekoodissa näkyvät rakenteet vastaavat datan sijoittumista
    tietokoneen muistiin niin, että mitään ei ole tai tapahdu
    "piilossa". Mm. tämän lähtökohdan vuoksi C (ja sittemmin C++)
    soveltuvat käyttöjärjestelmien ja muun laitehallinnan
    toteuttamiseen: datan sijainti tietokoneen muistiavaruudessa
    nähdään suoraan, koska struct-rakenteet ja taulukot (mukaanlukien
    merkkijonot) ovat kiinteitä, peräkkäin sijaitsevia pötköjä.

  + Mitä muuta C:n yksinkertaisuudesta seuraa? Mahdollisimman pieni
    määrä ajonaikaista alustakoodia - mm. siksi C soveltuu sellaisten
    pienten prosessorien ja mikrokontrollereiden ohjelmointiin, joissa
    ohjelmalle tai datalle ei yksinkertaisesti ole kovin paljon
    tilaa. Tällaisten valmistus ja siten käyttäminen tuotteiden osana
    on luonnollisesti halvempaa (=tarkoituksenmukaista) kuin isompien.

  + Miksei C:ssä olisi edes käännösaikana estetty taulukoiden tilan
    ylittämistä? Itse asiassa kääntäjät osaa varoittaa aika
    hyvin. Käytä oikeassa ohjelmassa -Werror argumenttia gcc:ssä



** Ehkä vielä takas?

[Siirtynyt aiemmasta..] Alkuun 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ä.


** alkupuolen luennoilta..


    + (ei pilata kaunista speksiä vuonna 2018 tällä:) 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).


Viime vuoden "opettajan pääsiäisläksy" eli pääohjelma, jossa ei ole
eksplisiittistä return-lausetta lopussa... tämähän se tuotti
hämmennystä ja "huonon esimerkin", kun en saanut kääntäjää
varoittamaan ja kieltäytymään omaan silmääni vaaralliselta näyttävästä
koodista... No.. läksy oli helppo, koska pääsiäisläksyn tehtävä eli
nollasta poikkeavan virhekoodin jättävä ohjelma olisi ollut faktisesti
mahdoton tehdä: C99-standardi määrittelee seuraavaa main()-aliohjelman
loppumisesta (luku 5.1.2.2.3)::

  5.1.2.2.3 Program termination

    If the return type of the main function is a type compatible with
    int, a return from the initial call to the main function is
    equivalent to calling the exit function with the value returned by
    the main function as its argument; reaching the } that terminates
    the main function returns a value of 0. If the return type is not
    compatible with int, the termination status returned to the host
    environment is unspecified.

Siellähän se standardissa luvataan: "reaching the } that terminates
the main function returns a value of 0". Tältä osin kaikki kunnossa,
ja itsekin olen yhtä asiaa viisaampi. Ja esimerkistä tulikin hyvä :) 
sovitaan vaan, että se käsitteli asioiden tarkistamista standardista,
jos joku alkaa käytännössä ihmetyttämään.

Silti suosittelen kirjoittamaan lähdekoodiin "return 0":n niin ei tule
ihmetystä eteen niillekään, jotka eivät ole yhtä tarkkaan lukeneet speksiä.

Tämä löytyi ensin Googlettamalla ja sitten varmistamalla itse
C99-standardista (ISO/IEC 9899:1999), että näin se on komitea mennyt
sopimaan. Ehkä tämä määritelmä auttaa keskimäärin vähentämään
ohjelmointivirheitä, kun porukka kumminkin unohtaa sen return 0:nsa
kirjoittaa, eikä tajuaisi muuttaa kääntäjän varoituksia virheiksi :).


Vastaus luennolla esitettyyn tarkennukseen kirjastofunktioiden
linkittämisestä käynnistysvaiheessa, eikä enää varsinaisen ajon
aikana:

Ainakin GNU:n työkaluilla ELF-muotoiseen ohjelmatiedostoon voi laittaa
pyynnön kirjastojen linkittämisestä heti ohjelman latauksen yhteydessä
seuraavalla komennolla (osio "-Wl,-z,now")::

  c99 -Wl,-z,now -Werror -g -O0 -o omaecho omaecho.c

Merkintä tulee luonnollisesti aivan viimeisessä työkaluketjun
vaiheessa eli linkitysohjelmassa "ld". Vastaus löytyi kuin löytyikin
helpoiten selaamalla ld:n manuaalia ja tarkistamalla c99-komennolla
käynnistyvän julkisivuohjelman manuaalista, miten ld-vaiheelle saadaan
tuupattua argumentteja. "-Wl,-z,now" johtaa siihen, että
ohjelmatiedoston kasaamisvaiheessa konepellin alla ajettava komento
"ld" saa mm. peräkkäiset argumentit "-z" ja "now". Oletusarvoisesti ld:n
ajo tulkitaan kuten "-z lazy" eli jaetut kirjastot ladataan laiskasti vain
tarvittaessa, eli kun jotakin kirjastossa sijaitsevaa aliohjelmaa
faktisesti kutsutaan.


* 2017 pois jätettyä:

Semaforin käyttö kuluttaja-tuottaja -ongelman ratkaisussa. (Semafori
tietorakenteena käytiin läpi, ja se on muistettava, ts. resurssien
määrää kuvaava kokonaisluku ja jono/joukko prosesseja, jotka
jonottavat siinä tapauksessa, että vapaana on 0 kpl resurssia).

TODO: Hyvä tietää -osastolle 2017:

*** 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: 2017/esimerkit/l17/hellofile.c

Esimerkki:

  - Oman "cat -apuohjelman" raakile; tiedoston avaaminen, lukeminen ja
    kirjoittaminen tavu kerrallaan, sulkeminen C:n alustakirjaston
    kutsuilla.

    koodi repossa: 2017/esimerkit/l17/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.

*** Lisää esimerkkejä erikoistiedostoista /dev/ -hakemistossa

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/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ä


*** 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.

- 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.



*** 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.



*** Muita ohitettuja 2017


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...

*** I/O:sta ja laitteista ohitettua 2017:

- DMA.

- RAID


*** Vuoronnusmenettelyjä, RT, skriptit.

Vuoden 2016 luennoilta 9-10:

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.


* Vuoden 2015 toteumaa:

** 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!!


** Palauteluento ekan tentin jälkeen 2015 (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.