Zbigniew S. Szewczak Podstawy Systemów Operacyjnych Wykład 6 Procesy. Toruń, 2004
Odrabianie wykładów czwartek, 1.04.2004, S7, g. 12.00 za 19.05 czwartek, 15.04.2004, S7, g. 12.00 za 12.05
Składowe systemu Zarządzanie procesami (ang. process management) Zarządzanie pamięcią operacyjną (ang. main memory management) Zarządzanie plikami (ang. file management) Zarządzanie systemem we/wy (ang. I/O system management) Zarządzanie pamięcią pomocniczą (ang. secondary-storage management)
Procesy Koncepcja procesu Planowanie procesów Działania na procesach Procesy współpracujące Komunikacja międzyprocesowa Wątki
Koncepcja procesu System operacyjny wykonuje wykonuje różne programy system wsadowy - zadania system z podziałem czasu - programy użytkownika (ang. user programs) lub prace (ang. tasks) Będziemy utożsamiać zadanie i proces! Proces - program wykonywany sekwencyjnie Koncepcja procesu zawiera licznik rozkazów (ang. program counter) stos (ang. stack) procesu - parametry, adresy powrotu sekcję danych (ang. data section) - zmienne globalne
Procesy a zasoby A B C pamięć wirtualna zasoby procesor we/wy we/wy pamięć
Stan procesu Wykonujący się proces zmienia swój stan (ang. state) nowy (ang. new): proces został utworzony aktywny (ang. running): są wykonywane instrukcje oczekiwanie (ang. waiting): proces czeka na zdarzenie (np. zakończenie we/wy) gotowy (ang. ready): proces czeka na przydział procesora zakończony (ang. terminated): proces zakończył działanie
Diagram stanów procesu nowy przyjęcie przerwanie wyjście zakończony gotowy aktywny obsłużenie zadrzenia lub operacja we/wy decyzja planisty czekający oczekiwanie na zdarzenie lub na wykonanie operacji we/wy
Diagram stanów procesu - SVR5 brak pamięci gotowy swap out wakeup uśpiony swap out utworzony (fork) swap in swap out swap out fork gotowy wakeup uśpiony w pamięci wywłaszczony decyzja planisty return preempt aktywny (kernel) sleep exit return aktywny (user) zombie przerwanie, funkcja systemowa przerwanie, powrót z przerwania
Blok kontrolny procesu (PCB) Każdy proces w systemie operacyjnym jest reprezentowany przez blok kontrolny procesu (ang. process control block - PCB) zawierający stan procesu - gotowy, nowy, aktywny, czekający, zatrzymany licznik rozkazów - adres następnego rozkazu do wykonania w procesie rejestry procesora - zależą od architektury komputera: akumulatory, rejestry (ogólne, bazowe, indeksowe) wskaźniki stosu przechowywane aby proces mógł być kontynuowany po przerwaniu
Blok kontrolny procesu (PCB) (c.d.) informacje o planowaniu przydziału procesora - priorytet procesu, wskaźniki do kolejek porządkujących zamówienia informacje o zarządzaniu pamiecią - zawartości rejestrów granicznych, tablice stron, tablice segmentów w zależności od systemu używanej pamięci informacje do rozliczeń - ilość zużytego czasu procesora i czasu rzeczywistego, ograniczenia czasowe, numery kont, numery zadań informacje o stanie we/wy - lista zaalokowanych urządzeń, wykaz otwartych plików
Blok kontrolny procesu (c.d.) wskaźnik stan procesu numer procesu licznik rozkazów rejestry ograniczenia pamięci wykaz otwartych plików...
Przełączanie procesora wykonywanie proces A system operacyjny przerwanie lub wywołanie systemowe proces B... przechowaj stan w bloku kontrolnym 0 odtwórz stan z bloku kontrolnego 1 bezczynność bezczynność przerwanie lub wywołanie systemowe wykonywanie... przechowaj stan w bloku kontrolnym 1 odtwórz stan z bloku kontrolnego 0 bezczynność wykonywanie
Struktura tablic kontrolnych pamięć urządzenia pliki procesy tablice pamięci tablice we/wy tablice plików tablica procesu proces 1 proces 2... proces n obraz procesu proces 1 obraz procesu proces n
Przykład - IBM/360 & OS/MVT TCB TCB task A save save link ep=a link ep=b TCB task B save return attach ep=c, ECB=E TCB task C return wait 1,E return post E Supervisor ECB
Kolejki planowania procesu Wchodzące do systemu procesy tworzą kolejkę zadań (ang. job queue) Gotowe do działania procesy oczekujące w pamięci głównej na wykonanie tworzą kolejkę procesów gotowych (ang. ready queue) Procesy czekające na konkretne urządzenie tworzą kolejkę do urządzenia (ang. device queue) Procesy migrują między kolejkami
Kolejka zadań i kolejki do urządzeń we/wy kolejka procesów gotowych jednostka taśmowa jednostka dyskowa 0 czoło ogon czoło ogon czoło ogon blok kontrolny 7 blok kontrolny 2 rejestry... rejestry blok kontrolny 3 blok kontrolny 14 blok kontrolny 6... jednostka dyskowa 1 jednostka terminali czoło ogon czoło ogon blok kontrolny 2
Diagram kolejek Diagram kolejek służy do opisu planowania procesów prostokąt określa kolejkę; kółko to zasoby; strzałka to przepływ nowy proces jest w kolejce procesów gotowych zostaje wybrany (ang. dispatched) i otrzymuje procesor proces może zamówić we/wy i trafia do kolejki oczekujących na we/wy proces może utworzyć potomka i czekać na jego zakończenie proces może zostać wywłaszczony wskutek przerwania i przeniesiony do kolejki procesów gotowych
Diagram kolejek w planowaniu procesów kolejka procesów gotowych CPU we/wy kolejka operacji we/wy zamówienia operacji we/wy zużycie kwantu czasu potomek działa powołanie procesu potomnego wystąpienie przerwania czekanie na przerwanie
Planiści Planista długoterminowy (ang. long-term scheduler) lub planista zadań (ang. job scheduler) - wybiera procesy, które powinny być sprowadzone do pamięci z kolejki procesów gotowych Planista krótkoterminowy (ang. short-term scheduler) lub planista przydziału procesora (ang. CPU scheduler) - wybiera proces następny do wykonania z kolejki procesów gotowych i przydziela mu procesor
Planiści (c.d.) Planista krótkoterminowy jest wołany bardzo często (milisekundy) dlatego musi być bardzo szybki Planista długoterminowy jest wołany rzadko (sekundy, minuty) dlatego może nie być szybki Planista długoterminowy nadzoruje stopień wieloprogramowości (liczbę procesów w pamięci)
Planiści (c.d.) Proces może być opisany jako jeden z ograniczony przez we/wy (ang. I/O bound) - więcej czasu zajmuje we/wy niż dostęp do procesora ograniczony przez dostęp do procesora (ang. CPU bound) - więcej czasu zajmują obliczenia, we/wy sporadyczne Planista długoterminowy powinien dobrać mieszankę procesów (ang. process mix) zawierającą zarówno procesy ograniczone przez we/wy jak i procesor Planista średnioterminowy(ang. medium-term scheduler) - swapping (wymiana) w celu uzyskania lepszego doboru procesów
Planista średnioterminowy sprowadź do pamięci (swap in) usunięte procesy częściowo wykonane usuń z pamięci (swap out) kolejka procesów gotowych CPU koniec we/wy kolejki procesów oczekujących na we/wy
Przełączanie kontekstu Gdy procesor przełącza do innego procesu system musi zachować stan starego procesu i załadować zachowany stan nowego procesu. Czynność tę nazywamy przełączaniem kontekstu (ang. context switch) Przełączanie kontekstu jest ceną za wieloprogramowość; system operacyjny nie wykonuje wtedy żadnej użytecznej pracy Czas przełączenia kontekstu zależy od sprzętu (zwykle od 1 do 1000 milisekund)
Działania na procesach - tworzenie procesu Proces macierzysty (ang. parent process) tworzy nowy proces - potomka (ang. child process) i każdy nowy proces może tworzyć nowe procesy, które tworzą drzewo procesów Dzielenie zasobów proces macierzysty i potomek dzielą wszystkie zasoby proces macierzysty i potomek dzielą część zasobów proces macierzysty i potomek nie dzielą żadnych zasobów
Drzewo procesów w UNIXie proces root proces pagedaemon proces swapper proces init proces użytkownika 1 proces użytkownika 2 proces użytkownika 3
Tworzenie procesu (c.d.) Wykonanie proces macierzysty i potomek działają współbieżnie proces macierzysty czeka aż potomek zakończy Przestrzeń adresowa nowego procesu potomek jest kopią procesu macierzystego potomek ładuje do przestrzeni adresowej nowy program
Przykłady UNIX funkcja systemowa fork tworzy nowy proces zawierający kopię przestrzeni adresowej procesu pierwotnego funkcja systemowa execlp użyta po fork powoduje zastąpienie zawartości pamięci przez nowy program (ładuje plik binarny do pamięci niszcząc obraz pamięci zawierający wywołanie execlp) proces macierzysty czeka aż potomek skończy (funkcja systemowa wait) w kolejce procesów gotowych Przykład pod Cygwinem
Przykład - Unix #include <stdio.h> int main(void) { int pid; /* fork another process */ pid = fork(); if (pid < 0) { /* error occurred */ fprintf(stderr, "Fork Failed\n"); exit(-1); } else if (pid == 0) { /* child process */ execlp("/bin/ls","ls",null); } else { /* parent process */ /* parent will wait for the child to complete */ wait(null); } } printf("child Complete\n"); exit(0);
Przykład new.c int main() { } execlp("/bin/ps","ps",0); gcc -o new new.c./new ps
Przykład - prosty shell #define TRUE 1 while (TRUE) { /* pętla */ type_prompt( ); /* prompt */ read_command (command, parameters) /*czytaj komendę */ if (fork()!= 0) { /* proces potomny */ /* Kod rodzica */ waitpid( -1, &status, 0); /* czekaj */ } else { /* Kod potomka */ execve (command, parameters, 0); /* wykonaj komendę */ } }
Przykłady (c.d.) DEC VMS tworzy proces i ładuje do niego program Windows NT - oba modele duplikowanie przestrzeni adresowej procesu macierzystego proces macierzysty może określić nazwę programu do załadowania do przestrzeni adresowej nowego procesu
Kończenie procesu Proces kończy się (ang. terminate) wówczas, gdy wykona swoją ostatnią instrukcję i za pomocą funkcji systemowej exit poprosi system operacyjny aby go usunął a także aby przekazał dane wyjściowe z potomka do procesu macierzystego (za pośrednictwem funkcji systemowej wait wydanej w procesie macierzystym) wszystkie zaalokowane zasoby (pamięć fizyczna i wirtualna, otwarte pliki, bufory we/wy) odebrał potomkowi
Kończenie procesu (c.d.) Proces macierzysty wywołuje funkcję systemową abort bowiem potomek nadużył zasobów wykonywanie potomka stało się jałowe proces macierzysty kończy się system operacyjny nie pozwala potomkowi na działanie jeśli proces macierzysty kończy działanie system operacyjny wymusza zakończenie wszystkich potomków - kończenie kaskadowe (ang. cascading termination)
Zombie zombie.c #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main () { pid_t child_pid; } /* Create a child process. */ child_pid = fork (); if (child_pid > 0) { /* This is the parent process. Sleep for a minute. */ sleep (60); } else { /* This is the child process. Exit immediately. */ exit (0); } ps -al
Procesy współpracujące Procesy współbieżne mogą być niezależne (ang. independent) lub współpracujące (ang. cooperating) Procesy współpracujące mogą oddziaływać na inne procesy w systemie lub inne procesy w systemie mogą oddziaływać na nie Korzyści ze współpracy procesów dzielenie informacji przyspieszanie (obliczeń) modularność - możliwość konstruowania systemów wygoda - użytkownik może mieć wiele procesów
Problem producent-konsument Paradygmat procesów współpracujących: proces-producent wytwarza do bufora informację, którą proces-konsument zużywa (z bufora) nieograniczony bufor (ang. unbounded-buffer) - producent wytwarza nieustannie jednostki do nieograniczonego bufora ograniczony bufor (ang. bounded-buffer) - producent wytwarza jednostki do bufora ograniczonego rozmiaru (n), który konsument opróżnia Dostęp do bufora np. przy pomocy pamięci dzielonej (IPC)
Rozwiązanie problemu - bufor ograniczony Proces konsumenta i producenta korzystają z wspólnych zmiennych #define BUFFER_SIZE 10 typedef struct {... } item; item buffer[buffer_size]; int in = 0; int out = 0; # in - następne wolne miejsce w buffer # out - pierwsze zajęte miejsce w buffer # in=out - buffer jest pusty # in+1 mod n = out - buffer jest pełny
Proces producenta item nextproduced; while (1) { /* produce an item in nextproduced */ while (((in + 1) % BUFFER_SIZE) == out) ; /* do nothing */ buffer[in] = nextproduced; in = (in + 1) % BUFFER_SIZE; }
Proces konsumenta item nextconsumed; while (1) { while (in == out) ; /* do nothing */ } nextconsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; /* consume the item in nextconsumed */
Komunikacja międzyprocesowa Komunikacja międzyprocesowa (ang. interprocess-communication - IPC) udogodnienia systemu pozwalające współpracującym procesom na kontaktowanie się ze sobą System przekazywania komunikatów (ang. message system) - sposób realizacji komunikacji międzyprocesorowej pozwalający nie odwoływać się do zmiennych dzielonych
Komunikacja międzyprocesowa Komunikacja międzyprocesowa dostarcza dwóch operacji nadaj (komunikat) (ang. send (message)) odbierz(komunikat) (ang. receive(message)) Jeśli procesy P i Q chcą się skomunikować to muszą ustanowić łącze komunikacyjne nadawać i odbierać komunikaty Implementacja fizyczna (np. pamięć dzielona, szyna sprzętowa) logiczna (np. własności logiczne)
Problemy związane z implementacją Jak ustanawiać połączenia Czy łącze może być powiązane z więcej niż dwoma procesami? Ile może być łączy na każdą parę procesów Jaka jest pojemność łącza? Czy łącze ma obszar buforowy? Jak duży? Jaki jest rozmiar komunikatów (stały, zmienny)? Czy łącze jest jest jedno- czy dwukierunkowe Komunikacja (bez)pośrednia, (a)symetryczna?
Komunikacja bezpośrednia Proces musi jawnie nazwać odbiorcę nadaj(p,komunikat) - nadaj komunikat do procesu P odbierz(q,komunikat) - odbierz komunikat od procesu Q Własności łącza łącze jest ustanawiane automatycznie, do komunikowania wystarczy znajomość identyfikatorów łącze dotyczy dokładnie dwóch procesów między każdą parą procesów istnieje dokładnie jedno łącze łącze jest zwykle dwukierunkowe, ale może być jednokierunkowe
Komunikacja pośrednia Komunikaty są nadawane i odbierane za pomocą skrzynek pocztowych (ang. mailboxes) nazywanych także portami (ang. ports) każda skrzynka ma swój unikalny identyfikator procesy komunikują się jeśli mają wspólną skrzynkę Własności łącza łącze jest ustanawiane jedynie wtedy gdy procesy dzielą skrzynkę łącze może być związane z więcej niż dwoma procesami każda para procesów może mieć kilka łączy z których każdy odpowiada jakiejś skrzynce łącze może być jedno- lub dwukierunkowe
Komunikacja pośrednia (c.d) System operacyjny dostarcza mechanizmów do tworzenia nowej skrzynki nadawania i odbierania komunikatów za pomocą skrzynki likwidowania skrzynki Dzielenie skrzynki : P, Q, R dzielą skrzynkę A P nadaje; Q i R odbierają który proces otrzyma komunikat nadany przez P? Rozwiązanie zezwalać jedynie na łącza między dwoma procesami pozwalać najwyżej jednemu procesowi na odbiór pozwalać aby system wybrał i poinformował odbiorcę
Buforowanie Łącze ma pojemność określającą maksymalną liczbę komunikatów, które mogą w nim przebywać dlatego musimy mieć kolejkę komunikatów Metody implementacji kolejki pojemność zerowa - nadawca musi czekać aż odbiorca odbierze komunikat pojemność ograniczona - nadawca musi poczekać jeśli kolejka jest pełna pojemność nieograniczona - nadawca nigdy nie czeka
Sytuacje wyjątkowe Zakończenie procesu system musi powiadamiać o zakończeniu procesu Utrata komunikatów system powinien wykryć utratę komunikatu proces nadawczy powinien umieć powtórzyć komunikat system zawiadamia proces nadawczy Zniekształcenie komunikatów sumy kontrolne, sprawdzanie parzystości, CRC
System Mach System oparty na komunikatach nadawanych i odbieranych przez skrzynki pocztowe zwane portami Każde zadanie ma dwie specjalne skrzynki skrzynka jądra (ang. kernel mailbox) do komunikowania się z zadaniem skrzynka zawiadomień (ang. notify mailbox) do wysyłania zawiadomień o zdarzeniach Funkcje systemowe msg_send, msg_receive, msg_rpc (wysyła i czeka na odpowiedź), port_allocate (tworzy skrzynkę) przykład wykorzystania mechanizmu RPC do komunikowania między systemami via msg_rpc
System Mach (c.d.) Jeśli skrzynka jest pełna to wątek nadawczy czeka aż się zwolni miejsce w skrzynce czeka co najwyżej n mililsekund nie czeka czasowo przechowuje komunikat Słaba wydolność systemu powodowana kopiowaniem komunikatu od nadawcy do skrzynki a potem ze skrzynki do odbiorcy rozwiązanie: odwzorowanie przestrzeni adresowej nadawanego komunikatu na przestrzeń odbiorcy, można tak zrobić jedynie dla komunikatów systemowych
Windows 2000 Modularny system operacyjny, w którym programy użytkowe kontaktują się za pomocą mechanizmu przekazywania komunikatów Udogodnienie wywoływania procedur lokalnych (ang. local procedure call facility - LPC) służy do komunikacji między procesami na tej samej maszynie przypomina mechanizm RPC, ale jest zoptymalizowane wykorzystuje obiekt portu łączącego i komunikacyjnego
Windows 2000 (c.d.) Komunikacja klient zaopatruje się w uchwyt do obiektu portu łączącego podsystemu klient wysyła prośbę o połączenie serwer tworzy dwa prywatne porty komunikacyjne i przekazuje klientowi uchwyt do jednego z nich klient i serwer korzystają z odpowiednich uchwytów portowych w celu wysyłania komunikatów lub przywołań oraz nasłuchiwania odpowiedzi Trzy typy komunikacji zależnie od wielkości komunikatu
Komunikacja klient/serwer - implementacje Gniazda (ang. sockets) przykład w Javie: time-of-day serwer RPC (ang. Remote Procedure Calls) RMI (ang. Remote Method Invocation) przykład w Javie: time-of-day serwer
Klient - gniazda import java.net.*; import java.io.*; public class DateClient { public static void main(string[] args) throws IOException { InputStream in = null; BufferedReader bin = null; Socket sock = null; try { sock = new Socket("127.0.0.1",6013); in = sock.getinputstream(); bin = new BufferedReader(new InputStreamReader(in)); } } String line; while( (line = bin.readline())!= null) System.out.println(line); } catch (IOException ioe) { System.err.println(ioe); } finally { sock.close(); }
import java.net.*; import java.io.*; public class DateServer { public static void main(string[] args) throws IOException { Socket client = null; ServerSocket sock = null; try { sock = new ServerSocket(6013); // now listen for connections while (true) { client = sock.accept(); System.out.println("server = " + sock); System.out.println("client = " + client); } } // we have a connection PrintWriter pout = new PrintWriter(client.getOutputStream(),true); // write the Date to the socket pout.println(new java.util.date().tostring()); pout.close(); client.close(); } } catch (IOException ioe) { System.err.println(ioe); } finally { if (sock!= null) sock.close(); if (client!= null) client.close(); }
RPC Wywołania procedur między systemami Namiastka (ang. stub, proxy) po stronie klienta do przekazania parametrów zdalnej procedurze oraz po stronie serwera do wywołania procedury Klient: namiastka procedury zdalnej lokalizuje port na serwerze i przetacza (ang. marshall) opakowane parametry i komunikaty Serwer: namiastka procedury na serwerze rozpakowuje parametry, wywołuje procedurę i zwraca wynik w ten sam sposób
Architektura RPC aplikacja klienta zdalna aplikacja serwera odpowiedź lokalna odpowiedź lokalna odpowiedź lokalna lokalne wywołanie procedury lokalne wywołanie procedury aplikacja lokalna lub system operacyjny namiastka mechanizm RPC przetaczanie RPC namiastka mechanizm RPC
RPC - implementacja Sun użytkownik zleca jądru wysłanie komunikatu RPC do procedury X jądro wysyła komunikat do demona randezvous z pytaniem o numer portu from: klient; to: serwer port: randezvous re: adres dla RPC X randezvous otrzymuje komunikat i przygotowuje odpowiedź jądro wstawia port P do komunikatu RPC użytkownika from: serwer; to: klient port: kernel; re: adres adres dla RPC X <P> randezvous odpowiada klientowi: port P jądro wysyła komunikat RPC użytkownika from: klient; to: serwer port: P ; <treść> demon nasłuchujący na porcie P otrzymuje komunikat jądro otrzymuje odpowiedź i przekazuje ją do użytkownika from: RPC; port: P to: klient; port: jądro <wyniki> demon obsługuje żądanie i przygotowuje wyniki klient komunikaty serwer
RMI Realizacja RPC na maszynie Javy Pozwala jednej maszynie wywołać metodę na zdalnym obiekcie Klient: namiastka (ang. stub) tworzy paczkę (ang. parcel) zawierającą nazwę metody wywoływanej na serwerze oraz parametry i przetacza je do serwera Serwer: szkielet (ang. skeleton) odpowiada za rozpakowanie parametrów i wywołanie metody
RMI - przetaczanie klient zdalny obiekt val=serwer.metoda(a,b) boolean metoda(obiekt x, Obiekt y) { implementacja metody metoda........... } namiastka szkielet A, B metoda zmienna boolowska
Serwer - implementacja import java.rmi.*; import java.rmi.server.unicastremoteobject; import java.util.date; public class RemoteDateImpl extends UnicastRemoteObject implements RemoteDate { public RemoteDateImpl() throws RemoteException { } public Date getdate() throws RemoteException { return new Date(); } public static void main(string[] args) { try { /* we only need to install this to distribute classes * System.setSecurityManager(new RMISecurityManager());*/ RemoteDate dateserver = new RemoteDateImpl(); // Bind this object instance to the name "DateServer" Naming.rebind("DateServer", dateserver); //Naming.rebind("//localhost:1099/DateServer", dateserver); } } System.out.println("DateServer bound in registry"); } catch (Exception e) { System.err.println(e); }
Serwer - kompilacja, rejestracja RemoteDate.java import java.util.date; import java.rmi.*; public interface RemoteDate extends Remote { public abstract Date getdate() throws RemoteException; } javac RemoteDate*.java rmic RemoteDateImpl rmiregistry &
Klient - kompilacja RMIClient.java import java.rmi.*; public class RMIClient { public static void main(string args[]) { try { /* We only need this for loading remote classes * System.setSecurityManager(new RMISecurityManager());*/ String host = "rmi://127.0.0.1/dateserver"; RemoteDate dateserver = (RemoteDate)Naming.lookup(host); System.out.println(dateServer.getDate()); } catch (Exception e) { System.err.println(e); } } } cp../server/remotedateimpl_stub.class. cp../server/remotedate.class. javac RMIClient.java
RMI - uruchomienie (Cygwin) W oknie serwera java RemoteDateImpl DataServer bound in registry netstat W oknie klienta netstat port 1099 java RMIClient Thu Mar 18 09:55:29 CET 2004 Ctrl-C w oknie serwera
Wątki Wątek (ang. thread) nazywany niekiedy procesem lekkim (ang. lightweight process - LWP) jest podstawową jednostką wykorzystania procesora. W skład tej jednostki wchodzą licznik rozkazów zbiór rejestrów obszar stosu
Wątki (c.d.) Wątek współużytkuje z innymi równorzędnymi wątkami sekcję kodu sekcję danych zasoby systemu (takie jak otwarte pliki i sygnały) zwane wspólnie zadaniem (ang. task) Proces tradycyjny lub ciężki (ang. heavyweight) to zadanie o jednym wątku
Wątki - przykład #include <pthread.h> #include <stdio.h> int sum; /* this data is shared by the thread(s) */ void *runner(void *param); /* the thread */ main(int argc, char *argv[]) { pthread_t tid; /* the thread identifier */ pthread_attr_t attr; /* set of attributes for the thread */ if (argc!= 2) { fprintf(stderr,"usage: a.out <integer value>\n"); exit(); } if (atoi(argv[1]) < 0) { fprintf(stderr,"argument %d must be non-negative\n",atoi(argv[1])); exit(); } /* get the default attributes */ pthread_attr_init(&attr);
Wątki - przykład (c.d.) /* create the thread */ pthread_create(&tid,&attr,runner,argv[1]); /* now wait for the thread to exit */ pthread_join(tid,null); printf("sum = %d\n",sum); } /** * The thread will begin control in this function */ void *runner(void *param) { int upper = atoi(param); int i; sum = 0; if (upper > 0) { for (i = 1; i <= upper; i++) sum += i; } } pthread_exit(0);
Procesy wielowątkowe kod dane pliki kod dane pliki rejestry stos rejestry rejestry rejestry stos stos stos
Wątki - korzyści W zadaniu wielowątkowym (ang. multithreaded task) w czasie gdy wątek serwer jest zablokowany i oczekuje, drugi wątek tego samego zadania może się wykonywać współpraca wielu wątków w tym samym zadaniu zwiększa przepustowość oraz polepsza wydajność systemu program użytkowy wykorzystujący wspólny bufor (np. producent-konsument) stosuje wątki
Przykład RPC - jeden wątek czas żądanie RPC żądanie RPC proces serwer 1 serwer 2 zablokowany, oczekuje na odpowiedź od RPC zablokowany, oczekuje na procesor używany przez wątek B wykonywany
Przykład RPC - dwa wątki czas żądanie RPC serwer 1 wątek A proces wątek B żądanie RPC serwer 2 zablokowany, oczekuje na odpowiedź od RPC zablokowany, oczekuje na procesor używany przez wątek B wykonywany
Wątki a proces Zablokowanie procesu powoduje zablokowanie wszystkich jego wątków albowiem dzielą one tę samą przestrzeń adresową Zakończenie procesu wiąże się z zakończeniem wszystkich jego wątków
Wątki - działanie Wątki mogą tworzyć wątki potomne (ang. spawn) i blokować (ang. block) się do czasu zakończenia wywołań systemowych Działanie wątków przypomina działanie procesów (gotowe, zablokowane, aktywne (ang. unblock), kończące (ang. finish)) jednak wątki nie są niezależne od siebie np. oczekiwanie na we/wy przechowanie kontekstu: rejestry, licznik i stos wybranie nowego wątku z kolejki wątków gotowych
Typy wątków Wątki (ang. kernel-level) obsługiwane przez jądro Mach, OS/2, Windows 9x/NT/2K, Linux, BeOS Wątki tworzone na poziomie użytkownika (ang. user-level) za pomocą funkcji bibliotecznych system Andrew POSIX: Pthreads, Mach: C-threads, Solaris 2: UI-threads zaleta: szybsze przełączanie, wada: planowanie wątków Hybrydowe podejście - Solaris 2 Wątki zarządzane przez JVM
Relacje międzywątkowe przestrzeń użytkownika biblioteka wątków biblioteka wątków P przestrzeń jądra P P wątki poziomu użytkownika wątki poziomu jądra wątki mieszane wątek poziomu użytkownika wątek poziomu jądra P proces P
Sposoby odwzorowań wątków Wiele do jednego (ang. Many-to-One) Jeden do jednego (ang. One-to-One) OS/2, Windows 9x/NT/2K Wiele do wielu (ang. Many-to-Many) Solaris 2, IRIX, HP-UX, Windows NT/2K (ThreadFiber)
Many-to-One wątek użytkownika wątek jądra
One-to-one wątek użytkownika wątek jądra
Many-to-many wątek użytkownika wątek jądra
Solaris 2 - wątki Solaris 2 jest klonem UNIXa realizującym zarówno wątki na poziomie jądra jak i użytkownika, symetryczne wieloprzetwarzanie i planowanie w czasie rzeczywistym Solaris 2 definiuje pośredni poziom wątków: między wątkami użytkownika i jądra występują procesy lekkie w skrócie LWP którymi zawiaduje biblioteka wątków Każde zadanie ma przynajmniej jeden proces lekki (LWP) do którego są podłączone wątki poziomu użytkownika
Solaris 2 - wątki (c.d.) Zasoby potrzebne wątkom wątek jądrowy (podlega planowaniu i może być przypięty (ang. pinned) do procesora) mała struktura danych i stos przełączanie wątków nie wymaga informacji o pamięci przełączanie stosunkowo szybkie proces lekki (LWP) blok kontrolny procesu z danymi rejestrowymi informacje rozliczeniowe informacje dotyczące pamięci przełączanie kontekstu dość wolne wątek użytkownika stos i licznik rozkazów szybkie gdyż jądro nie jest angażowane w ich planowanie
Solaris 2 - wątki (c.d.) wątek użytkownika proces lekki wątek jądrowy procesor
Java - wątki Język Java dostarcza mechanizmów do tworzenia i zarządznie wątkami Rozszerzenie klasy Thread http://people.westminstercollege.edu/faculty/ggagne/osc/index. html Zarządzanie wątkami przez JVM Odwzorowanie wątków: jądro - JVM W9x/NT/2K - one-to-one Solaris 2 - many-to-one (green threads)
Podsumowanie (1) Proces to wykonywany program, który może znajdować się w jednym z następujących stanów: nowy, gotowy, aktywny, oczekiwania lub zakończony Proces, który nie jest wykonywany jest umieszczany w kolejce oczekujących na coś kolejka zamówień we/wy kolejka procesów gotowych (oczekujących na procesor) Proces jest reprezentowany przez blok kontrolny procesu, który to blok jest elementem listy bloków kontrolnych procesów gotowych
Podsumowanie (2) Planowanie długoterminowe - dopuszczanie procesów do rywalizacji o procesor krótkoterminowe - wybieranie procesów gotowych Procesy mogą działać współbieżnie i być niezależne lub współpracować Procesy współpracujące komunikują się za pomocą pamięci dzielonej za pomocą systemu komunikatów
Podsumowanie (3) Procesy współpracujące, które dzielą logiczną przestrzeń adresową można implementować w postaci procesów lekkich, czyli wątków Wątek jest podstawową jednostką wykorzystania procesora, która dzieli z innymi równorzędnymi wątkami swoją sekcję kodu i danych oraz zasoby systemu operacyjnego - łącznie nazywa się to zadaniem Wykorzystanie wątków pozwala na uniknięcie kosztownego przełączania kontekstu w procesach ciężkich