Systemy operacyjne
description
Transcript of Systemy operacyjne
Systemy operacyjne
Wykład 6bWątki, mechanizmy IPC
dr inż. Wojciech BienieckiInstytut Nauk Ekonomicznychi Informatykihttp://wbieniec.kis.p.lodz.pl/pwsz 1
Wielowątkowość
2
Jeden proces może wykonywać się w wielu współbieżnych wątkach (ang. thread).
Każdy wątek (inna nazwa: proces lekki, ang. lightweight process)
– Ma swój własny stan (Aktywny, Gotowy, Zablokowany, ... )
– Ma swoje wartości rejestrów i licznika rozkazów.
– Ma swój własny stos (zmienne lokalne funkcji).
– Ma dostęp do przestrzeni adresowej, plików i innych zasobów procesu. Wszystkie wątki procesu współdzielą te zasoby.
Operacje zakończenia, zawieszenia procesu dotyczą wszystkich wątków.
Przełączanie pomiędzy równoprawnymi wątkami jest „tanie” (szybsze) w porównaniu z przełączaniem pomiędzy tradycyjnymi procesami (nie trzeba przełączać kontekstu pamięci).
Wątki zyskują na popularności ponieważ – mając pewne cechy ciężkich procesów – są efektywniejsze w działaniu.
Procesy są od siebie izolowane, wątki nie !
Schemat procesu i wątków
3
ProcesPrzestrzeń adresowaOtwarte plikiProcesy potomneObsługa sygnałówSprawozdawczośćZmienne globalne
Wątek 1Licznik rozkazówRejestryStos i wskaźnik stosuStan
Wątek 2Licznik rozkazówRejestryStos i wskaźnik stosuStan
Wątek 2Licznik rozkazówRejestryStos i wskaźnik stosuStan
Proces z wątkami
4
Standardowy UnixMS-DOS
Linux, MS-Windows, POSIX, OS/2, Solaris
Cechy wątków
5
Zalety
– Utworzenie i zakończenie wątku zajmuje znacznie mniej czasu niż w przypadku procesu
WadyŹle zachowujący się wątek może zakłócić pracę innych wątków tego samego procesu. W przypadku dwóch procesów o odrębnych przestrzeniach adresowych nie jest to możliwe
– Możliwość szybkiego przełączania kontekstu pomiędzy wątkami tego samego procesu
– Możliwość komunikacji wątków bez pośrednictwa systemu operacyjnego
– Możliwość wykorzystania maszyn wieloprocesorowych
Wątki na poziomie użytkownikaang. user-level threads
6
System operacyjny nie jest świadom istnieniawątków.
Zarządzanie wątkami jest przeprowadzane przez bibliotekę w przestrzeni użytkownika.
Przykład: Wątek A wywołuje funkcję read. Standardowo funkcja systemowa read jestsynchroniczna (usypia do momentu zakończenia operacji). Jednak implementacja w bibliotece wywołuje wersję asynchroniczną i przełącza się do wątku B.
Rozwiązanie to jest szybkie, ma jednak wady:– Dwa wątki nie mogą się wykonywać współbieżnie na dwóch różnych procesorach.– Nie można odebrać procesora jednemu wątkowi i przekazać drugiemu
Wątki na poziomie jądraang. kernel-level threads
7
Wątek jest jednostką systemu operacyjnego.
Wątki podlegają szeregowaniu przez jądro.
W systemie SMP* wątki mogą się wykonywać na różnych procesorach – przetwarzanie równoległe.
Windows i Linux wykorzystują tę metodę.
*) SMP (ang. Symmetric Multiprocessing, przetwarzanie symetryczne) - architektura komputerowa, która pozwala na znaczne zwiększenie mocy obliczeniowej systemu komputerowego poprzez wykorzystanie dwóch lub więcej procesorów do jednoczesnego wykonywania zadań.
Przykład użycia wątków: Serwer WWW
8
while(TRUE) { getNextRequest(&buf); handoffWork(&buf);}
while(TRUE) { waitForWork(&buf); lookForPageInCache(&buf,&page); if(pageNotInCache(&page)) { readPageFromDisk(&buf,&page); } returnPage(&page);}
Technika puli wątków: Zamiast tworzyć nowy wątek do obsługi kolejnego żądania, mamy zbiór wątków stale gotowych do działania. Nie ponosimy kosztu tworzenia i usuwania wątków.
Możliwe problemy z wątkami
9
Przykład:
errno to uniksowy mechanizm zgłaszania błędów przez funkcje libc, a w szczególności jądra.
Jeśli funkcja zakończy się błędem, sygnalizuje to zwracając zwykle -1 lub NULL.Program powinien wtedy zajrzeć do zmiennej globalnej errno, żeby dowiedzieć się jaki dokładnie błąd wystąpił.
Jeśli funkcja zakończy się pomyślnie zawartość errno nie jest zdefiniowana.
Możliwe problemy z wątkami
10
#include <stdio.h> /* fprintf */#include <errno.h> /* errno */#include <stdlib.h> /* malloc, free, exit */#include <string.h> /* strerror */
extern int errno;
int main( void ){ /* deklaracja wskaźnika do tablicy o pojemności 2GB */ char *ptr = malloc( 2000000000UL ); if ( ptr == NULL ){ puts("malloc failed"); puts(strerror(errno)); } else { /* Pomyślnie zaalokowano tablicę */ free( ptr ); } exit(EXIT_SUCCESS); /* exiting program */}
Możliwe problemy z wątkami
11
W standardowej bibliotece C, w wersji wielowątkowej, errno jest implementowane jako prywatna zmienna globalna (nie współdzielona z innymi wątkami)
Gdy kilka wątków jednocześnie wywołuje funkcje malloc/free - może dojść douszkodzenia globalnych struktur danych (listy wolnych bloków pamięci)Potrzeba synchronizacji => może prowadzić do spadku wydajności
Inne problemy z wątkami
12
Proces otrzymuje sygnał: – Wszystkie wątki otrzymują sygnał – Wybrany wątek otrzymuje sygnał – Wątek aktualnie aktywny otrzymuje sygnał
Proces wykonuje fork. – Czy duplikować jedynie działający wątek, czy też wszystkie wątki ?
Proces wywołuje exit. – Zakończyć proces czy też jedynie aktywny wątek ?
Anulowanie wątku (ang. cancellation). – Wykonać natychmiast . – Wątek co jakiś czas sprawdza czy nie został anulowany
Standard POSIX zawiera odpowiedzi na powyższe problemy.
Implementacje wątków – POSIX
13
void *thread(void *param) {// tu kod wątku// możemy przekazać wynikreturn NULL;}
int main(){ pthread_t id;// Parametr przekazywany wątkowi void *param=NULL; pthread_create(&id,NULL,&thread,param);// Funkcja thread w odrębnym wątku współbieżnie// z main. id przechowuje identyfikator wątkuvoid *result;// Czekaj na zakończenie wątkupthread_join(id,&result);// Wynik w result, zamiast &result można// przekazać NULL}
Funkcja pthread_create tworzy nowy wątek. Rozpoczyna on pracę od funkcji, której adres przekazano jako trzeci argument.
Funkcja pthread_join usypiawywołujący ją wątek do momentu, kiedy wątek o identyfikatorze przekazanym jako pierwszy argument zakończy pracę.
Zakończenie pracy wątku – powrót z funkcji, która go rozpoczyna.
Obsługa wątków w POSIX
14
W Linuxie wątki mogą być tworzone poprzez funkcję pthread_create().
W Linuxie wątki mogą być także tworzone poprzez funkcję clone().
Podobnie jak fork() funkcja pthread_create() tworzy nowy kontekst wykonywania.Nowy wątek dzieli z tworzącym go procesem PID, przestrzeń adresową, deskryptory plików itp.
Wątek kończy swoje działanie w momencie kiedy skończy się wykonywanie funkcji przekazanej jako parametr do pthread_create().
Różnica pomiędzy pthread_create() a clone(). Można wskazać:
Wątek kończy swoje działanie w momencie kiedy skończy się wykonywanie funkcji przekazanej jako parametr do clone().
które typy zasobów będą a które nie będą współdzielone (np. identyfikatory plików, uchwyty sygnałów itp.).
jaki będzie posiadała PID procesu macierzystego
jaki sygnał (jeśli w ogóle) będzie dostarczał informacji twórcy wątku o zakończeniu wątku .
gdzie będzie umieszczony stos nowego wątku.
Włókna – Win32 API
15
Włókna (ang. fibers) koncepcyjnie są to miniwątki, podobnie jak wątki dysponują własnym kontekstem wykonawczym – posiadają własny stos i chronią zawartość rejestrów procesora.
Włókna w odróżnieniu od wątków nie są wywłaszczane przez system operacyjny z czasu procesora – za przełączanie włókien jest odpowiedzialna sama aplikacja.
Zadania - Windows
16
W systemie Windows 2000 i późniejszych istnieje możliwość zgrupowania pewnej liczby procesów i zarządzania nimi w ramach tak zwanego zadania (ang. job).
Funkcje pozwalające zarządzać zadaniami dają większe możliwości kontroli niż standardowe funkcje dedykowane procesom.
Zadaniom można nakładać ograniczenia takie jak określenie maksymalnego czasu, w trybie użytkownika, jaki jest przyznawany każdemu procesowi (proces używający więcej czasu jest kończony), maksymalny czas, w trybie użytkownika, przyznany wszystkim procesom zadania itp.
Do umieszczenia procesu w zadaniu służy specjalna funkcja systemu:
BOOL AssignProcessToJobObject(HANDLE hJob, HANDLE hProcess);
Umieszczenie kilku procesów w zadaniu umożliwia między innymi ich równoczesne zakończenie. Dodatkowo istnieje możliwość powiadamiania o tym co się dzieje w zadaniu, np. który z procesów się zakończył i czemu.
Powinowactwo
17
Powinowactwo (ang. thread affinity) – powiązanie procesu/wątku ze zdefiniowaną jednostką centralną
Istnieją dwa modele powinowactwa:
słabe powinowactwo – nie ma gwarancji, że wątek, który wykonywał się na procesorze X będzie ponownie wykonywany na tym samym procesorze;
silne powinowactwo – system gwarantuje, że dany proces będzie się wykonywał tylko na procesorach wskazanych przez użytkownika.
System Windows 2000 standardowo stosuje słabe powinowactwo. Istnieje grupa funkcji systemowych, która pozwala wymusić silne powinowactwo. Silne powinowactwo jest szczególnie pożądane w komputerach o architekturze NUMA (ang. Non-Uniform Memory Access – nie jednolity dostęp do pamięci).
Metody komunikacji międzyprocesowej
18
Komunikacja międzyprocesowa (ang. Inter-Process Communication — IPC) – sposoby komunikacji pomiędzy procesami systemu operacyjnego.
Pojęcie IPC może odnosić się do wymiany informacji w systemach rozproszonych (klastrów, systemów odległych połączonych siecią).
Mechanizmy IPC opierają się na budowaniu w pamięci lub na dysku dynamicznych struktur, używanych do transmisji komunikatów pomiędzy procesami
Metody komunikacji międzyprocesowej
19
pliki i blokady – najprostsza i najstarsza forma IPC
Lista metod IPC obejmuje:
sygnały (ang. signals) – czasami znane jako przerwania programowe
łącza nienazwane (ang. pipes) – znane też jako łącza komunikacyjnełącza nazwane (ang. named pipes) – znane też jako nazwane łącza komunikacyjne
kolejki komunikatów (ang. message queues) umożliwiają przekazywanie określonych porcji danych
pamięć dzielona (ang. shared memory) umożliwiają współdzielenie kilku procesom tego samego fragmentu wirtualnej przestrzeni adresowej
semafory (ang. semaphores) umożliwiają synchronizacje procesów w dostępie do współdzielonych zasobów (np. do pamięci współdzielonej)
gniazda Uniksa (ang. Unix domain sockets)gniazda (ang. sockets)
RPC (ang. Remote Procedure Call) – zdalne wywoływanie procedur.
Pliki zwykłe w UNIX/LINUXJądro systemu operacyjnego UNIX udostępnia dwie operacje na plikach realizowane odpowiednio przez funkcje systemowe
Odczyt – funkcja readZapis – funkcja write
Z punktu widzenia jądra w systemie UNIX plik nie ma żadnej struktury – jest traktowany jako tablica bajtów. Operacje odczytu lub zapisu mogą dotyczyć dowolnego fragmentu pliku, określonego z dokładnością do bajtu.
Podawanie nazwy pliku przy każdym odwołaniu do niego wymagałoby przeszukiwania katalogów w celu jego odnalezienia.Dlatego wprowadzono została funkcję systemową open, której zadaniem jest zaalokowanie niezbędnych zasobów w jądrze, umożliwiających wykonywanie dalszych operacji na pliku bez potrzeby przeszukiwania katalogów.
Plik w UNIX identyfikowany jest przez nazwę.
Pliki zwykłe w UNIX
Funkcja open zwraca deskryptor (liczba), który będzie przekazywany jako parametrem dla funkcji systemowych związanych z operacjami na otwartych plikach.
Standardowo zajęte są deskryptory:0 – standardowe wejście, 1 – standardowe wyjście2 –standardowe wyjście diagnostyczne
Przy otwieraniu pliku przekazywany jest tryb otwarcia, określający dopuszczalne operacje, jakie można wykonać w związku z tym otwarciem, np. tylko zapis, tylko odczyt lub zapis i odczyt.Tryb otwarcia może mieć również wpływ na sposób wykonania tych operacji, np. każda operacja zapisu
Jądro systemu operacyjnego dostarcza też mechanizm tworzenia plików – dostępny przez funkcję systemową creat, która tworzy plik i otwiera go w trybie do zapisu, zwracając odpowiedni deskryptor.
Pliki zwykłe w UNIXTworzenie i otwieranie plików realizowane jest za pomocą funkcji:
open - otwarcie pliku (uogólniona funkcja open umożliwia również utworzenie pliku)
creat - utworzenie pliku i otwarcie do zapisu
dup - utworzenie kopii deskryptora i nadanie jej pierwszego wolnego numeru z tablicy otwartych plików
dup2 - utworzenie kopii deskryptora, umożliwiające określenie jej identyfikatora przez użytkownika
close - zamknięcie deskryptora otwartego pliku,
unlink - usunięcie dowiązania do pliku
Operacje na plikach realizowane są za pomocą funkcji:read - odczyt fragmentu pliku,
write - zapis fragmentu pliku,
lseek - przesunięcie wskaźnika bieżącej pozycji
Powyższe funkcje zdefiniowane są w pliku nagłówkowym fcntl.h.
Struktury danych w jądrze systemu związane z otwartymi plikami
23
Łącza komunikacyjneŁącza w UNIX są plikami specjalnymi.Są podobne do plików zwykłych – posiadają swój i-węzeł, posiadają bloki z danymi, na otwartych łączach można wykonywać operacje zapisu i odczytu.
Czym różnią się od plików zwykłych
• ograniczona liczba bloków – łącza mają rozmiar 4KB – 8KB w zależności od konkretnego systemu,
• dostęp sekwencyjny – na łączach można wykonywać tylko operacje zapisu i odczytu, ale nie można wykonywać funkcji lseek)
• sposób wykonywania operacji zapisu i odczytu – dane odczytywane z łącza są zarazem usuwane (nie można ich odczytać ponownie)
• proces jest blokowany w funkcji read na pustym łączu i w funkcji write, jeśli w łączu nie ma wystarczającej ilości wolnego miejsca, żeby zmieścić zapisywany blok
Łącza komunikacyjne – cechy wspólne i różnice
Łącze nazwane (tzw kolejki FIFO).
Procesy, które chcą komunikować się za pomocą łącza nienazwanego, muszą znać jego deskryptor.
Łącze nienazwane (tzw. potok)
Posiada dowiązanie w systemie plików (istnieje jako plik w jakimś katalogu)
Może być identyfikowane przez nazwę
Po zamknięciu pozostaje przydzielony i-węzeł, ale wszystkie jego bloki na dysku są zwalniane.
nie ma dowiązania w systemie plików – istnieje tylko tak długo, jak jest otwarte
Jest identyfikowane tylko przez deskryptory
Po zamknięciu wszystkich jego deskryptorów przestaje istnieć (zwalniany jest jego i-węzeł i wszystkie bloki)
Przykład użycia łącza nazwanego
26
Utworzone metodą mkfifo łącze musi zostać otwarte przez użycie funkcji open.
Funkcja ta musi zostać wywołana przynajmniej przez dwa procesy w sposób komplementarny, tzn. jeden z nich musi otworzyć łącze do zapisu, a drugi do odczytu.
Odczyt i zapis danych z łącza nazwanego odbywa się za pomocą funkcji read i write
mkfifo("kolejka",0666);
desc = open("kolejka" , O_RDONLY); desc = open("kolejka" , O_WRONLY);
read(desc);
close(desc);
unlink("kolejka");
write(desc);
close(desc);
Użycie łączy nienazwanych
27
Sygnały
28
Sygnałem nazywamy asynchroniczne zdarzenie skierowane do procesu. Otrzymanie sygnału przez proces oznacza, że pojawiło się jakieś zdarzenie wyjątkowe, wymagające natychmiastowej reakcji ze strony procesu.
od innego procesu (np. SIGINT, SIGKILL)
od jądra (np. SIGPIPE, SIGCHLD, SIGALRM)
od jądra, ale przez wyjątek sprzętowy (np. SIGSEGV, SIGBUS)
Reakcja procesu na otrzymany sygnał
Wykonanie akcji domyślnej – najczęściej zakończenie procesu z ewentualnym zrzutem zawartości segmentów pamięci na dysk, czasami zignorowanie sygnału,
Zignorowanie sygnału
Przechwycenie sygnału tj. podjęcie akcji zdefiniowanej przez użytkownika
Sygnały w systemie Unix
29Funkcje obsługujące sygnały zawarte są w bibliotece <signal.h>
Sygnały czasu rzeczywistego
30
W Posix dostępne są również sygnały czasu rzeczywistego (realtime, RT)W linuxie mają one wartości 34 – 64.
Sygnały czasu rzeczywistego charakteryzują się tym, że:
● Wielokrotne wystąpienie tego samego sygnału nie powoduje „zlepiania” w jeden sygnał
● Gdy do kolejki trafiają wielokrotne, nieblokowane sygnały czasu rzeczywistego to sygnały z niższym numerem mają wyższy priorytet.
● Sygnały RT przekazują nie tylko nr sygnału ale także: strukturę siginfo_t oraz kontekst.
● Sygnały są kolejkowane
Ważniejsze funkcje systemowe dla sygnałów
31
Kolejka komunikatów
32
Kolejki komunikatów to specjalne listy (kolejki) w jądrze, zawierające odpowiednio sformatowane dane i umożliwiające ich wymianę poprzez dowolne procesy w systemie. Istnieje możliwość umieszczania komunikatów w określonych kolejkach (z zachowaniem kolejności ich wysyłania przez procesy) oraz odbierania komunikatu na parę rożnych sposobów (zależnie od typu, czasu przybycia itp.).
Kolejka komunikatów
33
Dodatkowo, każdej kolejce komunikatów przydziela sie dwie kolejki typu wait_queue, na których śpią procesy zawieszone podczas wykonywania operacji czytania bądź pisania do danej kolejki.
Za każdą kolejkę komunikatów odpowiada jedna struktura typu msqid_ds
Komunikaty danej kolejki przechowywane są na liście, której elementami są struktury typu msg
każda z nich posiada informacje o typie komunikatu, wskaźnik do następnej struktury msg oraz wskaźnik do miejsca w pamięci, gdzie przechowywana jest właściwa treść komunikatu
Obsługa kolejki komunikatów
34
Kolejki komunikatów umożliwiają przesyłanie pakietów danych, nazywanych komunikatami, pomiędzy różnymi procesami.Sam komunikat jest zbudowany jako struktura msgbuf, jego definicja znajduje się w pliku <sys/msg.h>:
/* message buffer for msgsnd and msgrcv calls */struct msgbuf { long mtype; /* typ komunikatu */ char mtext[1]; /* tresc komunikatu */};
Każdy komunikat ma określony typ i długość. Typ komunikatu nadaje proces inicjujący komunikat.Komunikaty są umieszczane w kolejce w kolejności ich wysyłania.Nadawca może wysyłać komunikaty, nawet gdy żaden z potencjalnych odbiorców nie jest gotów do ich odbioru.Komunikaty są w takich przypadkach buforowane w kolejce oczekiwania na odebranie.Przy odbiorze komunikatu, odbiorca może oczekiwać na pierwszy przybyły komunikat lub na pierwszy komunikat określonego typu.Komunikaty w kolejce są przechowywane nawet po zakończeniu procesu nadawcy, tak długo, aż nie zostaną odebrane lub kolejka nie zostanie zlikwidowana.
Pamięć współdzielona
35
jest specjalnie utworzonym segmentem wirtualnej przestrzeni adresowej, do którego dostęp może mieć wiele procesów. Jest to najszybszy sposób komunikacji pomiędzy procesami.
Schemat korzystania z pamięci współdzielonej
jeden z procesów tworzy segment pamięci współdzielonej, dowiązuje go powodując jego odwzorowanie w bieżący obszar danych procesu, opcjonalnie zapisuje w stworzonym segmencie dane.
inne procesy mogą odczytywać i/lub zapisywać wartości w pamięci współdzielonej.
Każdy proces uzyskuje dostęp do pamięci współdzielonej względem miejscawyznaczonego przez jego adres dowiązania, stąd każdy proces korzystając z tych samych danych używa innego adresu dowiązania.
Kończąc korzystanie z segmentu pamięci proces może ten segment odwiązać, czyli usunąć jego dowiązanie. Kiedy wszystkie procesy zakończą korzystanie z segmentu pamięci współdzielonej, za jego usunięcie najczęściej odpowiedzialny jest proces, który segment utworzył.
Semafory
36
Semafor to struktura danych wspólna dla kilku procesów.
Służy do synchronizowania kilku procesów korzystających ze wspólnego zasobu – zapobiega sytuacjom hazardowym– może zapobiec zakleszczeniu lub zagłodzeniu procesów.
Semafor to liczba całkowita nieujemna przechowywana w jądrze systemu skojarzona z zasobem o wartości równej liczbie dostępnych zasobów tego typu.
W Uniksie mamy dostępneSemafory Systemu VSemafory Posiksowe nazwaneSemafory Posiksowe w pamięci wspólnej
Proces, który żąda zasobu sprawdza wartość semafora
– wartość dodatnia – zasób jest dostępny. Przed rozpoczęciem korzystania z zasobu proces zmniejsza wartość semafora.
– wartość zerowa – nie ma wolnych zasobów i proces musi czekać.
– zwolnienie zasobu przez proces – zwiększenie wartości semafora i wysłanie powiadomienia do kolejki procesów oczekujących na zasób
Porównanie semaforów i muteksów
37
pthread_mutex_lock(&mutex);/*********************//* sekcja krytyczna *//*********************/pthread_mutex_unlock(&mutex);
sem_wait(&sem);/*********************//* sekcja krytyczna *//*********************/sem_post(&sem);
Niemal identyczne zachowanie.
Jednak odblokowanie muteksu może dokonać tylko wątek który go zablokował.
Wywołanie odblokowania muteksu więcej niż 1 raz nie jest pamiętane.
Muteksy używamy tylko do synchronizacji wątków.
Semafory używamy do synchronizacji wątków i procesów
Przypadki wykorzystania semaforów
38
Literatura
39
Ważniak – laboratorium z systemów operacyjnychhttp://wazniak.mimuw.edu.pl/index.php?title=Systemy_operacyjne#Laboratorium
Wojciech Kwedlo, Wykład z Systemów Operacyjnych Wydział Informatyki Politechniki Białostockiejhttp://aragorn.pb.bialystok.pl/~wkwedlo/OS-Slides-new.html
dr inż. Jerzy Ułasiewicz Programowanie aplikacji współbieżnych – Sygnały i ich obsługahttp://www.zak.ict.pwr.wroc.pl/ulasiewicz/
dr Anna Kobusińska, Politechnika Poznańska. Materiały dydaktycznehttp://www.cs.put.poznan.pl/akobusinska/
dr inż. Paweł Paduch, Katedra Informatyki Politechniki Świętokrzyskiej w Kielcach Wykład z Programowania współbieżnegohttp://achilles.tu.kielce.pl/Members/ppaduch/
Beej's Guide to Unix IPChttp://beej.us/guide/bgipc/
Robert Love: Linux. Programowanie systemowe. Helion 2008
Stevens R.W.: Programowanie w środowisku systemu UNIX. WNT, 2002
Havilland K., Gray D., Salama B.: Unix - programowanie systemowe. ReadMe, 1999