Käyttöjärjestelmät: poissulkeminen ja synkronointi Teemu Saarelainen Tietotekniikka teemu.saarelainen@kyamk.fi Lähteet Stallings, W. Operating Systems Haikala, Järvinen, Käyttöjärjestelmät Eri Web-lähteet
Rinnakkaisuuden toteuttaminen Nykyaikaisissa käyttöjärjestelmissä rinnakkaisuus on itsestäänselvyys Erilaisia muotoja: Prosessien rinnakkaisuus Rinnakkaisohjelmointi Hajauttaminen Näiden toteuttamiseksi tarvitaan Poissulkemista Synkronointia Viestinvälitystä
Peruskäsitteistöä atominen operaatio kriittinen osio deadlock livelock poissulkeminen race condition nälkiintyminen jakamaton operaatio, jota ei voi keskeyttää ohjelman osio, joka käyttää jaettua resurssia, eivätkä muut prosessit saa olla yhtä aikaa suorittamassa vastaavaa osiota lukko, jossa kaksi tai useampi prosessi lukittuu, koska ne odottavat toistensa tekevän jotain lukko, jossa kaksi tai useampi prosessi vaihtaa tilaansa odottaessaan toistensa tekevän jotain, mutta eivät kuitenkaan tee mitään hyödyllistä yhden prosessin ollessa kriittisessä osiossa, pitää muut prosessit sulkea pois, jotta ne eivät pääse samoihin jaettuihin resursseihin käsiksi tilanne, jossa monta säiettä tai prosessia lukee ja kirjoittaa dataa, joka on jaettu resurssi, siten, että operaatioiden suoritusjärjestys vaikuttaa lopputulokseen tilanne, jossa prosessi ei saa suoritusaikaa skedulerilta, vaikka sen pitäisi
Yksi- vs. moniprosessori Suoritinajan jako yhdellä suorittimella P1 P2 P3 Prosessien jako eri suorittimille P1 P2 P3
Rinnakkaisuuden tuottamia ongelmia Mietintätauko: Mitä ongelmia rinnakkaisuus aiheuttaa ohjelmoinnissa ja käyttöjärjestelmissä? Jaetut resurssit ja data miten hallitaan luku- ja kirjoitusoperaatiot jaettuun muistiin? Resurssien jako suoritinaika ja I/O vaikea jakaa optimaalisesti, voi syntyä deadlock-tilanteita. Ohjelmointivirheitä syntyy helposti ja niiden löytäminen on vaikeaa suoritusjärjestys voi vaikuttaa tuloksiin.
Esimerkki: kriittinen osio ja race condition void echo(){ chin = getchar(); chout = chin; putchar(chout); } Ajetaan yksinkertaisessa yhden käyttäjän järjestelmässä, yksiprosessorijärjestelmässä, ohjelma kerrallaan Käytetään monessa eri ohjelmassa Jaettu funktio, jaettu muisti
Esimerkki: kriittinen osio ja race condition Entäpä, jos kyseessä onkin moniprosessorijärjestelmä, niin mitä voi tapahtua? Prosessi 1 Prosessi 2 chin = getchar(); chout = chin; putchar(chout); chin = getchar(); chout = chin; putchar(chout);
Ratkaisukeinoja Kriittinen osio vain yksi prosessi kerrallaan Prosessit suoritetaan eri suorittimilla P1 menee suorittamaan funktiota ensin P2 yrittää suorittaa samaan aikaan, mutta se estetään (blocked) P2 laitetaan suspend-tilaan P1 saa suoritettua funktion loppuun P2 pääsee jatkamaan (unblocked ready, running)
Race condition kilpatilanne Race condition eli kilpatilanne syntyy seuraavasti monta prosessia tai säiettä lukee ja kirjoittaa samaa dataa lopputulos riippuu prosessien käskyjen suoritusjärjestyksestä Viimeisenä suorituksen tekevä prosessi päättää lopputuloksen
Kilpailu prosessien välillä Tarvitaan poissulkemista (mutual exclusion, mutex) Kriittiset osat Kriittiset resurssit (esim. tulostin) Deadlockien välttäminen Lukko syntyy, kun kaksi tai useampi prosessi odottaa samoja resursseja, eikä kumpikaan vapauta jo varattua resurssia Nälkiintymisen välttäminen KJ ei välttämättä anna resursseja jollekin tietylle prosessille Sekä deadlockit että nälkiintyminen ovat seurausta poissulkemisesta
Toimivan poissulkemisen vaatimuksia Vain yksi prosessi kerrallaan kriittisessä osiossa Jos prosessi pysähtyy ei-kriittisessä osiossa, se ei saa häiritä muiden prosessien toimintaa Ei deadlockkeja eikä nälkiintymistä Prosessin tulee viipymättä päästä suorittamaan kriittistä osiota, mikäli muut prosessit eivät sitä ole suorittamassa Mitään oletuksia ei saa tehdä prosessien nopeuden tai määrän suhteen Prosessi on kriittisessä osiossa vain äärellisen pituisen ajan
H/W-tuki poissulkemiselle Keskeytysten disablointi Prosessi on suorittimella, kunnes se tarvitsee KJ:n palvelua tai se keskeytetään Keskeytysten (hetkellinen) disablointi takaa poissulkemisen muut prosessit eivät saa suoritinaikaa Toimii yhdellä prosessorilla, muttei moniprosessorijärjestelmissä
Esimerkki: keskeytysten disablointi Prosessi X: while (true){ interrupts_disable(); /* disable interrupts */ /* critical section, no other processes can execute*/ interrupts_enable(); /* enable interrupts */ /* remaining non-critical section */ }
Erityiset käskyt Compare & Swap Atominen käsky, jolla voi testata arvoja ja sijoittaa uuden Käskyn avulla voidaan toteuttaa poissulkeminen Exchange Atominen käsky, joka vaihtaa muistipaikan sisältämän arvon rekisteriin Käskyn avulla voidaan toteuttaa poissulkeminen
Esimerkki: Compare & Swap
Esimerkki: Exchange
H/W-tuen haittoja Odottelu vie prosessori aikaa Nälkiintyminen on mahdollista, jos useampi prosessi odottelee Lukittuminen on mahdollista Esim. korkeamman prioriteetin omaava prosessi saa suoritusaikaa ja matalamman prioriteetin prosessi on tehnyt poissulkemisen
Semaforit Semafori = kokonaislukuarvo, jota käytetään prosessien väliseen viestintään Arvoa käsitellään atomisilla operaatioilla alustus (initialize) vähennys (decrement) - semwait() lisäys (increment) - semsignal() Semafori alustetaan ei-negatiiviseen arvoon Jos semwait():n jälkeen arvo on negatiivinen, prosessi blokataan Jos semsignal():n jälkeen arvo on 0 tai negatiivinen, semwait():lla blokattu prosessi saa jatkaa
Semaforin toteutusesimerkki
Binäärinen semafori
Heikot ja vahvat semaforit Semaforia odottavat prosessit laitetaan jonoon (queue) Missä järjestyksessä prosessit otetaan jonosta pois? Vahvat semaforit käyttävät FIFO:a Reiluin tapa kohdella prosesseja Eniten odottanut pääsee ensiksi pois Heikot semaforit eivät määrittele järjestystä
Esimerkki: vahva semafori
Esimerkki: semafori
Poissulkeminen semaforeilla
Prosessit ja semaforit