Processzusok, szálak Operációs rendszerek MINB240 2. előadás Szálak, IPC Egy processzus Saját címtartomány Egyetlen vezérlési szál Hasznos lehet több kvázi párhuzamos vezérlési szál használata egy címtartományban Mintha különálló processzus lenne Szál (thread) vagy könnyű súlyú processzus 1 2 Szál modell Szál modell Nem csak processzus, hanem szál táblázat is van (a) 3 processzus, mindegyik egy szállal (b) 1 processzus, 3 szállal Processzus elemei Címtartomány Globális változók Megnyitott fájlok Gyermekprocesszusok Függőben lévő ébresztők Szignálok és szignálkezelők Elszámolási információk Szál elemei Utasításszámláló Regiszterek Verem Állapot 3 4
Miért használunk szálakat? Szövegszerkesztő Hasonlóak a processzusokhoz, de... Kevesebb idő kell a létrehozáshoz a lezáráshoz a szálak közötti váltáshoz A szálak egy memóriaterületen belül vannak így könnyen kommunikálhatnak a kernel hívása nélkül 5 6 Többszálas Web böngésző Kép kérés processzussal Sok weblap tartalmaz több kis képet A böngészőnek minden képért külön kapcsolatot kell kiépítenie a lapot tároló számítógéppel A kapcsolatok felépítése és bontása sok idő Idő Kép kérés Kép kérés A böngésző több szál használatával több képet kérhet le egyszerre Processzus 1 server server Futás Várakozás 7 8
Kép kérés szállal Többszálas Web szerver Idő Kép kérés server Szál A (Processzus 1) Szál B (Processzus 1) Kép kérés server Futás Várakozás Várakozás, amí szál B végez 9 10 Felhasználói szintű szálak Felhasználói szintű szálak, előnyök A kernel semmit nem tud a szálakról Csak a processzusokat látja Szál kezelés egy könyvtárban van implementálva Szálak közötti kapcsolás gyorsabb Nincs szükség kernel csapdára, rendszerhívásra Bármelyik operációs rendszer alatt implementálható Nagy számú szál hozható létre alkalmazásonként 11 12
Felhasználói szintű szálak, hátrányok Kernel szintű szálak A szálnak önként kell feladnia a futását Nincs óra megszakítás a szálhoz Együttműködő többszálas programozás Nem használja ki ha több CPU van a gépben Ha egy szál blokkolt, akkor az egész processzus blokkolt, hiszen a kernel semmit nem tud a szálakról 13 14 Kernel szintű szálak Hibrid szálak Előnyök Parallel működés Blokkolt I/O és számítás átlapolható Ki tud használni több processzort Hátrányok Szál létrehozás és lezárás esetén szükség van a kernelbe lépésre (rendszerhívásra) Drágább mint a felhasználói szintű 15 16
Processzusok kommunikációja Processzusok kommunikációja InterProcess Communication (IPC) Milyen feladatokat lát el: 1. Egymás közötti információcsere 2. Erőforrások megosztás (ne keresztezzék egymást) 3. Szinkronizáció (megfelelő sorrend kialakítása) Szálaknál 1. nem probléma (közös címtartomány) 2. és 3. ugyanúgy érvényes 17 18 Többszálas program, egy hibajelző Nyomtató démon Idő Szál 1 Szál 2 Háttér katalógus errno = -1 Honnan vegyük a nyomtatandó file nevét? errno = -2 Hová tároljuk a nyomtatandó file nevét? if(errno == -1) { 19 20
Versenyhelyzet Ha kettő vagy több processzus olvas vagy ír megosztott adatokat és a végeredmény attól függ ki és mikor fut Problémás lehet megtalálni a versenyhelyzetet Legtöbb teszt jó, csak néha kapunk hibát Megoldás: Versenyhelyzet Megelőzés Kölcsönös kizárás: egy módszer, amely biztosítja hogy ha egy processzus használ valamely megosztott változót, fájlt, akkor a többi processzus tartózkodjon ettől a tevékenységtől. 21 22 Kritikus terület, szekció Egy processzus ideje jelentős részét számítással tölti Néha a megosztott változókhoz, fájlokhoz kell hozzáférni Azt a részt mely megosztott részekhez fér hozzá kritikus területnek nevezzük Az kellene hogy két processzus azonos időben ne legyen kritikus szekcióban (kölcsönös kizárás) Koordinálatlan belépés a kritikus szekcióba verseny helyzethez vezet Versenyhelyzet elkerülésének 4 feltétele 1. Ne legyen két processzus egyszerre a saját kritikus szekciójában (kölcsönös kizárás) 2. Semmilyen előfeltétel ne legyen a sebességekről vagy a CPU-k számáról 3. Egyetlen, a kritikus szekcióján kívül futó processzus sem blokkolhat más processzusokat (haladás) 4. Egyetlen processzusnak se kelljen örökké arra várni, hogy belépjen a kritikus szekciójába (korlátosság) 23 24
Kölcsönös kizárás kritikus szekcióval Idő A kritikus szekcióba lép A kilép a kritikus szekcióból Processzus A B megpróbál kritikus szekcióba lépni B kritikus szekcióba lép B kilép a kritikus szekcióból Megoldások és problémák Processzus A B blokkolódik T 1 T 2 T 3 T 4 25 26 Kölcsönös kizárás tevékeny várakozással Tevékeny várakozás A processzus folyamatosan ellenőrzi hogy beléphet-e a kritikus szekcióba Semmi mást (hasznosat) nem tud csinálni a processzus Zárolásváltozó Szigorú váltogatás Peterson megoldása Hardware-es segítséggel 27 Zárolásváltozó Megosztott zárolásváltozó Kezdetben értéke 0 Mielőtt egy processzus belépne a kritikus szekcióba Ha a zárolásváltozó értéke 0, akkor 1-re állítja és belép a kritikus szekcióba Ha a zárolásváltozó értéke 1, akkor várakozik amíg 0 nem lesz 28
Zárolásváltozó, megoldás? Zárolásváltozó, a problémás futás Idő Processzus A Processzus B while(lock == 1); lock = 1; lock = 0; non_ while(lock == 1); lock = 1; lock = 0; non_ while(lock == 1); lock = 1; lock = 0; non_ while(lock == 1); lock = 1; lock = 0; non_ 29 30 Zárolásváltozó, megoldás? Szigorú váltogatás Segít-e ha a megint ellenőrizzük a zárolásváltozót az írás előtt? (lock = 1) NEM A processzustól bármikor elvehetik a vezérlést!!! while(turn!= 0); turn = 1; non_ while(turn!= 1); turn = 0; non_ Helyesen működik, de... 31 32
Idő Szigorú váltogatás Processzus 0 Processzus 1 while(turn!= 0); turn = 1; non_ while(turn!= 0); turn = 1; while(turn!= 1); turn = 0; non_... Szigorú váltogatás 0. processzust blokkolta egy nem kritikus szekcióban levő processzus Sérti a 3. feltételt Akkor jó, ha a két processzus szigorúan váltogatja egymást while(turn!= 0); turn = 1; Blokkolódik, amíg processzus 1 ismét végre nem hajt egy kritikus szekciót 33 34 #define IGEN 1 #define NEM 0 #define N 2 int turn; int interested[n]; Peterson megoldása void enter_region(int process) { int other; other = 1 - process; interested[process] = IGEN; turn = process; while(turn == process && interested[other] == TRUE) ; Peterson megoldása Processzus 0 Processzus 1 enter_region(0); leave_region(0); non_ enter_region(1); leave_region(1); non_ void leave_region(int process) { interested[process] = NEM; 35 36
enter_region(0); leave_region(0); non_ Peterson megoldása interested turn Processzus 0 0 1 Processzus 1 0 0 1 0 0 1 1 1 0 1 1 enter_region(1); leave_region(1); non_ 37 Peterson megoldása interested turn Processzus 0 0 1 Processzus 1 0 0 enter_region(0); 1 0 0 1 1 1 enter_region(1); while(turn == process && interested[other] == TRUE) ; leave_region(0); non_ leave_region(1); non_ Ha majdnem egyszerre hajtják végre az enter_region részt akkor is működik!!! 38 Hardware-es segítséggel, megszakítások Amikor belép a kritikus szekcióba letítja az összes megszakítást. Amikor kilép engedélyezi. Ilyenkor az órajel is tiltva van, nincs processzus átütemezés Probléma Felhasználói processzus kezébe adjuk a megszakításokat (nem szerencsés) Mi van ha egy processzus soha nem kapcsolja vissza Több CPU esetén a tiltás csak egy CPU-ra vonatkozik, így még mindig fennállhat a versenyhelyzet 39 Hardware-es utasítással Zárolásváltozók helyes implementálása Test and Set Lock utasítás: TSL RX,LOCK Beolvassa a LOCK memóriaszó tartalmát az RX regiszterbe Egy nem nulla értéket ír a LOCK memóriába Garantáltan nem szétválasztható, nem megszakítható műveletek Atomi művelet Az utasítást végrehajtva a CPU zárolja a memória sínt minden más CPU elől 40
Eddigiek összefoglalása Eddigi módszerek tevékeny várakozást használtak és van két problémájuk: Aktívan használják a CPU-t, még a várakozás alatt is Fordított prioritás probléma Legyen két processzus, H és L H processzusnak magas a prioritása L processzusnak alacsony a prioritása Amikor H futáskész, mindenképp fut L belép a kritikus szekcióba H futáskész lesz és belépne a kritikus szekcióba Örökké várni fog, mert L soha nem futhat 41 Alvás-ébredés Az ötlet: Amikor a processzus egy eseményre vár, meghívja a sleep (altatás) függvényt és blokkolódik Amikor az esemény bekövetkezik, az esemény generáló processzus (egy másik processzus), felébreszti (wake-up), futásra készre állítja a blokkolt processzust. Gyártó-fogyasztó probléma Korlátos tároló problémának is nevezik 42 Gyártó-fogyasztó probléma A gyártó adatokat generál és egy bufferben tárolja A fogyasztó adatokat vesz ki a bufferbőlés felhasználja A két processzus egy közös, korlátos méretű tárolón osztozik gyártó Gyártó-fogyasztó probléma, kérdések Gyártó Amikor a buffer megtelik, elalszik Felébresztik, amikor a fogyasztó kivett adatokat Fogyasztó Amikor a buffer üres, elalszik Felébresztik, amikor a gyártó betett adatokat X X X Versenyhelyzet alakulhat ki fogyasztó 43 44
Gyártó-fogyasztó probléma gyarto() { item = produce() if(count == N) sleep(); insert_item(); count++; if(count == 1) wakeup(con); int count = 0; #define N 4 fogyaszto() { if(count == 0) sleep(); remove_item(); count--; if(count == N-1) wakeup(prod); Gyártó-fogyasztó probléma Processzus 0 count Processzus 1 gyarto() { item = produce() if(count == N) sleep(); insert_item(); count++; if(count == 1) wakeup(con); fogyaszto() { if(count == 0) sleep(); remove_item(); Elveszik, hiszen count--; fogyasztó nem alszik if(count == N-1) wakeup(prod); Megtölti a buffert és elalszik Együttes, ellenőrizetlen hozzáférés 45 46 0 1 Igaznak találja Elalszik, örökre Szemaforok E.W. Dijkstra, 1965-ben javasolta Egész változókban számoljuk az ébresztések számát Az új változó típust szemafornak nevezte el (semaphor) Két művelet: Down Up Általánosabb mint, sleep-wakeup down-up down Megvizsgálja hogy a szemafor értéke nagyobb-e mint nulla? Ha igen, akkor csökkenti az értéket és folytatja Ha nulla, akkor a processzust elaltatja mielőtt befejeződne up A szemafor értékét növeli Ha egy vagy több processzus aludna ezen a szemaforon akkor egyet kiválaszt és megengedi hogy a down befejeződjön 47 48
Szemaforok Atomi, elemi műveletek (nem szedhetők szét) Csak néhány utasítás Egy CPU esetén megszakítások használhatók Több CPU esetén a TSL utasítás használható Szemaforok Szemaforok mint szinkronizációs eszközök Először A majd B részlet fusson le Szemafor: count = 0 Kód: Processzus i Processzus j...... A down(count) up(count) B 49 50 Mutex Mutex = Mutual Exclusion (Kölcsönös kizárás) szóból származik a megnevezés!! Nem a kölcsk lcsönös kizárást jelenti!!!!!!!! semaphor mutex; mutex = 1; /* inicializálás */ Gyártó-fogyasztó probléma szemaforral 3 szemafor full (0): tele rekeszek száma empty (N): üres rekeszek száma mutex (1): biztosítja, hogy egyszerre csak az egyik processzus érje el a tárolót down(mutex); /* belépés a kritikus szekcióba */ kritikus szekció up(mutex); /* kilépés a kritikus szekcióból */ 51 52
Gyártó-fogyasztó probléma szemaforral gyarto() { item = produce() down(&empty); down(&mutex); insert_item(); up(&mutex); up(&full); fogyaszto() { down(&full); down(&mutex); remove_item(); up(&mutex); up(&empty); Szemaforok összefoglalva Szemaforokkal többféle probléma megoldható Ugyanakkor könnyű hibázni Azonos számú down és up kell Megfelelő sorrendben kell őket kiadni 53 54 Monitorok Egyszerű példa Programozás könnyítésére Hoare (1974) javasolta Magas szintű szinkronizációs primitív A programozási nyelv része Ötlet Függvények és változók egy speciális modulba vannak csoportosítva Egyszerre csak egy processzus/szál hajthatja végre a monitoron belüli részt Fordító (compiler) biztosítja a kölcsönös kizárást monitor szamlalo { int count; inc() { count = count + 1; dec() { count = count - 1; Kölcsönös kizárást biztosít Nincs versenyhelyzet a count változón 55 56
Eddigiek összefoglalás Szemaforok túl alacsony szintűek A monitorok csak néhány programozási nyelvben használhatók Mindkét esetben a processzusok elérik a közös memóriát Mi van ha több CPU - több memóriával rendelkezünk? (Nincs közös memóriaterület.) Üzenetküldés Üzenetküldés Két primitív send: küldés send(cél, üzenet); receive: fogadás receive(forrás, &üzenet); Egyszerűek, akár könyvtári függvények is lehetnek MPI: Message Passing Interface PVM: Parallel Virtual Machine 57 58 Szinkronizálás A küldő és fogadó lehet blokkoló vagy nem blokkoló Blokkoló küldés, blokkoló fogadás Mind a küldő, mind a fogadó blokkolódik amíg az üzenet meg nem érkezik teljesen Ezt randevúnak hívják Szinkronizálás Nem blokkoló küldés, blokkoló fogadás A küldő folytatja működését A fogadó blokkolódik amíg az üzenet meg nem érkezik Nem blokkoló küldés, nem blokkoló fogadás Egyik processzus sem várakozik, blokkolt A fogadó kaphat üzenetet vagy semmit 59 60
Üzenetek küldése Direkt címzés Minden processzushoz hozzárendelünk egy egyedi címet Az üzenetet a processzusokhoz kell címezni Indirekt címzés Levelesláda A címzés a levelesládának szól Több üzenetet is képes tárolni ideiglenesen Ha egy láda tele van a küldő felfüggesztődik A fogadó a levelesládából fogadja az üzeneteket Két processzus csak akkor kommunikálhat ha közös a levelesládájuk 61 Üzenetküldés, tervezési szempontok Olyan problémák amelyekkel eddig nem kellett foglalkozni Üzenetek elveszhetnek a hálózaton Lehet nyugtázó üzenetet kérni Ha a küldő nem kapja meg a nyugtázó üzenetet, újra elküldi az üzenetet Üzenet megjön, de a nyugta elvész Ismét megkapja az üzenetet. Mi legyen vele? Sorszámmal megoldható Ugyanolyan sorszám esetén felismerhető, hogy már megérkezett 62 Üzenetküldés, tervezési szempontok Hitelesítés Tényleg a fájl szerverrel kommunikálunk-e? Példa: szálak Felhasználói szintű szálak POSIX Pthreads Win32 threads Java threads Kernel szintű szálak Windows XP/2000 Solaris Linux MacOS X 63 64
Több szálas modellek Sok-egy Sok-egy Egy-egy Sok-sok Sok felhasználói szintű szál tartozik egy kernel szintű szálhoz Példák Solaris Green Thread GNU Portable Thread 65 66 Egy-egy Minden felhasználói szintű szálnak egy kernel szintű szál felel meg Például Windows NT/2000/XP Linux Solaris 9 és később Sok-sok Több felhasználói szál több kernel szálhoz tartozhat Például Solaris 9 előtt Windows NT/2000 a ThreadFiber csomaggal 67 68
Két szintű modell Windows 2000 processzus Hasonló a sok-sok modellhez, de lehetőség van egy-egy megfeleltetésre is Például IRIX HP-UX Tru64 Unix 69 70 Windows 2000 szál Windows 2000 szál állapotok 71 72
Solaris Solaris Felhasználói szintű szálak Kernel szintű szálak Könnyű processzusok (Lightweight processes) 73 74 Unix vs. Solaris Solaris 75 76
Linux 77