330 likes | 541 Views
Systemy operacyjne. Wykład 9 Zarządzanie pamięcią operacyjną. dr inż. Wojciech Bieniecki Instytut Nauk Ekonomicznych i Informatyki http://wbieniec.kis.p.lodz.pl/pwsz. Cel zarządzania pamięcią. W idealnym świecie pamięć powinna:. - mieć bardzo dużą pojemność.
E N D
Systemy operacyjne Wykład 9 Zarządzanie pamięcią operacyjną dr inż. Wojciech Bieniecki Instytut Nauk Ekonomicznych i Informatyki http://wbieniec.kis.p.lodz.pl/pwsz
Cel zarządzania pamięcią W idealnym świecie pamięć powinna: - mieć bardzo dużą pojemność - mieć bardzo krótki czas dostępu - być nieulotna (zawartość nie jest tracona po wyłączeniu zasilania). W świecie rzeczywistym pamięć jest: - szybka albo - o dużej pojemności albo - tania Cel zarządzania pamięcią Przybliżenie rzeczywistości do ideału
Hierarchia pamięci Przemieszczając się w dół hierarchii Zwiększamy czas dostępu Rejestry Zmniejszamy koszt jednego bajtu Pamięć podręczna Rejestry procesora: dostęp najszybszy, pojemność najmniejsza Pamięć główna Pamięć podręczna (ang. cachememory). Na ogół kilka poziomów (L1,L2, L3). Dysk półprzewodnikowy Dysk magnetyczny Przechowuje najczęściej używane dane z pamięci operacyjnej. Często niewidoczna dla programisty aplikacji. Dysk optyczny Taśma magnetyczna Pamięć operacyjna (DRAM). Średnia szybkość i średni koszt. Pamięć dyskowa: Tania, Nieulotna, Duża pojemność, Bardzo duży czas dostępu
Działanie pamięci Najprostszy model pamięci operacyjnej opisuje ją jako ciąg komórek (lokacji) jednakowego rozmiaru, z których każda posiada unikalny identyfikator. Rozmiar komórki najczęściej wynosi jeden bajt, w przypadku ogólnym jest natomiast wyrażony słowem binarnym. Identyfikator komórki nazywany adresem jest liczbą całkowitą, najczęściej, która w sposób jednoznaczny identyfikuje tę komórkę. Procesor jest połączony z pamięcią trzema magistralami: magistralą sterowania, magistralą danych i magistralą adresową. W komunikacji między tymi układami często również pośredniczy jednostka zarządzania pamięcią (ang. Memory Management Unit MMU). Pamięć operacyjna stanowi podstawowy magazyn danych procesora. Każdy program, który podlega wykonaniu musi być w niej umieszczony.
Wiązanie adresów Program komputerowy przed wykonaniem znajduje się najczęściej na dysku w postaci wykonywalnego pliku binarnego. Na zlecenie użytkownika lub innego programu może on trafić do kolejki wejściowej na dysku, a następnie zostać załadowanym do pamięci operacyjnej i wykonanym. Jeśli program będzie wykonywany wielokrotnie, to może być za każdym razem ładowany do innego miejsca w pamięci. Pamięć komputera zaczyna się zazwyczaj od adresu zero, natomiast pamięć programu, czyli przydzielony mu przez system operacyjny obszar pamięci fizycznej najczęściej nie. Konieczne jest więc przeprowadzenie wiązania adresów wytwarzanych przez program z adresami fizycznymi.
Wiązanie adresów Operacja wiązania może zostać przeprowadzona na różnych etapach przygotowania programu do wykonania. Etap kompilacji W kodzie źródłowym adresy są wyrażane w postaci symbolicznej, czyli są to nazwy zmiennych. Jeśli kompilator dysponuje informacjami, gdzie wygenerowany przez niego kod wynikowy będzie umieszczony w pamięci komputera (tak sie dzieje jedynie w przypadku systemów w których może być uruchamiany jedynie jeden proces użytkownika), to zamienia adresy symboliczne bezpośrednio na adresy fizyczne, nazywane adresami bezwzględnymi. Etap ładowania Jeśli informacje na temat umiejscowienia programu w pamięci nie są znane na etapie kompilacji, to kompilator przekształca adresy symboliczne na adresy względne, inaczej relokowalne liczone względem początku generowanego przez niego bloku kodu. W ten sposób powstaje kod przemieszczalny lub relokowalny. Wiązania adresów względnych z adresami fizycznymi dokonuje program ładujący. Etap wykonania. Jeśli procesor jest wyposażony w odpowiedni sprzęt, to możliwe jest przemieszczanie procesu w pamięci podczas jego wykonania, np.: w celu zrobienia miejsca w pamięci innemu programowi, który będzie do niej załadowany. Tę metodę określa się również mianem dynamicznego wiązania adresów.
Dynamiczne wiązanie adresów Logiczna i fizyczna przestrzeń adresowa Adres logiczny (zwany czasami adresem wirtualnym): z punktu widzenia procesu Adres fizyczny: z punktu widzenia pamięci Translacja adresu: AdrFizyczny=RejestrBazowy+AdrLogiczny Rejestr Limitu służy do realizacji ochrony pamięci AdresFizyczny<L
Zarządzanie pamięcią w systemiejednoprogramowym Jeden program użytkownika => Ochrona pamięci nie jest potrzebna W najprostszym scenariuszu przydziału pamięci cała dostępna pamięć fizyczna jest przydzielana pojedynczemu procesowi, który oprócz określonych zadań wykonuje wszystkie prace charakterystyczne dla systemu operacyjnego, jak np. obsługa przerwań. Takie rozwiązanie jest spotykane w systemach bazujących na mikrokontrolerach.
Zarządzanie pamięcią w systemiejednoprogramowym Bardziej złożony przypadek – w pamięci rezyduje system operacyjny i dokładnie jeden proces użytkownika. Ponieważ system przerwań stanowi część systemu operacyjnego i musi być wraz z nim chroniony, to pamięć dla systemu operacyjnego jest przydzielana tam, gdzie projektanci procesora określili położenie tablicy wektorów przerwań. Najczęściej jest to dolna część pamięci, rozpoczynająca się od adresu 0.
Zarządzanie pamięcią w systemiejednoprogramowym Problem przydziału pamięci procesowi użytkownika jest trudniejszy. Kod tego procesu może być umieszczony bezpośrednio za kodem systemu operacyjnego. Problem, gdy SO chce przydzielić sobie więcej pamięci. Doraźne rozwiązanie – umieszczenie systemu operacyjnego na początku pamięci , a procesu użytkownika w pamięci górnej, tak aby ostatni adres programu użytkownika był jednocześnie ostatnim adresem w pamięci operacyjnej. Dzięki temu pośrodku pamięci operacyjnej powstaje obszar pamięci wolnej, z którego mogą dowolnie korzystać oba procesy.
Systemy wieloprogramowePartycje o stałym rozmiarze Pamięć operacyjna podzielona na obszary o stałym rozmiarze. – Rozmiary poszczególnych obszarów mogą się różnić – Do którego obszaru załadować program ? Program ładowany jest do wolnego obszaru. – Wspólna kolejka programów – Odrębne kolejki dla każdego obszaru – Proces trafia do kolejki związanej z najmniejszym obszarem zdolnym zmieścić proces
Przydział dynamiczny - przykład Załóżmy że w kolejce procesów gotowych systemu, który stosuje szeregowanie FCFS jest 5 procesów, które potrzebują odpowiednio: 600KB, 1000KB, 300KB, 700KB i 500KB pamięci. Dostępnych jest tylko 2560KB pamięci operacyjnej. Można ją przydzielić od razu pierwszemu, drugiemu i trzeciemu procesowi. W pamięci zostanie dziura (D), miejsce wolne, które będzie nie wystarczające, dla żadnego z pozostałych procesów. Będą musiały poczekać, aż zakończy sie jeden z trzech procesów, które są już w pamięci. Jako pierwszy zakończył się proces drugi. W pamięci powstają zatem dwa ciągłe obszary wolne. Okazuje sie, ze dziurę po P2 można przydzielić tylko jednemu z procesów, z kolejki. Tym procesem będzie proces P4.
Przydział dynamiczny - przykład Po tym przydziale w pamięci operacyjnej nadal istnieją dwie dziury, o sumarycznej wielkości 560KB. Ta wielkość spełnia wymagania programu piątego (500KB), ale ponieważ te dziury nie tworzą obszaru spójnego, to nie można ich przydzielić temu procesowi. Następnym procesem, który zakończy swa prace będzie proces P1. Po jego zakończeniu w pamięci operacyjnej pojawia się ciągły obszar wolny o wielkości 600KB, co pozwala na spełnienie zapotrzebowania na pamięć ze strony procesu piątego. Z tej dziury procesowi P5 zostanie przydzielone dokładnie 500KB. Po wykonaniu ostatniego z przydziałów w pamięci operacyjnej powstają trzy niespójne wolne obszary o łącznej pojemności 660KB.
Strategie wyboru dziury SO utrzymuje ewidencję wolnych oraz zajętych obszarów pamięci i na bieżąco podejmuje decyzję, który z wolnych obszarów przydzielić czekającym procesom. To planowanie wymaga określenia strategii wyboru dziury, jeśli jest ich wiele. Pierwsza pasująca (ang. first-fit) Przydzielana jest pierwsza dziura, która spełnia wymagania procesu co do rozmiaru. Jej poszukiwanie może rozpoczynać się zawsze od początku wykazu miejsc wolnych lub od miejsca ostatniego przydziału (ang. next-fit). Najlepiej pasująca (ang. best fit) Przydziela sie dziurę, która dokładnie spełnia wymagania co do rozmiaru, lub dla której różnica miedzy jej rozmiarem, a rozmiarem wymaganym jest najmniejsza spośród pozostałych dziur. Najgorzej pasująca (ang. worst fit) przydziela sie największą dziurę w systemie. Zakłada się, że proces zażąda w czasie wykonania dodatkowej pamięci. Przy zastosowaniu tej strategii istnieje duże prawdopodobieństwo, ze zadanie to zostanie od razu zrealizowane. Symulacje wykazały, że najlepsze rezultaty uzyskuje się przy zastosowaniu strategii Pierwsza pasująca i Najlepiej pasująca. Z praktycznego punktu widzenia ta pierwsza jest lepsza ponieważ działa szybciej.
Fragmentacja pamięci Zjawisko występuje powszechnie w systemach, które stosują dynamiczny przydział pamięci. Rozróżniamy dwa rodzaje tego zjawiska: Fragmentacja zewnętrzna Występuje, gdy w pamięci operacyjnej istnieje wiele obszarów wolnych, których sumaryczna wielkość pozwalałaby na spełnienie zadania przydziału pamięci przez proces, ale każdy z osobna z tych obszarów ma zbyt mała pojemność, żeby to było możliwe. Fragmentacja wewnętrzna Występuje, gdy procesowi przydzielane jest więcej pamięci, niż on potrzebuje. Ta dodatkowa pamięć nie będzie nigdy przez niego wykorzystana. Przydział taki może być podyktowany względami ekonomicznymi: nie jest opłacalne utrzymywanie 2 bajtowej dziury w pamięci, jeśli należy zapamiętać o wiele więcej informacji o niej. Reguła 50% Po dużej liczbie cykli przydziałów i zwolnień będziemy w stanie przydzielić tylko połowę wolnej pamięci. Możemy zapobiegać temu zjawisku stosując kompakcję (upakowanie pamięci), tzn. okresowe przemieszczanie procesów, tak aby w pamięci powstał jeden ciągły obszar. System operacyjny powinien tak wykonywać te operacje, aby czas potrzebny na jej wykonanie był jak najmniejszy.
Wzrost wymagań procesu na pamięć Proces może zwiększać swoje wymagania na pamięć. Dotyczy to stosu i danych. Strategia: Przydziel większy blok pamięci niż wymagany na początku – mała wydajność
Ochrona granic pamięci przy realokacji Jeśli dopuszczamy relokacje procesów podczas wykonania, należy sprawdzić, czy adres logiczny wygenerowany przez program nie jest większy niż zawartość rejestru granicznego, a następnie, jeśli ten test sie powiódł dodać do niego zawartość rejestru przemieszczenia. Celem zmniejszenia fragmentacji programy dzieli sie na części. Najczęściej są to dwie części: zawierająca kod i zawierająca dane. Do ochrony tych części służą osobne pary rejestrów bazowych i granicznych. Jeśli chcemy wykonać podział programów na więcej części, to musimy mieć odpowiednio więcej par wymienionych rejestrów. Zastosowanie zwielokrotnionych rejestrów bazowych i granicznych pozwala również na określenie sposobu dostępu do danego fragmentu pamięci (np. tylko odczyt dla stałych) lub współdzielenie tych fragmentów przez kilka procesów (np. obszar kodu).
Stronicowanie Stronicowanie (ang. paging) jest systemem zarządzania pamięcią, który rozwiązuje problem zewnętrznej fragmentacji pamięci pozwalając, aby pamięć przydzielana była nieciągła. Pamięć fizyczna jest podzielona na ramki (ang. frame) o stałym rozmiarze, będącym potęgą dwójki (512B – 4KB). Przestrzeń adresowa procesu jest podzielona na strony (ang. page), rozmiar strony jest równy rozmiarowi ramki. I–tej stronie w przestrzeni adresowej procesu odpowiada K-ta ramka. Dla dowolnego I, K może być dowolne. Adres generowany przez procesor jest podzielony na dwie części: Numer strony (p) oraz przesunięcie na stronie (d) Przykład strona ma rozmiar 4KB=2^12 bajtów, adres ma 32 bity
Przykład stronicowania Aby proces mógł być załadowany do pamięci musi jedynie istnieć odpowiednia liczba wolnych ramek dla niego. Strony w ramkach nie musza być umieszczane po kolei, fizycznie pamięć procesu nie musi być ciągła. Po lewej stronie znajduje się pamięć logiczna, w środku tablica stron, a po prawej pamięć fizyczna. Stronicowanie eliminuje całkowicie fragmentację zewnętrzną, ale nie jest odporne na fragmentacje wewnętrzną. Ta fragmentacja dotyczy ostatniej ramki przydzielonej procesowi i w skrajnych przypadkach może wynosić rozmiar strony minus jeden bajt.
Translacja adresu w stronicowaniu Translacja adresu logicznego na fizyczny wymaga odnalezienia w tablicy stron elementu o określonym przez numer strony indeksie, odczytaniu z niego adresu bazowego ramki i zastąpieniu nim numeru strony w adresie. Nr strony przesunięcie Nr ramki Nr ramki
Tablica stron W każdym przypadku stronicowanie wymaga wspomagania sprzętowego. Każdy proces ma własną tablicę stron. Procesor ma rejestr bazowy tablicy stron, zawierający adres początku tablicy stron aktywnego procesu. Liczba elementów w tablicy stron jest przechowywana w rejestrze długości tablicy stron Zawartość obydwu rejestrów jest zmieniana przy przełączaniu kontekstu. Przy naiwnej sprzętowej implementacji tego schematu każde, odwołanie do pamięci przez proces wymaga wykonania dwóch cykli dostępu do pamięci. Jeden cykl aby znaleźć numer ramki w tablicy stron Jeden cykl na wykonanie właściwej operacji Szybkość dostępu do pamięci spada dwukrotnie
Przykład stronicowania W pamięci procesy A, B. Załaduj C. W pamięci procesy A, B, C. Zakończ B. W pamięci procesy A, C. Załaduj D. Struktury systemu po załadowaniu D.
rejestr asocjacyjny TLB TLB (ang. Translation Lookaside Buffer) Przechowywany w procesorze Zawiera numer strony oraz odpowiadający mu numer ramki dla k (np k=32) najczęściej używanych stron. Jeżeli numer strony występuje w buforze TLB, to nie jest wymagany dostęp do tablicy stron. Jeżeli nie występuje, wykonywany jest dostęp do tablicy stron a para (Strona, Ramka) jest wprowadzana do bufora TLB Efektywny czas dostępu do pamięci tema zależy od współczynnika trafień h (ang. hit ratio). W praktyce h > 95%. tema = h · (tTLBa + tma) + (1 − h) · (tTLBa + 2 · tma) tTLBa jest czasem dostępu do rejestrów TLB, a tma czasem dostępu do pamięci. Uwaga: przełączenie kontekstu wymaga opróżnienia bufora TLB
Ochrona przy stronicowaniu Istnieje sprzętowy mechanizm ochrony, którego naruszenie (np. przez proces wykonywujący się w trybie użytkownika) powoduje zgłoszenie wyjątku (przerwania) stronicowania (ang. pagefault) Możliwość określenia długości tablicy stron (rozmiaru przestrzeni adresów logicznych procesu). Bit ważności związany z każdą stroną i przechowywany w tablicy stron – Strona ważna => obecna w pamięci – Strona nieważna => próba dostępu powoduje wyjątek stronicowania. – Możliwość realizacji "dziur" w logicznej przestrzeni adresowej. Strony, którym nie odpowiada zaalokowana pamięć mają wyzerowany bit ważności. Trzy bity, które określają rodzaj dostępu do określonej strony: odczyt, zapis, wykonanie (w notacji uniksowej: rwx). Dzięki odpowiednim kombinacjom tych bitów można uzyskać różne formy kontroli dostępu do stron, np. tylko odczyt i zapis. Bit trybu jądra – próba dostępu do strony z ustawionym bitem trybu jądra z procesu wykonywującego się w trybie użytkownika powoduje wyjątek stronicowania . W ten sposób jądro chroni swoją pamięć przed programami użytkowników.
Pamięć współdzielona – przykład Niech pamięć edytora tekstu składa się z 3 stron kodu i jednej strony z danymi. Trzech użytkowników uruchomiło edytor. Czy musimy trzykrotnie wczytać kod do pamięci (razem dziewięć stron) ? Jeżeli kod jest kodem niemodyfikującym się, to nie. Kod taki nazywa się wznawialnym lub współużywalnym (ang. reentrant). Trzy ramki z kodem zostały odwzorowane w przestrzeń adresową trzech procesów, każda z nich jest współdzielona przez trzy procesy. Wymagana jest implementacja bitu ochrony przed zapisem – aby nie pozwolić żadnemu z trzech procesów na modyfikację stron z kodem. Pamięć współdzielona może być również wykorzystana do bardzo szybkiej wymiany danych pomiędzy procesami.
Stronicowanie dwupoziomowe Tablica stron może mieć duży rozmiar. Niech adres logiczny ma 32 bity, przestrzeń adresowa na rozmiar 4GB. Jeżeli pozycja w tablicy stron ma 4 bajty, to na tablicę stron potrzebujemy 4MB. Zastosujemy stronicowanie wielopoziomowe Idea: Tablica stron podlega stronicowaniu. Tablica stron pierwszego poziomu przechowuje numery stron w tablicy drugiego poziomu Każdej pozycji w tablicy stron pierwszego poziomu odpowiada tablica stron drugiego poziomu. Tablica stron drugiego poziomu przechowuje numery stron.
Stronicowanie - podsumowanie Eliminuje fragmentacje zewnętrzną Fragmentacja wewnętrzna jest ograniczona do rozmiaru strony. Łatwa realizacja ochrony pamięci Łatwa realizacja dynamicznego wzrostu obszaru przydzielonej pamięci. (wraz z przydzielaniem dodatkowych ramek zaznaczaj bit ważności.) Możliwość implementacji pamięci wirtualnej. – Część przestrzeni adresowej procesu w pamięci, część na dysku. – Rozmiar przestrzeni adresowej procesu większy od pojemności pamięci RAM.
Segmentacja Stronicowanie jest niewidoczne dla programistów języków zarówno wysokiego poziomu jak i asemblera. Programy te tworzone są tak samo jak dla komputerów, które nie obsługują stronicowania. Pamięć logiczna procesów jest dzielona na równie obszary, niezależnie od tego, czy zawierają one dane, czy kod. Segmentacja(ang. segmentation) – pamięć logiczna jest dzielona na obszary o różnej wielkości, które zawierają logicznie odrębne fragmenty kodu. Osobny segment może zawierać rozkazy programu, inny dane, a w jeszcze inny – stos. Segmentację można pogłębić: w osobnych segmentach można zamykać np.: stałe programu lub poszczególne struktury danych. Segmentacja jest wiec bliższa wyobrażeniu programisty na temat pamięci procesu, niż stronicowanie.
Segmentacja Asembler umożliwia ręczne określenie segmentów i kwalifikację poszczególnych fragmentów kodu do nich. W języku wysokiego poziomu podział tworzony jest automatycznie przez kompilator zależnie od jego parametrów. Każdy segment ma swój unikalny numer. Podobnie jak w przypadku stronicowania do translacji adresów potrzebna jest tablica nazywana tutaj tablicą segmentów. W procesorach Intel wymusza się podział procesy na trzy segmenty: kodu, danych i stosu. Tablica segmentów jest realizowana za pomocą rejestrów CS, DS i SS. Segmentacja jest pozbawiona fragmentacji wewnętrznej, ale obarczona jest fragmentacją zewnętrzną. Ponieważ rozmiary segmentów nie są na ogół duże, to nie jest ona tak dotkliwa jak w przypadku przydziału obszarów ciągłych pamięci. Segmentacja podobnie jak stronicowanie jest formą dynamicznego wiązania adresów, więc można do eliminacji fragmentacji zewnętrznej zastosować technikę upakowania.
Segmentacja – translacja adresów Adres logiczny składa się z numeru segmentu s i z przesunięcia d względem początku tego segmentu. Numer segmentu z adresu logicznego jest indeksem w tablicy segmentów. Każdy element tej tablicy zawiera dwie wartości: wielkość segmentu (granica) oraz adres bazowy segmentu (baza). Przesuniecie dodawane jest do adresu bazowego segmentu i wykonywane jest odwołanie do pamięci fizycznej. Przesunięcie w adresie logicznym większe niż wielkość segmentu, generuje wyjątek adresowania. Translacja adresów w segmentacji wraz ze sprawdzeniem ich poprawności wykonywana jest sprzętowo.
Segmentacja stronicowana Mechanizmy zarządzania pamięcią, takie jak stronicowanie i segmentacja można połączyć - oba są również realizacjami koncepcji dynamicznego przydziału pamięci. Segmentacja stronicowana ma zaletę stronicowania – nie jest obarczona fragmentacja zewnętrzną. Z drugiej strony pozwala lepiej dopasować się do logicznej struktury kodu procesu co jest zaletą segmentacji. To rozwiązanie stosował system Multics. Adres logiczny w segmentacji stronicowanej ma te sama strukturę, co w zwykłej segmentacji. Z tablicy segmentów nie jest jednak odczytywany adres bazowy segmentu, ale adres początku tablicy stron tego segmentu. Przesuniecie w segmencie podzielone jest na dwie części: numer strony oraz przesuniecie na tej stronie. Ten system zarządzania pamięcią ze względu na swój stopień skomplikowania jest rzadko stosowany.