Uwaga : jeśli musisz wziąć pod uwagę konkretny system operacyjny, aby móc odpowiedzieć, rozważ Linux.
Ilekroć uruchamiam program, dostanie on przestrzeń pamięci wirtualnej do uruchomienia, z obszarem na stos i jednym na stos.
Pytanie 1 : czy stos i sterta mają limit wielkości statycznej (np. 2 gigabajty każdy), czy też limit ten jest dynamiczny, zmienia się zgodnie z przydziałami pamięci podczas wykonywania programu (tj. 4 gigabajty do wykorzystania przez oba, więc jeśli program używa tylko stosu, będzie mógł mieć stos z 4 gigabajtami)?
Pytanie 2 : Jak zdefiniowany jest limit? Czy jest to całkowita dostępna pamięć RAM?
Pytanie 3 : Co z sekcjami tekstu (kodu) i danych, w jaki sposób są one ograniczone?
Odpowiedzi:
Istnieją dwa różne limity pamięci. Limit pamięci wirtualnej i limit pamięci fizycznej.
Pamięć wirtualna
Pamięć wirtualna jest ograniczona rozmiarem i układem dostępnej przestrzeni adresowej. Zwykle na samym początku kod wykonywalny oraz dane statyczne i przeszłość powiększają stertę, podczas gdy na końcu jest obszar zarezerwowany przez jądro, zanim udostępnione biblioteki i stos (które na większości platform rosną). Daje to wolną przestrzeń na stosy i stosy, a inne obszary są znane podczas uruchamiania procesu i naprawione.
Wolna pamięć wirtualna nie jest początkowo oznaczana jako użyteczna, ale jest oznaczana podczas przydzielania. Podczas gdy sterty mogą rosnąć do całej dostępnej pamięci, większość systemów nie powiększa automatycznie stosów. Domyślny limit IIRC dla stosu wynosi 8 MB w systemie Linux i 1 MB w systemie Windows i można go zmienić w obu systemach. Pamięć wirtualna zawiera także pliki i sprzęt mapowane w pamięci.
Jednym z powodów, dla których stos nie może być automatycznie rozwijany (arbitralnie), jest to, że programy wielowątkowe potrzebują osobnego stosu dla każdego wątku, aby w końcu mogły sobie wzajemnie przeszkodzić.
Na platformach 32-bitowych całkowita ilość pamięci wirtualnej wynosi 4GiB, zarówno Linux, jak i Windows zwykle rezerwują ostatnie 1GiB dla jądra, co daje maksymalnie 3GiB przestrzeni adresowej. Istnieje specjalna wersja systemu Linux, która nie rezerwuje niczego, co daje pełne 4GiB. Jest przydatny w rzadkich przypadkach dużych baz danych, w których ostatni 1GiB oszczędza dzień, ale przy regularnym użyciu jest nieco wolniejszy z powodu dodatkowych przeładowań tabeli stron.
Na platformach 64-bitowych pamięć wirtualna to 64EiB i nie musisz o tym myśleć.
Pamięć fizyczna
Pamięć fizyczna jest zwykle przydzielana przez system operacyjny tylko wtedy, gdy proces potrzebuje do niej dostępu. Ilość pamięci fizycznej wykorzystywanej przez proces jest bardzo rozmyta, ponieważ część pamięci jest dzielona między procesami (kod, biblioteki współdzielone i wszelkie inne mapowane pliki), dane z plików są ładowane do pamięci na żądanie i usuwane, gdy brakuje pamięci i Pamięć „anonimowa” (pamięć nieopartą na plikach) może zostać zamieniona.
W systemie Linux, co się stanie, gdy zabraknie pamięci fizycznej, zależy od
vm.overcommit_memory
ustawień systemowych. Domyślnie jest to zbyt duże. Gdy poprosisz system o alokację pamięci, daje ci trochę, ale tylko alokuje pamięć wirtualną. Gdy faktycznie uzyskasz dostęp do pamięci, spróbuje ona użyć pewnej pamięci fizycznej, odrzucając dane, które można ponownie odczytać, lub w razie potrzeby wymieniając różne rzeczy. Jeśli stwierdzi, że nic nie może uwolnić, po prostu usunie proces z istnienia (nie ma sposobu, aby zareagować, ponieważ reakcja ta może wymagać więcej pamięci, co doprowadziłoby do nieskończonej pętli).W ten sposób umierają procesy na Androidzie (którym jest także Linux). Logika została ulepszona o logikę, którą proces usunąć z istnienia na podstawie tego, co robi proces i ile ma lat. Procesy Androida po prostu przestają cokolwiek robić, ale siedzą w tle, a „zabójca pamięci” zabije je, gdy będzie potrzebował pamięci na nowe.
źródło
Myślę, że łatwiej jest odpowiedzieć na to pytanie według kolejności wykorzystania pamięci.
Pytanie 3: Co z sekcjami tekstu (kodu) i danych, w jaki sposób są one ograniczone? Tekst i dane są przygotowywane przez kompilator. Wymaganiem kompilatora jest upewnienie się, że są one dostępne i spakowanie ich w dolnej części przestrzeni adresowej. Dostępna przestrzeń adresowa będzie ograniczona sprzętowo, np. Jeśli rejestr wskaźnika instrukcji jest 32-bitowy, wówczas przestrzeń tekstu tekstowego będzie wynosić 4 GiB.
Pytanie 2: Jak zdefiniowany jest limit? Czy jest to całkowita dostępna pamięć RAM? Po tekście i danych obszar powyżej to sterty. Z pamięci wirtualnej, można praktycznie sterta rośnie w górę blisko max przestrzeni adresowej.
Pytanie 1: czy stos i sterta mają limit wielkości statycznej (np. 2 gigabajty każdy), czy też limit ten jest dynamiczny, zmienia się zgodnie z przydziałami pamięci podczas wykonywania programu (tj. 4 gigabajty do wykorzystania przez oba, więc jeśli program używa tylko stosu, będzie mógł mieć stos z 4 gigabajtami)? Ostatnim segmentem w przestrzeni adresowej procesu jest stos. Stos zajmuje segment końcowy przestrzeni adresowej i zaczyna się od końca i rośnie w dół .
Ponieważ stos rośnie, a stos rośnie, zasadniczo się ograniczają. Ponadto, ponieważ oba typy segmentów są zapisywalne, jeden z nich nie zawsze naruszał granicę, więc możesz mieć przepełnienie bufora lub stosu. Teraz istnieją mechanizmy zapobiegające ich wystąpieniu.
Dla każdego procesu na początku jest ustawiony limit stosu (stosu). Limit ten można zmienić w czasie wykonywania (za pomocą brk () / sbrk ()). Zasadniczo dzieje się tak, gdy proces potrzebuje więcej miejsca na sterty i zabrakło przydzielonego miejsca, biblioteka standardowa wyda wywołanie do systemu operacyjnego. System operacyjny przydzieli stronę, która zwykle będzie zarządzana przez bibliotekę użytkownika dla programu. To znaczy, jeśli program chce 1 KiB, system operacyjny da dodatkowe 4 KiB, a biblioteka da 1 KiB programowi i pozostawi 3 KiB do wykorzystania, gdy program poprosi o więcej następnym razem.
Przez większość czasu układem będzie Tekst, Dane, Sterty (rośnie), nieprzydzielone miejsce i na koniec Układanie (rośnie). Wszystkie mają tę samą przestrzeń adresową.
źródło