Systemy operacyjne: trzy łatwe elementy. Część 2: Abstrakcja: Proces (tłumaczenie)

Wprowadzenie do systemów operacyjnych

Hej Habra! Pragnę zwrócić Państwa uwagę na cykl artykułów-przekładów jednej ciekawej moim zdaniem literatury - OSTEP. Ten materiał dość szczegółowo omawia działanie uniksowych systemów operacyjnych, a mianowicie pracę z procesami, różnymi programami planującymi, pamięcią i innymi podobnymi komponentami, które składają się na nowoczesny system operacyjny. Oryginał wszystkich materiałów można zobaczyć tutaj tutaj. Zaznaczam, że tłumaczenie zostało wykonane nieprofesjonalnie (dość swobodnie), ale mam nadzieję, że zachowałem ogólny sens.

Pracę laboratoryjną na ten temat można znaleźć tutaj:

Inne części:

Możesz również sprawdzić mój kanał na telegram =)

Przyjrzyjmy się najbardziej podstawowej abstrakcji, którą system operacyjny udostępnia użytkownikom: procesowi. Definicja procesu jest dość prosta – tak jest uruchomiony program. Sam program jest martwą rzeczą znajdującą się na dysku - jest to zestaw instrukcji i ewentualnie jakieś statyczne dane czekające na uruchomienie. To system operacyjny pobiera te bajty i uruchamia je, przekształcając program w coś użytecznego.
Najczęściej użytkownicy chcą uruchomić więcej niż jeden program jednocześnie, na przykład na swoim laptopie można uruchomić przeglądarkę, grę, odtwarzacz multimedialny, edytor tekstu i tym podobne. W rzeczywistości typowy system może jednocześnie uruchamiać dziesiątki lub setki procesów. Fakt ten sprawia, że ​​system jest łatwiejszy w użyciu, nigdy nie musisz się martwić o to, czy procesor jest wolny, po prostu uruchamiasz programy.

Rodzi to problem: jak zapewnić iluzję wielu procesorów? W jaki sposób system operacyjny może stworzyć iluzję niemal nieskończonej liczby procesorów, nawet jeśli masz tylko jeden fizyczny procesor?

System operacyjny tworzy tę iluzję poprzez wirtualizację procesora. Uruchamiając jeden proces, następnie zatrzymując go, uruchamiając inny proces itd., system operacyjny może utrzymać iluzję, że istnieje wiele wirtualnych procesorów, podczas gdy w rzeczywistości będzie jeden lub więcej procesorów fizycznych. Ta technika nazywa się podział zasobów procesora według czasu. Technika ta pozwala użytkownikom na uruchamianie dowolnej liczby współbieżnych procesów. Kosztem tego rozwiązania jest wydajność - ponieważ jeśli procesor jest współdzielony przez kilka procesów, każdy proces będzie przetwarzany wolniej.
Aby wdrożyć wirtualizację procesora, a zwłaszcza zrobić to dobrze, system operacyjny potrzebuje wsparcia zarówno niskiego, jak i wysokiego poziomu. Nazywa się wsparcie niskiego poziomu mechanizmy to metody lub protokoły niskiego poziomu, które implementują wymaganą część funkcjonalności. Przykładem takiej funkcjonalności jest przełączanie kontekstu, które daje systemowi operacyjnemu możliwość zatrzymania jednego programu i uruchomienia innego programu na procesorze. Ten podział czasu jest realizowany we wszystkich nowoczesnych systemach operacyjnych.
Oprócz tych mechanizmów istnieje pewna logika wbudowana w system operacyjny w postaci „polityk”. Polityka to pewien algorytm podejmowania decyzji dla systemu operacyjnego. Takie polityki decydują na przykład, który program powinien zostać uruchomiony (z listy poleceń) jako pierwszy. Na przykład ten problem zostanie rozwiązany za pomocą polityki o nazwie harmonogram (polityka planowania) a przy wyborze rozwiązania będzie się kierować takimi danymi jak: historia uruchomień (który program został uruchomiony najdłużej w ciągu ostatnich minut), jakie obciążenie niesie ten proces (jakie typy programów zostały uruchomione), metryki wydajnościowe (czy system jest zoptymalizowany pod kątem interakcji interaktywnej lub przepustowości) i tak dalej.

Abstrakcja: proces

Nazywamy to abstrakcją działającego programu wykonywanego przez system operacyjny proces. Jak wspomniano wcześniej, proces to po prostu działający program w dowolnej chwili. Program, za pomocą którego możemy uzyskać podsumowanie informacji z różnych zasobów systemowych, do których ten program uzyskuje dostęp lub na które ma wpływ podczas jego wykonywania.
Aby zrozumieć elementy procesu, należy zrozumieć stany systemu: co program może odczytać lub zmienić w trakcie swojego działania. W każdym momencie musisz zrozumieć, które elementy systemu są ważne dla wykonania programu.
Jednym z oczywistych elementów stanu systemu, który obejmuje proces jest pamięć. Instrukcje znajdują się w pamięci. Dane, które program odczytuje lub zapisuje, również znajdują się w pamięci. Zatem pamięć, którą proces może zaadresować (zwana przestrzenią adresową), jest częścią procesu.
Częścią stanu systemu są także rejestry. Wiele instrukcji ma na celu zmianę wartości rejestrów lub odczytanie ich wartości, dlatego rejestry również stają się ważną częścią działania procesu.
Należy zauważyć, że stan maszyny jest również tworzony na podstawie niektórych specjalnych rejestrów. Na przykład, IP - wskaźnik instrukcji — wskaźnik do instrukcji, którą aktualnie wykonuje program. Jest również wskaźnik stosu i z tym związane wskaźnik ramki, które służą do zarządzania: parametrami funkcji, zmiennymi lokalnymi i adresami zwrotnymi.
Wreszcie programy często uzyskują dostęp do pamięci ROM (pamięci tylko do odczytu). Te informacje „we/wy” (wejścia/wyjścia) powinny zawierać listę plików aktualnie otwartych przez proces.

API procesu

Aby lepiej zrozumieć działanie tego procesu, przeanalizujmy przykłady wywołań systemowych, które powinny znaleźć się w interfejsie dowolnego systemu operacyjnego. Te interfejsy API są dostępne w takiej czy innej formie w dowolnym systemie operacyjnym.

Stwórz (tworzenie): System operacyjny musi zawierać jakąś metodę umożliwiającą tworzenie nowych procesów. Kiedy wpiszesz polecenie w terminalu lub uruchomisz aplikację poprzez dwukrotne kliknięcie ikony, do systemu operacyjnego zostanie wysłane wezwanie w celu utworzenia nowego procesu, a następnie uruchomienia określonego programu.
Usuwanie: Ponieważ istnieje interfejs do tworzenia procesu, system operacyjny powinien także zapewniać możliwość wymuszenia usunięcia procesu. Większość programów w naturalny sposób uruchamia się i kończy samoistnie w trakcie działania. W przeciwnym razie użytkownik chciałby mieć możliwość ich zabicia i dlatego przydatny byłby interfejs do zatrzymania procesu.
Czekać (oczekiwanie): Czasami warto poczekać na zakończenie procesu, dlatego dostępne są interfejsy umożliwiające oczekiwanie.
Różne sterowanie (różna kontrola): Oprócz zabijania i czekania na proces istnieją również inne różne metody kontroli. Na przykład większość systemów operacyjnych zapewnia możliwość zamrożenia procesu (zatrzymania jego wykonywania na określony czas), a następnie wznowienia go (kontynuowania wykonywania)
Rynek (stan): Istnieją różne interfejsy umożliwiające uzyskanie pewnych informacji o statusie procesu, takich jak czas jego działania lub stan, w jakim się aktualnie znajduje.

Systemy operacyjne: trzy łatwe elementy. Część 2: Abstrakcja: Proces (tłumaczenie)

Tworzenie procesu: szczegóły

Jedną z interesujących rzeczy jest to, w jaki sposób dokładnie programy przekształcają się w procesy. Zwłaszcza sposób, w jaki system operacyjny pobiera i uruchamia program. Jak dokładnie powstaje proces.
Przede wszystkim system operacyjny musi załadować kod programu i dane statyczne do pamięci (do przestrzeni adresowej procesu). Programy są zwykle zlokalizowane na dysku lub dysku SSD w jakimś formacie wykonywalnym. Zatem proces ładowania programu i danych statycznych do pamięci wymaga, aby system operacyjny mógł odczytać te bajty z dysku i umieścić je gdzieś w pamięci.

We wczesnych systemach operacyjnych proces ładowania przebiegał ochoczo, co oznacza, że ​​cały kod został załadowany do pamięci przed uruchomieniem programu. Nowoczesne systemy operacyjne robią to leniwie, to znaczy ładują fragmenty kodu lub dane tylko wtedy, gdy program ich potrzebuje podczas swojego działania.

Po załadowaniu kodu i danych statycznych do pamięci systemu operacyjnego należy wykonać jeszcze kilka czynności, zanim proces będzie mógł zostać uruchomiony. Na stos należy przydzielić pewną ilość pamięci. Programy używają stosu do przechowywania zmiennych lokalnych, parametrów funkcji i adresów zwrotnych. System operacyjny przydziela tę pamięć i przekazuje ją procesowi. Stos może być również przydzielony pewnymi argumentami, w szczególności wypełnia parametry funkcji main(), na przykład tablicą argc i argv.

System operacyjny może również przydzielić część pamięci do sterty programu. Sterta jest używana przez programy do jawnego żądania dynamicznie przydzielanych danych. Programy żądają tego miejsca, wywołując funkcję malloc () i czyści go jawnie, wywołując funkcję darmowy(). Sterta jest potrzebna w przypadku struktur danych, takich jak połączone arkusze, tablice mieszające, drzewa i inne. Na początku do sterty przydzielana jest niewielka ilość pamięci, ale z biegiem czasu, w miarę działania programu, sterta może zażądać większej ilości pamięci za pośrednictwem wywołania API biblioteki malloc(). System operacyjny bierze udział w procesie przydzielania większej ilości pamięci, aby pomóc w obsłużeniu tych wywołań.

System operacyjny będzie również wykonywał zadania inicjalizacji, szczególnie te związane z operacjami we/wy. Na przykład w systemach UNIX każdy proces ma domyślnie 3 otwarte deskryptory plików, dla standardowego wejścia, wyjścia i błędu. Uchwyty te umożliwiają programom odczytywanie danych wejściowych z terminala, a także wyświetlanie informacji na ekranie.

Zatem ładując kod i dane statyczne do pamięci, tworząc i inicjując stos oraz wykonując inne prace związane z wykonywaniem zadań we/wy, system operacyjny przygotowuje scenę do wykonania procesu. Na koniec pozostało jeszcze ostatnie zadanie: uruchomienie programu przez jego punkt wejścia, zwany funkcją main(). Wykonując funkcję main(), system operacyjny przekazuje kontrolę nad procesorem nowo utworzonemu procesowi, w związku z czym program rozpoczyna wykonywanie.

Stan procesu

Teraz, gdy mamy już pewne pojęcie o tym, czym jest proces i jak jest tworzony, wypiszmy stany procesu, w jakich może się on znajdować. W najprostszej formie proces może znajdować się w jednym z następujących stanów:
Bieganie. Podczas działania proces działa na procesorze. Oznacza to, że instrukcje są wykonywane.
Gotowy. W stanie gotowości proces jest gotowy do uruchomienia, ale z jakiegoś powodu system operacyjny nie wykonuje go w określonym czasie.
Zablokowany. W stanie zablokowanym proces wykonuje pewne operacje, które uniemożliwiają mu gotowość do wykonania do czasu wystąpienia jakiegoś zdarzenia. Typowym przykładem jest sytuacja, gdy proces inicjuje operację we/wy, zostaje ona zablokowana, dzięki czemu inny proces może skorzystać z procesora.

Systemy operacyjne: trzy łatwe elementy. Część 2: Abstrakcja: Proces (tłumaczenie)

Można sobie wyobrazić te stany w formie wykresu. Jak widać na obrazku, stan procesu może zmieniać się pomiędzy RUNNING i READY, w zależności od uznania systemu operacyjnego. Zmiana stanu procesu z READY na RUNNING oznacza, że ​​proces został zaplanowany. W przeciwnym kierunku - usunięte z układu. W momencie, gdy proces zostanie ZABLOKOWANY, np. zainicjuję operację IO, system operacyjny utrzyma go w tym stanie do momentu wystąpienia jakiegoś zdarzenia, na przykład zakończenia IO. w tym momencie przejście do stanu READY i ewentualnie od razu do stanu RUNNING jeśli system operacyjny tak postanowi.
Spójrzmy na przykład, jak dwa procesy przechodzą przez te stany. Na początek wyobraźmy sobie, że oba procesy są uruchomione i każdy używa tylko procesora. W tym przypadku ich stany będą wyglądać następująco.

Systemy operacyjne: trzy łatwe elementy. Część 2: Abstrakcja: Proces (tłumaczenie)

W poniższym przykładzie pierwszy proces po pewnym czasie działania żąda wejścia/wyjścia i przechodzi w stan ZABLOKOWANY, umożliwiając uruchomienie innego procesu (RYSUNEK 1.4). System operacyjny widzi, że proces 0 nie używa procesora i uruchamia proces 1. Podczas gdy proces 1 jest uruchomiony, operacja we/wy jest zakończona, a status procesu 0 zmienia się na GOTOWY. Wreszcie proces 1 zakończył się, a po jego zakończeniu proces 0 rozpoczyna, wykonuje i kończy swoją pracę.

Systemy operacyjne: trzy łatwe elementy. Część 2: Abstrakcja: Proces (tłumaczenie)

Struktura danych

Sam system operacyjny jest programem i, jak każdy inny program, ma pewne kluczowe struktury danych, które śledzą różne istotne informacje. Aby śledzić stan każdego procesu, system operacyjny będzie obsługiwał niektóre z nich Lista procesów dla wszystkich procesów w stanie READY oraz dodatkowe informacje umożliwiające śledzenie aktualnie uruchomionych procesów. Ponadto system operacyjny powinien monitorować zablokowane procesy. Po zakończeniu operacji we/wy system operacyjny musi obudzić wymagany proces i ustawić go w stanie gotowym do uruchomienia.

Na przykład system operacyjny musi zachować stan rejestrów procesora. W momencie zatrzymania procesu stan rejestrów zapisywany jest w przestrzeni adresowej procesu, a w momencie kontynuacji jego działania wartości rejestrów są przywracane i tym samym kontynuacja realizacji tego procesu.

Oprócz stanów gotowości, zablokowania i działania istnieją inne stany. Czasami w momencie tworzenia proces może znajdować się w stanie INIT. Wreszcie proces może zostać wprowadzony w stan KOŃCOWY, gdy jest już zakończony, ale zawarte w nim informacje nie zostały jeszcze wyczyszczone. W systemach UNIX stan ten nazywany jest proces zombie. Ten stan jest przydatny w przypadkach, gdy proces nadrzędny chce poznać kod zwrotny potomka, na przykład zwykle 0 oznacza sukces, a 1 błąd, ale programiści mogą wygenerować dodatkowe kody wyjściowe, aby zasygnalizować różne problemy. Kiedy proces nadrzędny się kończy, wykonuje końcowe wywołanie systemowe, takie jak wait(), aby poczekać, aż proces potomny zakończy się i zasygnalizuje systemowi operacyjnemu, że może wyczyścić wszelkie dane powiązane z zakończonym procesem.

Systemy operacyjne: trzy łatwe elementy. Część 2: Abstrakcja: Proces (tłumaczenie)

Kluczowe punkty wykładu:

proces — główna abstrakcja działającego programu w systemie operacyjnym. W dowolnym momencie proces można opisać na podstawie jego stanu: zawartości pamięci w jego przestrzeni adresowej, zawartości rejestrów procesora, w tym wskaźnika instrukcji i wskaźnika stosu, oraz informacji we/wy, takich jak odczytywanie lub zapisywanie otwartych plików.
API procesu składa się z wywołań, które programy mogą wykonywać do procesów. Zazwyczaj są to wywołania tworzenia, usuwania lub inne.
● Proces znajduje się w jednym z wielu stanów, m.in. uruchomiony, gotowy, zablokowany. Różne zdarzenia, takie jak planowanie, wyjątki od harmonogramu lub oczekiwania, mogą zmieniać stan procesu z jednego na drugi.
Lista procesów zawiera informacje o wszystkich procesach zachodzących w systemie. Każdy znajdujący się w nim wpis nazywany jest blokiem sterowania procesem, który w rzeczywistości jest strukturą zawierającą wszystkie niezbędne informacje o konkretnym procesie. 

Źródło: www.habr.com

Dodaj komentarz