4. Luento: Prosessit ja säikeet Arto Salminen, arto.salminen@tut.fi
Agenda Prosessi Säikeet Keskeytykset Keskeytyskäsittely Käyttöjärjestelmäkutsut Prosessielementti Prosessin hallinta Suunnittelunäkökohtia Yhteenveto
Prosessi käsitteenä Prosessi ==? Ohjelma? vai resurssien varaamisen yksikkö? vai muistin suojaamisen yksikkö? vai tietoturvan yksikkö? vai latauksen yksikkö? Tilanteesta riippuen erilaisia tilamalleja Ready-Run-Wait Ready-Run-Wait-Swapped wait-swapped ready
Ready-Run-Wait Run Vuorontaja Ready Uusi prosessi Prosessi odottaa Odotus päättyy Wait
Ready-Run-Wait-Block Run Vuorontaja Ready Uusi prosessi Prosessi odottaa Wait Odotus päättyy Block
Ready-Run-Wait- Swapping Run Vuorontaja Ready Uusi prosessi Image muistissa Prosessi odottaa Wait Odotus päättyy Heittovaihtaja Heittovaihtaja Image levyllä Swapped Wait Odotus päättyy Swapped Ready
Process image Koodi Prosessin muistialueet Käyttöjärjestelmältä varatut resurssit Rekisterien sisältö ja muu konteksti Tietoturvaan liittyvät attribuutit ja oikeastaan kaikki muukin mitä tarvitaan jotta prosessin tila voidaan palauttaa täsmälleen samaan kohtaan takaisin levyltä Sivutus ja muistinhallinta keskeisiä vaatimuksia tehokkaan toteutuksen kannalta
Säikeet Usein tarvitaan kevyempää kuin täysverinen prosessi Säikeet, kevytprosessit (thread, light-weight-process, etc) Samaan prosessiin kuuluvat säikeet samassa muistiavaruudessa Kaikilla (yleensä) omat pinot Joskus jopa haarautuvat pinot jos tilanne sitä vaatii! Kysymyspähkinä: Milloin ei omaa pinoa? Käyttö voi erota prosessitasosta Omat rutiinit, joskus jopa suora pyyntö prosessorista luopumiseksi
Säikeiden toteuttamisesta Käyttäjän tasolla Kirjastorutiini, joka toimii prosessin sisäisenä vuorontajana (voihan tämän tietysti tehdä itsekin jos haluaa) Ongelma: Kun joku säie odottaa, kaikki helposti odottavat Käyttöjärjestelmän tasolla Jokainen säie skeduloidaan erikseen Kuormittaa tietysti ytimen tietorakenteita Vaatii käyttöjärjestelmäkutsun
Säikeet ja prosessit: Eräs tulkinta Säikeet -> Suoritusaika Kontekstin vaihto, erilaiset vuoronnusalgoritmit Prosessit -> Resurssien varaus Semaforit, lukot, jne Kommunikointi Jaettu muisti (kätevää saman prosessin sisällä) Viestinvälitys (kätevää prosessien välillä)
FreeRTOS esimerkki FreeRTOS API http://www.freertos.org/a00106.html xtaskcreate( vtaskcode, "NAME", STACK_SIZE, &ucparametertopass, tskidle_priority, &xhandle ); // Use the handle to delete the task. vtaskdelete( xhandle );
Keskeytyksistä Rytmittävät järjestelmän suoritusta Tulevat oheislaitteilta tai ohjelmalta itseltään Vähintään kellokeskeytys tarvitaan pitämään laskenta käynnissä
Keskeytyskäsittelyn aloitus ja lopetus Ensitason keskeytyskäsittely (FLIH, First-Level Interrupt Handling): Talletetaan ympäristö (suorittimen rekisterit, tilasana, muistinhallinnan tiedot) Haaraudutaan oikeaan keskeytyskäsittelijään Paluu: Palautetaan ympäristö Palataan keskeytyskäsittelystä (esim. RETI)
Keskeytyskäsittelystä vielä Ohjelmalliset tarvittavat toimenpiteet vaihtelevat riippuen siitä mitä laitteiston keskeytystoiminta määritelty Esim. rekisterien suhteen suuria eroja Jotta keskeytykset mahdollisimman usein sallittuja, käytössä usein ympäristöpino (kernel stack) Ei ylivuotoa! Jos tyhjenee, kutsutaankin vuorontajaa! Jos ei ympäristöpinoa, säikeen omakin pino käy (olettaen että se löytyy aina muistista kun on paluun aika (ei siis virtuaalimuistia)) Voidaan edelleen keskeyttää (ainakin yleensä)
Keskeytyvä keskeytyskäsittely FLIH FLIH Keskeytys A: Keskeytys B: Keskeytyksen käsittely JMP vuorontaja RETI. RETI A:n ympäristö B:n ympäristö A:n ympäristö Vastaavat ympäristöpinot suorituksen aikana
Käyttöjärjestelmäkutsut Tapahtuvat em. keskeytyskäsittelyn mukaisesti SVC-käskyllä Voi yleensä käyttää myös käyttöjärjestelmän sisältä Esim. sleep
Käyttöjärjestelmää kutsuva käyttöjärjestelmäkutsu FLIH FLIH FLIH SVC SLEEP SLEEP: wait_event: SVC wait_event JMP vuorontaja SVC vuorontaja RETI vuorontaja: RETI vuorontaja: RETI
Prosessielementti (process control block, pcb) Kokoaa tärkeää prosessiin liittyvää tietoa Nimi (yleensä kokonaisluku) Prosessin tila (ready, run, wait, ) Nykyinen prioriteetti Perusprioriteetti Tilaa säikeiden ympäristöjen tallennusta varten (ympäristöpino) Muistiosoitteita (data, ohjelma) Varatut resurssit Saadun signaalin numero ja signaalien käsittelijät Kirjanpitotietoa (ajoaika, jne)
Prosessin luominen Linkittäjä (linker) muodostaa kooditiedoston joka vastaa ohjelmalle varatun muistialueen sisältöä ohjelman käynnistyessä (process image) Käyttöjärjestelmän ytimessä palvelurutiini, joka osaa käynnistää parametrina annetun kooditiedoston Prosessielementin kentät päivitetään sopiviin arvoihin Käytännössä useita variaatioita Fork (uusi prosessi, sama koodi, isäprosessi jatkaa) Exec (uusi prosessi, uusi koodi, isäprosessi jatkaa) Wait (uusi prosessi, uusi koodi, isäprosessi odottaa)
Esimerkki If (!(pid=fork())) { } // Lapsiprosessin suoritettava komento exec( komento ); // Komennon kutsu pieleen; ei pitäisi koskaan tapahtua // mutta ylimääräinen varautuminen helpottaa debuggausta // sitten kun näin joskus käy. exit(exit_failure); status = wait(pid); // Isä odottaa lapsiprosessin lopettamista.
Prosessin päättäminen Suljetaan avoinna olevat tiedostot Vapautetaan resurssit Vapautetaan prosessielementti Prosessien väliset riippuvuudet (isälapsi) voivat joskus aiheuttaa erikoisia tilanteita
Ohjelmallisesti aiheutetut keskeytykset Signaali ohjelmallisesti aiheutettu keskeytys prosessille Prosessi (no oikeastaan vuorontaja) havaitsee signaalin kun se seuraavan kerran tulee tilaan run Voidaan käyttää moneen tarkoitukseen Prosessien välinen kommunikointi Tietyt virhetilanteet (esim. integer_overflow)
Signaalien käsittelystä Signaalien käsittely prosessikohtaista Jos skeduloidaan säikeitä eikä prosesseja voi signaali mennä mille tahansa säikeelle Yleensä kannattaa sallia signaalien vastaanotto vain yhdelle säikeelle ja muutenkin keskittää samantapaisten housekeeping tyyppisten tehtävien hoito samaan säikeeseen (yksinkertaistaa debuggausta ja designia!)
Suunnittelunäkökohtia Säikeet ja prosessit kuluttavat ytimen tietorakenteita ja muistia Varsinkin pienissä järjestelmissä voi olla rajoituksia sille, kuinka monta säiettä/prosessia voi olla Esim. 32kpl (toteutettu 32 sopivan tietorakenteen vektorina) Vaikka rajoja ei olisikaan, voi käytännössä olla tarpeen rajoittaa määrää esim. skeduloinnin ennustamiseksi
Prosessien/säikeiden vuorovaikutus Suora vaikutus Yhteiset resurssit (myös kriittinen alue), viestinvälitys Epäsuora vaikutus Kilpailu yhteisistä resursseista Ohjelmointivirheet vaikeasti löydettäviä (kuten tavallista rinnakkaisuutta sisältävissä ohjelmissa) Kannattaa toteuttaa omia debuggausrutiineja, jos muisti riittää
Esimerkki kunnonvalvojasta task Tn() { while (1) { self.activitybit = 1; } } void systemmonitor() { setpriority(system.lowest); while (1) { foreach (task in mytasks) { if (task.activitybit) { task.activitybit = 0; } else { ReportError(task); } } }
Prosessien ja säikeiden välttäminen sarjallistamalla Periaate: Suoran säikeiden välisen kommunikoinnin sijasta tapahtumapohjaiseen (event-based) kommunikointiin MainLoop jossa odotetaan tapahtumia ja käsitellään niitä saman säikeen sisällä Palvelemaan riittää yleensä 1 säie Edut Ei rinnakkaisen ohjelmoinnin tuskaa Yleensä muistinkulutus laskee, eikä varsinkaan ytimen tietorakenteita tarvitse varata -> suorituskykyetu! Haitat Ei oikeaa rinnakkaisuutta Ei sovi kaikkiin toteutuksiin
Yhteenveto Prosessit sisältävät yhden tai useampia säikeitä saman osoiteavaruuden sisällä Säie pienin skeduloitava yksikkö Run, Ready, Wait (+ lisätiloja tarpeen mukaan?) Keskeytyksissä säikeen (prosessin) ympäristö (rekisterit + tilasana) talletetaan ympäristöpinoon Ajettava säie vaihdetaan vaihtamalla ympäristö toiseksi Keskeytyksessä palattaessa palautetaan ympäristö Keskeytyskäsittely voidaan keskeyttää Käyttöjärjestelmäpyynnöt keskeytysmekanismin avulla