42. Stany procesów i przejścia między nimi w wielozadaniowym systemie operacyjnym.



Podobne dokumenty
ang. file) Pojęcie pliku (ang( Typy plików Atrybuty pliku Fragmentacja wewnętrzna w systemie plików Struktura pliku

41. System operacyjny. Postrzeganie systemu operacyjnego przez warstwę oprogramowania użytkowego

Podstawy informatyki. System operacyjny. dr inż. Adam Klimowicz

System plików warstwa fizyczna

System plików warstwa fizyczna

System plików warstwa fizyczna

Działanie systemu operacyjnego

System plików. Warstwowy model systemu plików

SYSTEMY OPERACYJNE I SIECI KOMPUTEROWE

4. Procesy pojęcia podstawowe

Działanie systemu operacyjnego

Schematy zarzadzania pamięcia

Działanie systemu operacyjnego

Architektura komputerów

Zarządzanie procesami i wątkami

Prezentacja systemu RTLinux

SYSTEMY OPERACYJNE: STRUKTURY I FUNKCJE (opracowano na podstawie skryptu PP: Królikowski Z., Sajkowski M. 1992: Użytkowanie systemu operacyjnego UNIX)

Zarządzanie pamięcią w systemie operacyjnym

Systemy operacyjne III

Systemy operacyjne III

dr inż. Jarosław Forenc

Programowanie współbieżne Wykład 2. Iwona Kochańska

3 Literatura. c Dr inż. Ignacy Pardyka (Inf.UJK) ASK SP.06 Rok akad. 2011/ / 22

Struktura i funkcjonowanie komputera pamięć komputerowa, hierarchia pamięci pamięć podręczna. System operacyjny. Zarządzanie procesami

Księgarnia PWN: Włodzimierz Stanisławski, Damian Raczyński - Programowanie systemowe mikroprocesorów rodziny x86

Procesy i wątki. Blok kontrolny procesu. Proces. Proces - elementy. Stan procesu

Działanie systemu operacyjnego

Zarządzanie pamięcią operacyjną

Projektowanie oprogramowania systemów PROCESY I ZARZĄDZANIE PROCESAMI

SYSTEMY OPERACYJNE WYKLAD 6 - wątki

Jądro systemu operacyjnego

Proces y i y w i ąt ą ki

4. Procesy pojęcia podstawowe

architektura komputerów w. 8 Zarządzanie pamięcią

Budowa systemów komputerowych

System komputerowy. System komputerowy

ARCHITEKTURA PROCESORA,

Wykład 7. Zarządzanie pamięcią

Zarządzanie pamięcią operacyjną

Programowanie na poziomie sprzętu. Tryb chroniony cz. 1

Struktura systemu operacyjnego. Opracował: mgr Marek Kwiatkowski

dr inż. Jarosław Forenc

Zarządzanie pamięcią operacyjną zagadnienia podstawowe

Dodatek B. Zasady komunikacji z otoczeniem w typowych systemach komputerowych

Wprowadzenie. Dariusz Wawrzyniak. Miejsce, rola i zadania systemu operacyjnego w oprogramowaniu komputera

Pamięć. Jan Tuziemski Źródło części materiałów: os-book.com

Wprowadzenie. Dariusz Wawrzyniak. Miejsce, rola i zadania systemu operacyjnego w oprogramowaniu komputera

Komputery przemysłowe i systemy wbudowane

Procesy, wątki i zasoby

Systemy operacyjne. Wprowadzenie. Wykład prowadzą: Jerzy Brzeziński Dariusz Wawrzyniak

PRZYDZIAŁ PAMIĘCI OPERACYJNEJ

System operacyjny System operacyjny

Komunikacja za pomocą potoków. Tomasz Borzyszkowski

Systemy plików FAT, FAT32, NTFS

Zarządzanie zasobami pamięci

Algorytm. a programowanie -

Zarządzanie procesorem

Układ sterowania, magistrale i organizacja pamięci. Dariusz Chaberski

Programowanie współbieżne Wykład 10 Synchronizacja dostępu do współdzielonych zasobów. Iwona Kochańska

16MB - 2GB 2MB - 128MB

Architektura komputerów

ZASADY PROGRAMOWANIA KOMPUTERÓW

Poniższe funkcje opisane są w 2 i 3 części pomocy systemowej.

Mikroprocesor Operacje wejścia / wyjścia

LEKCJA TEMAT: Zasada działania komputera.

UNIX: architektura i implementacja mechanizmów bezpieczeństwa. Wojciech A. Koszek dunstan@freebsd.czest.pl Krajowy Fundusz na Rzecz Dzieci

projektowanie systemu

SYSTEMY OPERACYJNE WYKLAD 4 - zarządzanie pamięcią

Logiczny model komputera i działanie procesora. Część 1.

4. Procesy pojęcia podstawowe

SYSTEMY OPERACYJNE WYKLAD 6 - procesy

Tworzenie pliku Zapisywanie pliku Czytanie pliku Zmiana pozycji w pliku Usuwanie pliku Skracanie pliku

Organizacja typowego mikroprocesora

Procesy i wątki. Blok kontrolny procesu. Proces. Proces - elementy. Stan procesu. Blok kontrolny procesu

Podstawy Informatyki Systemy operacyjne

Planowanie przydziału procesora

Sektor. Systemy Operacyjne

Procesor budowa, schemat, tryby pracy

dr inż. Konrad Sobolewski Politechnika Warszawska Informatyka 1

"Klasyczna" struktura systemu operacyjnego:

Stronicowanie w systemie pamięci wirtualnej

Podstawowe wiadomości o systemach plików.

Stan procesu. gotowy - czeka na przydział procesora, zakończony - zakończył działanie.

SOE Systemy Operacyjne Wykład 8 Pamięć wirtualna dr inż. Andrzej Wielgus

Przetwarzanie wielowątkowe przetwarzanie współbieżne. Krzysztof Banaś Obliczenia równoległe 1

Planowanie przydziału procesora

Od uczestników szkolenia wymagana jest umiejętność programowania w języku C oraz podstawowa znajomość obsługi systemu Linux.

Systemy operacyjne III

SYSTEMY OPERACYJNE I SIECI KOMPUTEROWE

Urządzenia wejścia-wyjścia

Systemy operacyjne. Systemy operacyjne. Systemy operacyjne. Program wykładów. Strona WWW przedmiotu: Program ćwiczeń projektowych

System plików warstwa logiczna

Przełączanie kontekstu. Planista średnioterminowy. Diagram kolejek. Kolejki planowania procesów. Planiści

Pamięć wirtualna. Przygotował: Ryszard Kijaka. Wykład 4

Pytania do treści wykładów:

Materiały pomocnicze 1

Mikroprocesory rodziny INTEL 80x86

Warstwy systemu Windows 2000

Od programu źródłowego do procesu

Transkrypt:

42. Stany procesów i przejścia między nimi w wielozadaniowym systemie operacyjnym. Proces - to jedno z najbardziej podstawowych pojęć w informatyce. Z definicji jest to po prostu egzemplarz wykonywanego programu. Należy odróżnić jednak proces od wątku - każdy proces posiada własną przestrzeń adresową, natomiast wątki posiadają wspólną sekcję danych. Każdemu procesowi przydzielone zostają zasoby, takie jak: * procesor, * pamięć, * dostęp do urządzeń wejścia-wyjścia, * pliki. Każdy proces posiada tzw. "rodzica". W ten sposób tworzy się swego rodzaju drzewo procesów. Proces może (ale nie musi) mieć swoje procesy potomne. Za zarządzanie procesami odpowiada jądro systemu operacyjnego. Wykonanie musi przebiegać sekwencyjnie. Może przyjmować kilka stanów: * działający, * czekający na udostępnienie przez system operacyjny zasobów, * przeznaczony do zniszczenia, * proces zombie, * właśnie tworzony itd. W skład procesu wchodzi: * kod programu, * licznik rozkazów, * stos, * sekcja danych. Stany procesów; Nieustalony - przed uruchomieniem lub po zakończeniu działania Aktywny zakończono operacje we/wy a jeden z procesów systemu wykonuje jego kod Gotowy-jeżeli zakończył operacje we/wy ale nie ma wolnego procesora Wstrzymany-czekanie na zakończenie operacji we/wy dozorowanej przez system operacyjny Tworzenie procesów * Użytkownik za pomocą powłoki zleca uruchomienie programu, proces wywołujący wykonuje polecenie fork, lub jego pochodną. * System operacyjny tworzy przestrzeń adresową dla procesu oraz strukturę opisującą nowy proces w następujący sposób: o wypełnia strukturę opisującą proces, o kopiuje do przestrzeni adresowej procesu dane i kod, zawarte w pliku wykonywalnym, o ustawia stan procesu na działający, o dołącza nowy proces do kolejki procesów oczekujących na procesor,

o zwraca sterowanie do powłoki użytkownika. Wykonywanie procesów Dany proces rozpoczyna wykonywanie w momencie przełączenia przez Jądro systemu operacyjnego przestrzeni adresowej na przestrzeń adresową danego procesu oraz takie zaprogramowanie procesora, by wykonywał kod procesu. Wykonujący się proces może żądać pewnych zasobów, np. większej ilości pamięci. Zlecenia takie są na bieżąco realizowane przez system operacyjny. Kończenie procesów * Proces wykonuje ostatnią instrukcję - zwraca do systemu operacyjnego kod zakończenia. Jeśli proces zakończył się poprawnie zwraca wartość 0, w przeciwnym wypadku zwraca wartość kodu błędu. * W momencie zwrotu do systemu operacyjnego kodu zakończenia, system operacyjny ustawia stan procesu na przeznaczony do zniszczenia i rozpoczyna zwalnianie wszystkich zasobów, które w czasie działania procesu zostały temu procesowi przydzielone. * System operacyjny po kolei kończy wszystkie procesy potomne w stosunku do procesu macierzystego. * System operacyjny zwalnia przestrzeń adresową procesu. Jest to dosłowna śmierć procesu. * System operacyjny usuwa proces z kolejki procesów gotowych do uruchomienia i szereguje zadania. Jest to ostatnia czynność wykonywana na rzecz procesu. * Procesor zostaje przydzielony innemu procesowi. Proces zombie to wpis w tablicy procesów opisujący program, którego wykonanie w systemie operacyjnym zostało zakończone, ale którego zamknięcie nie zostało jeszcze obsłużone przez proces rodzica. Termin ten odnosi się zazwyczaj do systemów z rodziny UNIX, gdzie pozostawienie wpisu zombie tymczasowo zajmującego pozycję w tablicy procesów zapobiega ponownemu wykorzystaniu danego PIDa i możliwym na skutek tego pomyłkom programistycznym. Wpisy takie nie dają się wyeliminować poleceniem kill, czemu prawdopodobnie zawdzięczają swoją złowrogą nazwę. Wpis zombie znika po odpowiednim wywołaniu funkcji wait(), waitpid() lub analogicznej przez proces macierzysty. W przypadku zakończenia także procesu rodzica, w wielu architekturach pozostawione przez niego zombie są obsługiwane automatycznie przez dziedziczący po nim proces init lub przez system operacyjny. Chociaż wpisy zombie nie obciążają znacząco komputera, nieprawidłowo napisany program, który nie obsługuje zakończenia pracy potomków, może doprowadzić do destabilizacji pracy systemu. Dzieje się tak gdy cała tablica procesów, zwykle posiadająca sztucznie ograniczony rozmiar, zostanie zajęta przez wpisy zombie. Hierarchia powiadamiania o procesach zombie może zostać czasowo zmieniona przez mechanizm ptrace, czasem prowadząc do utrudnień przy debuggowaniu programów. Demonem (ang. daemon czyli duszek) nazywamy proces działający w tle, nie podlegający sterowaniu z żadnego terminala, uruchamiany zwykle podczas startu systemu i działający do jego zamknięcia. Demon świadczy zwykle usługi o charakterze systemowym. Ponieważ

demony nie są związane z żadnym terminalem, wyjściem diagnostycznym dla nich jest zwykle podsystem dziennika pracy systemu (demon syslogd), zwyczajowo zapisujący komunikaty w plikach tekstowych. Sterowanie demonami odbywa się poprzez sygnały lub nazwane środki komunikacji międzyprocesowej. Zakończenie pracy procesu potomnego powoduje wysłanie do procesu macierzystego sygnału SIGCLD oraz przejście w stan zwany zombie. Wszystkie zasoby przydzielone procesowi potomnemu są zwalniane (np. zamykane sa pliki), ale pozostaje wpis w liście procesów, mogący doprowadzi do jej przepełnienia. Wpis ten zostaje usunięty, o ile proces macierzysty wykona funkcję z rodziny wait. Najprostszą formą jest funkcja z argumentem typu wskazanie na int, gdzie zapisuje się stan zakończonego procesu potomnego. Kod powrotu procesu na przykład można uzyska za pomocą makra WEXITSTATUS (definicja w pliku nagłówkowym sys/wait.h). Funkcja wait zwraca numer procesu potomnego. Sposób realizacji wszystkich tych działań jest różny dla różnych systemów operacyjnych. 43. Semafor binarny. Definicja Dijkstry. Semafor to jeden ze sposobów komunikacji międzyprocesowej. Semafory zostały po raz pierwszy opisane przez Edsgera Dijkstrę jako istotne rozwinięcie algorytmu Dekkera. Typowy semafor implementowany jest jako zmienna typu całkowitego. Semafory dzieli się na binarne i zliczające. Semafor binarny może przyjmować wartości całkowite z przedziału <0;1>, zliczający - również większe niż 1. Modyfikacja wartości semafora jest możliwa za pomocą trzech operacji: "init", "wait" ("P") oraz "signal" ("V"). Dwie ostatnie muszą być realizowane nieprzerwanie - "atomowo", aby uniknąć jednoczesnego sprawdzenia i modyfikacji przez więcej niż jedno zadanie. P(Semafor s) { oczekuj s > 0, wówczas s := s-1; /* operacja atomowa */ } V(Semafor s) { s := s+1; /* operacja atomowa */ } Init(Semafor s, Całkowitoliczbowe v) { s := v; } Litery P i V zwykle są kojarzone ze słowami holenderskimi: passeren (przejść), proberen (próbować), vryjgeven (zwolnić), verhoog (zwiększać). Jednakże sam Dijkstra użycie liter P i V wyjaśniał nieco inaczej [1]. Najczęstszym zastosowaniem jest synchronizacja dostępu do zasobów systemowych współdzielonych przez kilka zadań, aby zapobiec problemom wynikającym z prób jednoczesnego dostępu i modyfikacji danego zasobu.

Semafory są zwykle implementowane w obszarze jądra systemu operacyjnego. Pozwala to na zaawansowaną obsługę zadań chcących uzyskać dostęp do zasobu: * wstrzymywanie ich do czasu zwolnienia semafora powiązanego z danym zasobem, * wznowienie pracy zadania oczekującego na semaforze, * utrzymywania semafora nawet po zakończeniu zadania, który go utworzyło. //inna wersja Współbieżne operacje na pamięci grożą jej desynchronizacją. Zjawisko to powstaje wtedy, gdy pewna podzielna (wywłaszczalna) operacja modyfikująca jest wykonywana przez wiele procesów jednocześnie. Po wywłaszczeniu jednego procesu w jej trakcie, drugi dostaje dane częściowo tylko zmienione - zwykle nieprawidłowe. Cześć kodu, która musi być wykonywana niepodzielnie (atomowo) przez co najwyżej jeden z procesów grupy nazywa się zwykle sekcją krytyczną. Najpopularniejszą metodą zapewniania atomowości kodu jest zabezpieczenie go semaforem. Na semaforze możemy wykonać dwie operacje - możemy czekać pod zamkniętym semaforem (tradycyjnie nazywa się tę operację P lub wait) lub go podnieść (V lub post). Semafory implementuje się zwykle jako współdzielone zmienne całkowite, których warto niedodatnia oznacza stan zamknięty. P jest więc operacją oczekiwania na dodatnią wartość semafora, V operacja jego zwiększenia. Jeżeli początkowa wartość semafora jest równa 1, mamy do czynienia z semaforem binarnym, jeżeli jest większa niż 1 - z semaforem zliczającym. Operacjami P i V na semaforze binarnym otacza się sekcję krytyczną Nowoutworzone tablice semaforów są niezainicjowane - nie możemy zakładać, że semafory są zamknięte czy otwarte. Do ich inicjowania należy użyć Funkcji semctl, która ma trzy obowiązkowe argumenty: deskryptor zbioru, indeks semafora w zbiorze (licząc od 0) oraz stałą operacji do wykonania. Operacjami tymi są: GETVAL zwraca wartość semafora; SETVAL nadaje wartość semafora; GETALL przepisuje wartości całej tablicy semaforów do zaalokowanej przez programistę tablicy elementów typu unsigned short; SETALL nadaje wartości całej tablicy semaforów według tablicy programisty. Ponieważ w większości współczesnych systemów rozmiary komponentów powyższej unii są takie same, wielu programistów używa jako dalszych argumentów semctl zamiast unii odpowiednich wartości i tak: semctl(d, n, GETVAL) zwraca warto n-tego semafora w tablicy; semctl(d, n, SETVAL, x) ustawia warto n-tego semafora w tablicy na x; semctl(d, 0, GETALL, buf) przepisuje zawarto tablicy semaforów do tablicy użytkownika buf; semctl(d, 0, SETALL, buf) przepisuje zawarto tablicy użytkownika buf do tablicy semaforów. Operacje P i V są realizowane przez funkcję semop. Pierwszym jej argumentem jest deskryptor zbioru semaforów, drugim - zbiór operacji do niepodzielnego wykonania na semaforach w postaci tablicy struktur sembuf, a trzecim liczność tej tablicy. Struktura sembuf zawiera przynajmniej trzy pola typu short: sem_num - numer semafora, sem_op - kod operacji na semaforze oraz sem_flg - opcje operacji.

W najprostszym przypadku programista powinien zadeklarować Zmienną typu struct sembuf, o nazwie powiedzmy op, nadać wartości komponentom sem_num, sem_op i sem_flg i wywołać semop(d, &op, 1). Kluczowe znaczenie w pracy na semaforach ma wartość komponentu sem_op: Jeżeli sem_op jest dodatnia, to semafor jest zwiększany o tę wartość. Wartość 1 oznacza więc typową operację podniesienia semafora (V). Zerowa warto sem_op uruchamia oczekiwanie na zerową wartość semafora. Nie odpowiada to żadnej typowej operacji na semaforze. Ujemna warto sem_op uruchamia oczekiwanie na wartość semafora większą lub równą wartości bezwzględnej sem_op, po czym wartość sem_op jest dodawana do wartości semafora (jest on zmniejszany). Wartość-1 oznacza więc typową operację czekania pod semaforem (P). 44. Przydział pamięci dyskowej: listowy i indeksowy. Podstawową kwestią przy wyborze metody przydziału miejsca na dysku jest efektywność i szybkość dostępu do plików. Powszechnie używa się 3 metod: * przydział ciągły, * przydział listowy, * przydział indeksowy Każda z nich ma swoje wady i zalety. W niektórych systemach korzysta się z trzech metod równocześnie, powszechniejsze jest jednak użycie jednej metody dla wszystkich plików w systemie. Przydział ciągły W przydziale ciągłym (ang. contiguous allocation) plik zajmuje ciąg kolejnych bloków (jednostek alokacji). Ponieważ bloki rozmieszczone są blisko siebie, dostęp do plików jest efektywny niewielkie ruchy głowic dyskowych. Możliwa jest szybka lokalizacja bloków pliku, zarówno przy dostępie swobodnym jak i sekwencyjnym. Wadą przydziału ciągłego jest problem fragmentacji zewnętrznej po usuniętych plikach pozostają dziury, które trudno połączyć w jeden, większy blok. Problemy pojawiają się również przy próbie rozszerzenia pliku. Aby to zrobić, zazwyczaj trzeba go przenieść w nowe miejsce (należy znaleźć większą dziurę). Dlatego należy z góry rezerwować dla plików więcej miejsca w przestrzeni dyskowej. Przykład:

Przydział listowy W przydziale listowym (ang. linked allocation) plik jest listą powiązanych bloków, dowolnie rozproszonych w dostępnej przestrzeni adresowej. Zaletą tej metody jest brak problemu fragmentacji zewnętrznej, a także łatwa realizacja dostępu sekwencyjnego. Wadą, problem realizacji dostępu swobodnego przejście do poprzedniego bloku wymaga rozpoczęcia przeglądania listy bloków od początku. Konieczne jest tu pamiętanie wewnątrz bloku wskaźnika do bloku następnego. Przydział listowy jest zawodny utrata jednego bloku pociąga za sobą stratę wszystkich następnych. Przykład: Przydział indeksowy W przydziale indeksowym (ang. indexed allocation) wskaźniki (indeksy) do rozproszonych bloków dyskowych skupione są w jednym miejscu w tzw. bloku indeksowym. Wyróżnia się: * schemat listowy bloku indeksowego - gdy w ostatnim elemencie bloku indeksowego znajduje się wskaźnik do następnego bloku indeksowego tego pliku, * indeks wielopoziomowy gdy blok indeksowy pierwszego poziomu zawiera wskaźnik do bloków drugiego poziomu itd.,

* schemat kombinowany zastosowanie do pewnej liczny bloków indeksu pierwszego poziomu,dla następnych bloków indeksowego dwupoziomowego itd. Przydział indeksowy charakteryzuje się łatwością lokalizacji bloków pliku, zarówno przy dostępie sekwencyjnym, jak i swobodnym. Brak w nim problemu fragmentacji zewnętrznej. Wadą jest konieczność przeznaczenia pewnej części przestrzeni dyskowej na bloki indeksowe. Przykład: Przykładowe systemy plikowe: FAT FAT ( z ang. File Allocation Table) to system plików powstały pod koniec lat 70-tych, zastosowany w takich systemach operacyjnych jak DOS i Windows Określa on rozmieszczenie plików, katalogów i wolnej przestrzeni na nośnikach danych. Najważniejszym elementem systemu jest tablica informująca o rozmieszczeniu plików na partycji (FAT), od nazwy tej tablicy pochodzi nazwa systemu. Wyróżnia się trzy rodzaje FAT: * FAT 12, * FAT 16, * FAT 32 Podstawowa różnica między nimi polega na różnej ilości bitów, na których koduje się numery jednostek alokacji plików zwane klastrami (określone w nazwie systemu FAT). EXT2 Ext2 ( z ang. second extended filesystem) to drugi, rozszerzony system plików dla systemu operacyjnego Linux. Jest to rozwinięta wersja systemu plików ext. W ext2 rozpoznanie uszkodzenia systemu plików (np. po załamaniu się systemu) następuje przy starcie systemu, co pozwala na automatyczne naprawianie szkód za pomocą oddzielnego programu e2fsck. System plików ext2 zawiera mechanizm zapobiegający znacznej fragmentacji dysku. Dzięki wolnym polom w strukturach danych możliwa jest konwersja w locie do systemu ext3. EXT3

Ext3 to nowoczesny system plików oparty na ext2. Jest to domyślny system plików w większości dystrybucji systemu GNU/Linux opartych na jądrze 2.4 oraz nowszych. Główną cechą systemu odróżniająca go od ext2 jest księgowanie. Dane nie są bezpośrednio zapisywane na dysk, ale w dzienniku/kronice. Dzięki temu zmniejsza się prawdopodobieństwo utraty danych. Ext3 dodaje dokładny zapis zmian na dysku co w razie nagłego wyłączenia systemu umożliwia szybkie przywrócenie spójności systemu plików. Zaletą tego systemu plików oprócz dużego bezpieczeństwa danych jest fakt, iż bardzo łatwo przekonwertować do niego system plików ext2. NTFS NTFS (z ang. New Technology File System) to standardowy system plików dla systemów operacyjnych Microsoftu (Windows NT, Windows 2000, Windows XP). Pochodzi od HPFS, który został opracowany przez Microsoft i IBM dla systemu OS/2 na miejsce systemu FAT. Występuje w wersjach: * NTFSv4, * NTFSv5, * NTFSv6 System NTFS posiada kilka ulepszeń w porównaniu do systemu FAT, takich jak wsparcie dla metadanych, użycie zaawansowanych struktur w celu polepszenia, wiarygodności i wydajności (zarówno w odniesieniu do szybkości jak i wymaganej pojemności dyskowej), listy kontroli dostępu (ACL), dziennik operacji dyskowych. 45. Cechy tradycyjnego systemu unixowego. (http://math.uni.lodz.pl/~jarocki/nps/nps.pdf) Czym tak naprawdę jest system Unix? Nazwa ta pojawia się po raz pierwszy w 1969 roku jako określenie systemu stworzonego przez Kena Thompsona i Dennisa Ritchie z zespołu badawczego Bell Laboratories, będącego częścią koncernu telekomunikacyjnego AT&T. Wraz z wersją 3 systemu pojawiła się przełomowa dla dalszych jego losów koncepcja rozwijania kodu systemu w języku C (powstałym dzięki Ritchiemu i Brianowi Kernighanowi), z niewielką nieprzenośną częścią pisaną w asemblerze danej maszyny. Od początku rozwój systemu był nakierowany na przenośność na poziomie kody źródłowego z racji używania w Bell Laboratories sprzętu rozmaitego typu. Wersja 7 z roku 1978 zamyka pierwszą fazę rozwoju systemu, ograniczą do firmy AT&T, choć już w tym czasie kod systemu trafiał już do amerykańskich uniwersytetów. Unix stał się produktem firmy AT&T. AT&T rozwijało dalej system, co zaowocowało opublikowaniem w 1982 wersji

zwanej Systemem III, a w 1983 Systemem V. Na bazie kodu z Bell Laboratories były również prowadzone prace rozwojowe na uczelniach amerykańskich. Najbardziej wpływowy okazał się tu Uniwersytet Kalifornijski w Berkeley (UCB).Wersje systemu powstałe w UCB nazywane były BSD (Berkeley Software Distributions), a pierwsza kompletna pojawiła się już w roku 1978. Subsydia rządowe uczyniły wersje Unixa BSD równie dojrzałymi jak wersje z AT&T, choć rozwój szedł w nieco innych kierunkach. Zespół UCB zakończył prace badawcze wraz z wydaniem 4.4 z roku 1993. Bazą każdego systemu Unix jest albo wydanie pochodzące z AT&T albo z UCB. Producent sprz etu (Sun, DEC, IBM, HP, Silicon Graphics) nabywał system Unix od firmy AT&T lub UCB, dostosowywał j a do własnego sprzętu i dodawał własne rozszerzenia tworząc wersje użytkowe systemu (odpowiednio: SunOS, Ultrix, AIX, HP/UX, IRIX). Dookoła nazwy Unix powstało wiele organizacji standaryzujących. Sama nazwa Unix ma bogate dzieje, jeżeli chodzi o własność znaku towarowego. Sytuacje komplikuje dodatkowo fakt, ze najpowszechniej obecnie wykorzystywana wersja systemu unixopodobnego, Linux, właściwie nie jest Unixem, ponieważ kod jądra został stworzony od podstaw przez Linusa Torvaldsa i wolontariat internetowy. Wolontariat rozwija również wersje systemu wywodzące się z BSD jak FreeBSD, NetBSD oraz OpenBSD. Nad częścią systemów zbudowano środowiska użytkowe, często bardziej rozbudowane niż sama baza (Unixware nad Systemem V, Solaris nad SunOS em, MacOS X nad FreeBSD). Definicja słowa Unix staje się powoli niemożliwą... Bardzo ważnym pojęciem dla zrozumienia czym Unix jest a czym nie, jest norma POSIX (Portable Operating System Interface for unix). Jest on rodziną standardów opracowanych przez IEEE (Institute for Electrical and Electronics Engineers), uznanych za normy przez ISO (International Organization for Standarization). Definiują one między innymi: interfejs między jądrem systemu (unixopodobnego) a językiem C, formaty baz systemowych, formaty archiwów, interpreter Bourne a i inne programy usługowe (w tym m.in. awk i vi), komunikację międzyprocesową, rozszerzenia czasu rzeczywistego, interfejs wątków i inne. Popularnym znaczeniem słowa unixopodobny (ang. unix-like) jest zgodny z normami POSIX. Pozwala to zakwalifikować jako systemy unixowe również te, które nie dziedziczą kodu po systemach z AT&T. Zaproponuję więc inne spojrzenie na definicję słowa unix (celowo używam tu małej litery), spojrzenie oderwane od znaków towarowych, praw autorskich czy zapożyczę kodu, spojrzenie traktujące unix jako zbiór charakterystycznych cech systemu (czyli słowo unix należy tu czytać jako typowy system unixowy lub unixopodobny ), występujących najczęściej: 1. Jądro systemu jest, oprócz pewnej części ściśle związanej z obsługiwanym sprzętem, napisane w języku wysokiego poziomu (C). 2. Unix to system wielozadaniowy (z podziałem czasu); tradycyjnie unixy preferują zadania nastawione na wejście/wyjście, obniżając priorytety efektywne procesów obliczeniowych. 3. Jednostką aktywną w systemie jest proces, pracujący w trybie nieuprzywilejowanym procesora, we własnej chronionej przestrzeni adresowej; jedynym elementem aktywnym w trybie uprzywilejowanym jest j adro systemu.

4. Unix używa pamięci wirtualnej, rozszerzając pamięć operacyjną o tzw. Obszary wymiany w pamięci masowej. Niewykorzystaną pamięć operacyjną wypełniają bufory używanych plików. 5. Podstawową metodą tworzenia nowych procesów jest rozwidlanie procesu aktywnego funkcją systemową fork. Po jej wywołaniu system tworzy nowy proces, którego przestrzeń adresowa jest kopią przestrzeni procesu macierzystego. Oba procesy rozpoczynają współbieżną pracę od następnej instrukcji za wywołaniem fork. Często proces potomny wykonuje niedługo po utworzeniu funkcję systemową execve, która zastępuje kod aktywnego procesu kodem z pliku wykonywalnego. 6. Procesy korzystają podczas pracy z mechanizmów łączenia dynamicznego, ładując kod wspólnych bibliotek w miarę potrzeb. Podstawową biblioteką uwspólnioną jest standardowa biblioteka języka C (tzw. libc). 7. Komunikacja międzyprocesowa odbywa się przez jądro systemu (wydaje się, że jest to najmniej pożądana cecha systemu większość środowisk unixowych zapewnia obecnie nie tylko wsparcie dla organizacji wspólnej pamięci, ale również elementów aktywnych w postaci wątków). 8. Budowie interfejsu programisty systemu (API) prześwięca minimalizm, ujawniający się choćby tym, że odczyt i zapis informacji w rozmaitych urządzeniach obsługiwanych przez system odbywa się za pomocą tego samego interfejsu jak odczyt i zapis informacji do plików zwykłych. Zasadę tę często definiuje się jako: Dla unixa wszystko jest plikiem. 9. Otwarty plik jest dostępny w procesie poprzez liczbę całkowitą zwaną a deskryptorem pliku. Predefiniowanymi deskryptorami są tu wartości 0 (standardowe wejście, zwykle związane z klawiaturą terminala), 1 (standardowe wyjście, zwykle z związane z wyjściem terminala) oraz 2 (standardowe wyjście dla błędów). 10. Unix to system wielodostępny (o ile jego administrator nie zażyczy sobie inaczej); typowymi formami realizacji wielodostępu są sesje z terminali tekstowych bądź ich emulatorów; dla fanów środowisk graficznych przygotowuje się zwykle zdalne środowisko pracy w oparciu o protokół X Window. 11. W środowisku tekstowym naturalnym środowiskiem pracy jest tzw. Interpreter poleceń czyli powłoka (ang. shell). 12. Unix wykorzystuje do pracy w środowisku rozproszonym rodzinę protokołów TCP/IP. 13. Naturalnym sposobem organizacji pamięci masowej jest model indeksowy oparty na tzw. i-węzłach (ang. i-nodes). i-węzeł zawiera w postaci tablicy o stałym rozmiarze wszystkie informacje o pliku poza jego nazwą (jest to przyczyną problemów z implementacją w systemach unixowych tzw. List kontroli dostępu (ang. access control lists) informacja taka z natury bowiem ma charakter dynamiczny). Odwzorowaniem i-węzłów na nazwy plików zajmują się pliki specjalne katalogi. 14. Unixowy system plików jest widoczny jako wielopoziomowe drzewo.

15. Unix bezpośrednio po starcie widzi tylko jedno urządzenie pamięci masowej, zawierające tzw. Korzeń systemu plików (oznaczany znakiem /). Inne urządzenia są przyłączane do głównego drzewa w procesie tzw. Montowania (to nieszczęśliwa kalka angielskiego słowa mount) i są widoczne jako fragmenty drzewa plikowego od pewnego katalogu określanego jako punkt montowania. 16. Plik danych jest ciągiem bajtów. 17. System praw dostępu do plików (czyli również do urządzeń czy kanałów komunikacyjnych, w myśl hasła wszystko jest plikiem ) jest zbudowany w oparciu o tablicę bitową stałej długości, zapisaną w i-węźle. Zawiera ona zezwolenia na trzy podstawowe operacje czytanie, zapis i wykonanie dla trzech rozłącznych klas użytkowników: właściciela pliku, członków tzw. grupy pliku oraz innych.bardzo charakterystyczne dla unixa sa bity SUID i SGID. Ich ustawienie dla pliku wykonywalnego zmienia efektywny identyfikator użytkownika (bądź włącza do grupy pliku) dla uruchamiającego. Unixowy system praw dostępu jest bardzo efektywny w działaniu, brak dynamicznych list dostępu jest jednakże dość uciążliwy. 18. W unixie obowiązuje model administracyjny, bazujący na ograniczonym zaufaniu do użytkowników. Ujawnia się on między innymi tym, że zwykle użytkownik lokalny ma prawo zapisu jedynie w swoim katalogu domowym, katalogu na pliki tymczasowe oraz w kilku innych, dobrze znanych miejscach. Jednocześnie administratora systemu (użytkownika o numerze identyfikacyjnym 0) nie dotyczą jakiekolwiek ograniczenia. 46. Wsparcie sprzętowe dla wielozadaniowych systemów operacyjnych. Tryb rzeczywisty to tryb pracy mikroprocesorów z rodziny procesorów x86, w którym procesor pracuje tak jak procesor Intel 8086. Nowym trybem pracy procesora Intel 80286 był tryb chroniony. W trybie tym brak ochrony pamięci przed użyciem przez inny proces i brak obsługi wielozadaniowości. W trybie rzeczywistym pracowały programy w systemie operacyjnym DOS, na przełomie lat 80 i 90 dwudziestego wieku prowadzono działania nad pracą programów w systemie DOS w trybie chronionym, pozostawiając sam system w trybie rzeczywistym, zbudowano kilka systemów umożliwiających taką pracę systemu. Tryb chroniony (ang. protected mode) to tryb pracy mikroprocesorów serii x86 wprowadzony w mikroprocesorze Intel 80286. Tryb chroniony umożliwia adresowanie pamięci w większym zakresie niż 1MB (tryb rzeczywisty), wprowadza wiele nowych udogodnień wspierających wielozadaniowość, takich jak: sprzętowa ochrona pamięci (układ MMU), wsparcie przełączania kontekstu procesora i wiele innych. Większość nowoczesnych systemów operacyjnych wykorzystuje procesory serii x86 właśnie w trybie chronionym. Zaliczają się do nich m.in.: Linux, Windows w wersji 3.0 i wyższych, systemy z rodziny BSD.

Tryb chroniony został wprowadzony do mikroprocesora Intel 80286 wraz z trybem rzeczywistym (ang. real mode) dla zachowania zgodności z poprzednimi mikroprocesorami rodziny x86. W mikroprocesorze Intel 80286 w trybie chronionym 16-bitowe rejestry segmentowe CS, SS, DS, ES zawierają selektory, które jednoznacznie określają deskryptor (8- bajtowa struktura w pamięci) opisujący segment. Deskryptor dysponuje następującymi informacjami o segmencie: fizyczna lokalizacja segmentu w pamięci (24-bitowy adres bazowy, 16-bitowa długość segmentu w bajtach), prawa dostępu do segmentu i numer uprawnienia segmentu. W odróżnieniu od trybu chronionego w trybie rzeczywistym rejestry segmentowe CS, SS, DS, ES zawierają adresy bazowe (początków) segmentów. Procesor zaczyna pracę trybie chronionym po ustawieniu bitu PE (ang. Protection Enable) na jeden, wyzerowanie tego bitu powoduje powrót do trybu rzeczywistego (bit PE to najmłodszy bit rejestru CR0 (ang. Control Register)). MMU (Memory Management Unit), to zestaw układów realizujących dostęp do pamięci fizycznej żądanej przez CPU. Wśród zadań tych układów znajdują się funkcje translacji pamięci wirtualnej do pamięci fizycznej, ochronę pamięci, obsługę pamięci podręcznej, zarządzanie szynami danych oraz, w prostszych (szczególnie 8-bitowych) systemach, przełączanie banków pamięci. Obecne układy MMU dzielą przestrzeń logiczną (wirtualną) pamięci na strony, których rozmiar wynosi 2N, zazwyczaj kilka kilobajtów. Młodsze N bitów adresu (przesunięcie - ang. offset) pozostaje niezmienione, podczas gdy starsze bity adresu określają numer (logiczny) strony pamięci. MMU tłumaczy adresy logiczne (wirtualne) na adresy fizyczne za pomocą asocjacyjnej pamięci podręcznej nazywanej TLB Translation Lookaside Buffer. Jeżeli TLB nie posiada odpowiedniego przypisania (rozmiar pamięci TLB jest ograniczony) uruchamiane są wolniejsze, sprzętowe mechanizmy procesora przeszukujące struktury danych znajdujące się w pamięci, co wymaga niekiedy pomocy ze strony oprogramowania (systemu operacyjnego). Pozycje w tych strukturach nazywają się wpisami (elementami) tablicy stron pamięci (PTEs - Page Table Entries) a cała struktura nazywana jest tablicą stron pamięci (ang. Page Table). Kompletny adres w pamięci fizycznej jest ustalany poprzez dodanie bitów przesunięcia (ang. offset) do przetłumaczonego numeru strony. Wpisy w TLB lub PTE mogą także przechowywać informację o tym, czy dostęp do strony odbył się w trybie zapisu (ang. dirty bit) czy w trybie odczytu (ang. accessed bit - bit pomocny algorytmom wymiatania pamięci), bity uprawnień do operacji na stronie pamięci (prawa dla trybu nadzorcy lub trybu użytkownika) lub informację o tym, czy strona może być przeniesiona do pamięci wymiany. Jeżeli w strukturach TLB lub PTE nie znajduje się odpowiedni opis aktualnie wykorzystywanej logicznej strony pamięci lub znajdujący się wpis zabrania dostępu w danym trybie, MMU sygnalizuje CPU wyjątek związany z błędnym dostępem do strony pamięci, tzw. page fault. System operacyjny może wtedy podjąć akcje związane z wyjątkiem, np. uzupełnić wpisy w tablicy stron lub w TLB, ew. przerwać proces, którego działanie spowodowało wystąpienie wyjątku. Segmentacja pamięci - jedna z metod ochrony pamięci, używana przy wielozadaniowości. Każdy proces otrzymuje swój własny obszar pamięci, realizowany poprzez rejestry segmentowe. Segmentacja pamięci polega na podzieleniu przez system operacyjny pamięci fizycznej na fragmenty o określonym początku, rozmiarze, atrybutach i identyfikatorze. System tworzy

takie segmenty na żądanie aplikacji, przekazując jej jedynie identyfikatory nie pozwalające na odczytanie parametrów segmentów. Programy odwołują się zatem do kolejnych komórek pamięci w ramach należących do nich segmentów, nie wiedząc nic o tym, w jakie miejsca pamięci fizycznej trafiają ich odwołania. Procesy nie mają też prawa widzieć segmentów należących do innych programów w czasie przekazywania kontroli procesowi system musi zablokować definicje segmentów należących do pozostałych procesów, przy każdym przełączeniu blokując segmenty wyłączanego programu i na nowo uaktywniając segmenty programu aktywowanego. Segmenty mają swoje zalety. Największą jest prostota relokacji kodu i danych; ponieważ nie jest ważne gdzie w pamięci fizycznej zakotwiczony jest segment, program może odwoływać się do kolejnych słów pamięci w ramach segmentu zawsze licząc od zera do końca segmentu. Konieczne dodawanie adresów realizuje sprzętowo układ zarządzający pamięcią. Okazuje się jednak, że wady segmentacji przeważyły nad zaletami. Pierwsze implementacje segmentowanej pamięci wirtualnej narzucały dość poważne ograniczenia na rozmiary segmentów, zmuszając programistów do dzielenia kodu programów oraz bloków danych w sposób nienaturalny i utrudniając tworzenie naprawdę dużych struktur danych. Nawet po zniesieniu tego ograniczenia okazało się, że nikt nie chce bawić się w dzielenie programu na logiczne części, a normalną pracę systemu i programu można osiągnąć znacznie prostszymi środkami. Segmentacja jest rozwiązaniem bardzo eleganckim, lecz na tyle kłopotliwym, że obecnie praktycznie się jej nie stosuje. Przełączanie kontekstu to komputerowy proces zachowania i odtwarzania stanu procesora (kontekstu), by wiele procesów mogło dzielić zasoby pojedynczego procesora. Przełączanie kontekstu to ważna cecha wielozadaniowego systemu operacyjnego. Z reguły przełączanie kontekstu jest zadaniem intensywnym obliczeniowo i wiele czasu przy projektowaniu systemów operacyjnych poświęca się na optymalizację tego zadania. Pamięć wirtualna jest techniką programową a także sprzętową gospodarowania pamięcią operacyjną RAM pozwalającą na przydzielanie pamięci dla wielu procesów, zwalnianie jej i powtórne przydzielanie. Mechanizm umożliwia przydzielenie procesom więcej pamięci niż rzeczywista ilość pamięci fizycznej zainstalowanej w komputerze poprzez przeniesienie danych z ostatnio nie używanej pamięci do pamięci masowej (np. twardego dysku), w sytuacji gdy procesor odwołuje się do danych z pamięci przeniesionej na dysk przesuwa się te dane do pamięci w wolne miejsce, a gdy brak wolnej pamięci zwalnia się ją przez wyżej opisane przerzucenie jej na dysk. Najczęściej spotykane są dwa sposoby przechowywania danych zrzuconych z pamięci fizycznej na dysk. Pierwszy, stosowany w systemach rodziny Windows polega na zapisie pamięci w pliku znajdującym się na ustalonej partycji komputera. Drugi, stosowany w systemach z rodziny UNIX to utworzenie osobnej partycji wymiany (partycji swap) przeznaczonej wyłącznie na pamięć wirtualną. Zapewnia to szybszy dostęp do danych niż pierwsze rozwiązanie (głównie ze względu na ominięcie obsługi systemu plików). Pamięć wirtualna jest najczęściej zaimplementowana przy użyciu stronicowania. Procesor gospodaruje wówczas pamięcią w blokach będących wielokrotnością strony o jednakowej wielkości (w procesorach Pentium 4 kb lub 4 MB). Procesy (poza procesem zarządzania

pamięcią) "widzą" pamięć poprzez adresy logiczne. Gdy proces rezerwuje pamięć proces rządzący pamięcią przydziela blok opisujący parametry tej pamięci w tablicy stron (adres logiczny, wielkość, adres fizyczny, warunki użycia i inne informacje umożliwiające gospodarowaniem pamięcią). Adresy logiczne są tłumaczone na ich fizyczne odpowiedniki przy pomocy tablicy stron. Ta znajdująca się w RAM struktura zawiera informacje o tym, gdzie w danej chwili znajduje się dana strona. Tablica stron pamięci jest najczęściej buforowana poprzez bufor TLB, zawierający kilkadziesiąt (zwykle ok. 32) wpisów, do których w ostatnim czasie nastąpiło odwołanie. Pamięć wirtualna może także działać w innych trybach - najpopularniejsze z nich to segmentacja i stronicowanie z segmentacją. Pierwsza implementacja tej techniki (w systemie UNIX) pojawiła się w systemie 3BSD, napisanym w UCB. Wywłaszczenie - to technika używana w środowiskach wielowątkowych, w której algorytm szeregujący (scheduler) może wstrzymać aktualnie wykonywane zadanie (np. proces lub wątek), aby umożliwić działanie innemu. Dzięki temu rozwiązaniu zawieszenie jednego procesu nie powoduje blokady całego systemu operacyjnego. W systemach bez wywłaszczenia zadania jawnie informują scheduler, w którym momencie chcą umożliwić przejście do innych zadań. Jeżeli nie zrobią tego w odpowiednim czasie, system zaczyna działać bardzo wolno. Oprócz tego wywłaszczanie umożliwia szczegółowe określanie czasu, w jakim dany proces może korzystać z procesora. Wywłaszczanie w niektórych systemach operacyjnych może dotyczyć nie tylko programów, ale także samego jądra - przykładem takiego systemu jest Linux. Wywłaszczanie jest często ograniczane, na przykład procedury odpowiedzialne za obsługi przerwań sprzętowych są zwykle niewywłaszczalne, co znacznie upraszcza ich konstrukcje ale wymusza też zadbanie o to, żeby szybko się kończyły umożliwiając działanie innym procesom. W systemie Linux przed wersją 2.6 niemożliwe było wywłaszczenie procesu który znajdował się w trybie jądra, co w pewnych sytuacjach mogło być powodem bardzo wolnej reakcji na działania użytkownika. Popularne wielozadaniowe systemy operacyjne z możliwością wywłaszczania procesów [edytuj] * przeważająca większość systemów uniksowych * Mac OS X * Microsoft Windows (95, 98, ME, NT, 2000, XP, Vista) * AmigaOS (1.3,2.x,3.x,4.x,Morphos) Popularne wielozadaniowe systemy operacyjne bez możliwości wywłaszczania procesów [edytuj] * Microsoft Windows 3.x i wcześniejsze * Mac OS 9 i wcześniejsze

47. Algorytmy szeregowania zadań Definicja Dla jednego procesora jest to funkcja: Algorytm szeregowania n zadań stanowiących zbiór J= {J_1,..., J_n} jest to takie przydzielanie zadań procesorowi (lub procesorom), że każde zadanie jest przetwarzane do momentu zakończenia. Jednakże przetwarzanie danego zadania może być przerywane na bliżej nieokreślony czas. Zatem zgodnie z definicją, jest to funkcja która dzieli czas na przedziały i każdemu przedziałowi przyporządkowuje jedną wartość naturalną będącą numerem procesu, który ma się w tym przedziale czasu wykonywać. Przyjęte jest, że przyporządkowanie wartości równej 0 oznacza procesor w stanie bezczynności. Numer nie musi mieć związku z priorytetem zadania. Chociaż wyjaśnienie wydaje się proste, zaprojektowanie i implementacja dobrego algorytmu szeregowania nastręcza wielu trudności. Implementacja Zwykle implementacja algorytmu jest umieszczana w jądrze systemu, jednak nie zawsze. Ponieważ jego celem jest jedynie ustawianie listy zadań kierowanych do wykonywania a nie samo ich kierowanie, może być jednym ze zwykłych zadań, spełniającym usługę dla jądra. Taką sytuację można spotkać w systemach opartych o mikrojądro. Planista musi także uwzględniać priorytety procesów i ich gotowość do wykonania oraz przeciwdziałać zagłodzeniu procesu poprzez przedłużający się brak dostępu do zasobów oraz tzw. inwersji priorytetów. Większość praktycznych rozwiązań oparta jest o nadawanie zadaniom priorytetów. Jednak już samo określanie priorytetu jest problemem nietrywialnym i nie można rozpatrywać go niezależnie od co najmniej kilku czynników: * Obszaru zastosowania systemu * Celu jaki ma osiągnąć każde z zadań * Zastosowanego algorytmu szeregowania W praktyce pod względem czasu na jaki realizowane jest planowanie kolejki zadań, można wyróżnić dwa typy planistów: * Planista długoterminowy wybiera procesy z pamięci masowej i ładuje do pamięci operacyjnej.

* Planista krótkoterminowy odpowiada za ustalanie kolejności wykonywania procesów gotowych do wykonania. Musi być on bardzo szybki, w przeciwieństwie do planisty długoterminowego. Problem szeregowania zadań powinien być rozpatrywany wielopłaszczyznowo i zwykle nie można go sprowadzić wyłącznie do rozdziału czasu procesora. Implementacja w typowym systemie powinna uwzględniać również takie elementy jak na przykład: * Korzystanie z zasobów sprzętowych takich jak na przykład pamięć masowa, sieć itd. * Lokalność pamięci cache * Różne wymagania wobec procesów (priorytety, poziom interaktywności) W systemach operacyjnych codziennego użytku łatwo dokonać podziału na zadania interaktywne i nieinteraktywne. Zadania interaktywne przez większość czasu pozostają w stanie oczekiwania na reakcję użytkownika. Gdy taka reakcja nastąpi, powinny szybko przejść do stanu wykonywania aby ich użytkownik nie miał wrażenia, że program "zacina się". Problemem jest tu nieprzewidywalny moment, w którym do wykonywania powinno być skierowane zadanie interaktywne. Należy jednocześnie zapewnić jak najmniejsze opóźnienia w realizowaniu zadań nieinteraktywnych. Szeregowanie a wywłaszczanie Większość współcześnie spotykanych rozwiązań opiera się na wymuszaniu oddania kontroli czyli wielozadaniowości z wywłaszczaniem. Systemy dobrowolnego oddawania kontroli (wielozadaniowość oparta na współpracy) są rzadziej spotykane, gdyż pojedynczy źle zaimplementowany lub wrogi proces potrafi w takim wypadku zdestabilizować pracę całego systemu. Dość często stosuje się też rozwiązania mieszane - wymuszanie wobec zadań (realizowanych zwykle jako procesy) a współpraca wewnątrz zadania czyli zwykle między wątkami. Wybrane algorytmy szeregowania Używane najczęściej * FIFO - algorytm powszechnie stosowany, jeden z prostszych w realizacji, dający dobre efekty w systemach ogólnego przeznaczenia; zadanie wykonuje się aż nie zostanie wywłaszczone przez siebie lub inne zadanie o wyższym priorytecie; * Planowanie rotacyjne (round-robin) - każde z zadań otrzymuje kwant czasu; po spożytkowaniu swojego kwantu zostaje wywłaszczone i ustawione na końcu kolejki; * Planowanie sporadyczne - zadania otrzymują tak zwany "budżet czasu"; ten algorytm pomaga pogodzić wykluczające się reguły dotyczące szeregowania zadań okresowych i nieokresowych; wciąż nie jest implementowany przez wiele systemów, jednak znalazł się w standardzie POSIX; Mniej powszechne Trzy wymienione wyżej algorytmy są stosowane najczęściej. Jednak lista algorytmów szeregowania jest bardzo długa i znajdują się na niej między innymi jeszcze takie algorytmy jak:

* FCFS (first come, first start) - Bardzo podobny do kolejki FIFO - Pierwszy przyjdzie, pierwszy wykonany. Algorytm ten dokonuje najsprawiedliwszego przydziału czasu (każdemu według potrzeb), jednak powoduje bardzo słabą interakcyjność systemu - pojedynczy długi proces całkowicie blokuje system na czas swojego wykonania, gdyż nie ma priorytetów zgodnie z którymi mógłby zostać wywłaszczony. Algorytm ten stosuje się jednak z powodzeniem w systemach wsadowych, gdzie operator ładuje zadania do wykonania, a one wykonują się do skutku. * SJF (shortest job first) - Najpierw najkrótsze zadanie. Jest algorytmem optymalnym ze względu na najkrótszy średni czas oczekiwania. W wersji z wywłaszczaniem, stosowana jest metoda: najpierw najkrótszy czas pracy pozostałej do wykonania. Problemem tego algorytmu jest głodzenie długich procesów - może się zdarzyć, że cały czas będą nadchodzić krótsze procesy, a wtedy proces dłuższy nigdy nie zostanie wykonany. Modyfikacje Działania planisty zwykle muszą być skonsolidowane z całością systemu. Dlatego w praktycznie używanych algorytmach szeregowania pojawiają się dodatkowe cechy, takie jak: * Planowanie priorytetowe - wybierany jest proces o najwyższym priorytecie. W tej metodzie występuje problem nieskończonego blokowania (procesu o niskim priorytecie przez procesy o wysokim priotytecie). Stosuje się tu postarzanie procesów, polegające na powolnym podnoszeniu priorytetu procesów zbyt długo oczekujących. * Planowanie wielopoziomowe - zadania przypisywane są do kolejek szeregowania w zależności od parametru opisującego każde z zadań jakim w praktyce zwykle jest priorytet. Zadania w danej kolejce są następnie szeregowane określonym algorytmem takim jak na przykład FIFO lub round-robin i kierowane do wykonania. Jeśli w danej kolejce nie ma zadań gotowych do wykonywania, planista ponownie dokonuje analizy kolejki ale dla zadań o niższym priorytecie. Zwykle możliwa jest zmiana kolejki w której szeregowane jest zadanie, poprzez zmianę priorytetu zadania. * Planowanie wieloprocesorowe - na jednakowe lub różne procesory a także całe komputery; * Synchronizacja międzyzadaniowa - ze względu na powiązanie zadań różnymi zasobami a nie tylko procesorem, konieczne jest uwzględnienie aspektu dostępu do tych innych zasobów przez szeregowane zadania; 48. Model sekcji krytycznej i warunki jego poprawnego funkcjonowania. Sekcja krytyczna - w programowaniu współbieżnym fragment kodu programu, który w danej chwili powinien być wykonywany przez nie więcej niż jeden wątek. Brak wzajemnego wykluczania się wykonywania sekcji krytycznych może spowodować błędy wykonania, np. dwukrotne zapisanie danej albo niepoprawna modyfikacja. Rozpatrzmy dwa procesy zliczające liczbę wystąpień tego samego elementu:

Kod x = x + 1 rozkłada się na prostsze elementy: 1. wczytaj zmienną X 2. zwiększ zmienną X 3. zapisz zmienną X W komputerze działają dwa takie procesy i zliczają wystąpienia: 1. początkowa wartość x = 1 2. proces 1 wykonuje instrukcję 1 3. system operacyjny przerywa działanie procesu 1 i przekazuje sterowanie do procesu 2, 4. proces 2 wykonuje wszystkie instrukcje i ustawia x na 2, 5. system przełącza działanie na proces 1 6. proces 1 zwiększa pobraną w pierwszym punkcie wartość o 1, czyli do 2, i wykonuje instrukcję 3 zapisując wartość 2. Przy rozdzielnym działaniu programów wartość x powinna równać się 3 a nie 2. Sekcje krytyczne realizuje się np. z wykorzystaniem muteksów lub semaforów. Model sekcji krytycznej Rozważmy system złożony z n procesów. Każdy z nich ma w kodzie fragment zwany sekcją krytyczną. W modelu sekcji krytycznej co najwyżej 1 proces systemu może znajdować się w swojej sekcji krytycznej (jeden lub żaden). Przed wejściem do swojej sekcji krytycznej proces musi dostać na to zgodę (od innych procesów grupy lub od S.O.). Oczekiwanie na zgodę nazywamy sekcją wejściową. Po zakończeniu wykonania sekcji krytycznej proces musi poinformować o jej zakończeniu i, że inni mogą do niej wejść (bo inaczej inni nie będą wiedzieli, że sekcja krytyczna jest wolna) jest to nazywane sekcją wyjściową. Resztę kodu procesu nazywamy resztą. Ogólny schemat procesu korzystającego z sekcji krytycznej While(1) { } /* sekcja wejściowa*/ /* sekcja krytyczna*/ /* sekcja wyjściowa*/ /* reszta*/ Warunki poprawnego funkcjonowania modelu sekcji krytycznej:

1. wzajemne wyłączanie (gdy proces jest w sekcji krytycznej to żaden inny nie może do niej wejść) jest to warunek podstawowy, zazwyczaj spełniony w pierwszej kolejności.; 2. warunek postępu tylko procesy wykonujące sekcję wejściową mogą kandydować do wejścia do sekcji krytycznej, a wybór jednego z nich nie może być odwlekany; 3. ograniczone czekanie jeżeli proces wykonuje sekcję wejściową to istnieje ograniczona liczba wejść do sekcji krytycznej innych programów.