Ĺadny brzuch
Jeśli każdy program już podczas kompilacji wyznacza sobie miejsce w pamięci
(dla kodu i danych), to bardzo mozliwe jest, że 2 progsy będą miały takie same adresy.
Dlaczego więc wszystko jest OK? Słyszałem coś kiedyś, że każdy program widzi inaczej pamięć.(?)
Program nie może sobie wybrać pamięci, programista może nakazać programowi, aby odwoływał się do chcianego obszaru. System wyznacza miejsce umieszczenia programu, i ono nie jest stałe.
Zagadnienie jest bardzo ciekawe i zapoznanie się z nim całkowicie zmienia spojrzenie na pamięć, którą dysponuje nasz program :D
Otóż jest tak:
Windows dla każdego programu (lub mówiąc ściślej procesu) tworzy coś co nazywa się przestrzenią adresową! Jest to nic innego jak całkowity zakres pamięci w której funkcjonuje program. A jaki jest ten zakres? Niespodzianka od 0x00000000 do 0xFFFFFFFF! Czyli wszystkie możliwe wartości 4 bajtowego wskaźnika (mówię tu o systemie 32 bitowym, w 64 bitowym będzie tego duuuużo więcej). W sumie jest tego ponad 4 gigabajty, z tym że 2 gigabajty rezerwuje na swoje potrzeby Windows, a reszta jest do dyspozycji programu :D
Tak właśnie jest - program "myśli" że ma 2 gigabajty pamieci tylko dla siebie 8) Mało tego - on "myśli" że jest jedynym programem uruchomionym w systemie 8) Oczywiście na tym, że tak "myśli" się nie kończy - on może z tego korzystać :!
Dokładnie - program może sobie zaalokować trochę pamięci pod dowolnym adresem z tych dostępnych mu 2 gigabajtów np. chce mieć 20 bajtów pamięci zaczynających się od adresu 0x00543210 - nie ma sprawy. Program może sobie nawet przydzielić gigabajt albo i dwa pamięci na jakąś strukturę danych.
Dobra. Napewno dziwisz się jak to wszystko jest możliwe skoro tak naprawdę w systemie działa mnóstwo programów (a nie tylko jeden), a pamięci masz może 256MB (a nie 2GB).
Jest to możliwe, bo tak naprawdę program nie ma dostępu do prawdziwych adresów w pamięci. Windows daje każdemu programowi jego własną wirtualną pamięć. I np. program sobie alokuje zmienną:
int * pVar = new int;
wtedy Windows wybiera wolny adres z tej wirtualnej przestrzeni adresowej TEGO programu i zwraca mu np. adres 0x005FA21C
ale tak naprawdę Windows będzie korzystał z zupełnie innego adresu prawdziwej pamięci fizycznej np. 0x0041BF37
teraz kiedy program pisze coś pod swój adres:
* pVar = 5; // czyli pod 0x005FA21C
to Windows wie, że ten program chce dostać się do zmiennej która tak naprawdę znajduje się pod 0x0041BF37 i właśnie tą zmienną udostępnia.
Dzięki temu mechanizmowi dwa programy mogą mieć pod tym samym adresem zupełnie różne dane. Każdy program będzie widział adres np. 0x005FA21C, ale Windows oczywiście rozmieści je po swojemu pod zupełnie różnymi adresami pamięci fizycznej.
Pytanie - po co to? Odpowiedź jest prosta - pamięć tak samo jak dysk ulega defragmentacji, wyobraź sobie, że kolejno programy A, B i C alokują pamięć. Każdy z nich dostaje odpowiednią ilość pamięci:
AAAAABBBBCCCCCC
teraz program B zwalnie pamięć i wygląda ona tak:
AAAAA____CCCCCC
a teraz program D chce więcej pamięci i co się dzieje?
AAAAA(tu brakuje miejsca)CCCCCCDDDDDDDDDDDDDDDDDD
pozostaje luka, te luki się mnożą i chociaż w sumie jest dużo wolnej pamięci w postaci takich malutkich luk, to program nie może z niej korzystać, bo jest pofragmentowana!
ponieważ w Windowsie działa jednocześnie mnóstwo porgramów musi on cały czas defragmentować pamięć, a dzięki temu, że każdy program ma własną przestrzeń adresową Windows może dowolnie operować danymi w rzeczywistej pamięci fizycznej - w tym np. kopiować te dane na dysk do pliku wymiany
Dla programu też jest to ogromna zaleta, Windows udostępnia funkcję VirtualAlloc, dzięki której można rezerwować i przydzielać pamięć. Dzięki niej program może sobie zarezerwować np. 100MB pamięci:
pMemory = VirtualAlloc(NULL, 100 * 1024 * 1024, MEM_RESERVE, PAGE_READWRITE);
ale ta pamięć jest tylko zarezerwowana, twój program nie zabrał jeszcze nic z pamięci fizycznaj, ale może już te 100MB uważać za swoją własność :D Tych adresów juz nikt mu nie zabierze, a kiedy bedzie potrzebny np. 20 megabajt z tego 100MB obszaru np. na wczytanie obrazka może przydzielić tym razem już pamięć fizyczną:
pPicture20 = VirtualAlloc(pMemory + 20 * 1024 * 1024, 1024, MEM_COMMIT, PAGE_READWRITE);
a kiedy znów będzie potrzebna pamięć program znów ją przydzieli w dowolnym miejscu spośród tych 100MB, niezłe prawda? możesz sobie w zarezerwować miejsce na ogromną tablicę i traktować ją jak najzwyklejszą tablicę i łazić po niej posługując się indeksem np. Array[1223], tablica może mieć nawet gigabajt ;) chociaż zapewne tyle nie potrzebujesz, będziesz więc rezerwował tylko te komórki które będą ci potrzebne, a kiedy już przestaną byc potrzebne od razu zwolnisz je posługując się VirtualFree, w ten właśnie sposób tworzy się np. arkusze kalkulacyjne
i możesz zapomnieć o listach, które są zdecydowanie mniej wydajne hehe :twisted:
zanotowane.pl doc.pisz.pl pdf.pisz.pl zsf.htw.pl
(dla kodu i danych), to bardzo mozliwe jest, że 2 progsy będą miały takie same adresy.
Dlaczego więc wszystko jest OK? Słyszałem coś kiedyś, że każdy program widzi inaczej pamięć.(?)
Program nie może sobie wybrać pamięci, programista może nakazać programowi, aby odwoływał się do chcianego obszaru. System wyznacza miejsce umieszczenia programu, i ono nie jest stałe.
Zagadnienie jest bardzo ciekawe i zapoznanie się z nim całkowicie zmienia spojrzenie na pamięć, którą dysponuje nasz program :D
Otóż jest tak:
Windows dla każdego programu (lub mówiąc ściślej procesu) tworzy coś co nazywa się przestrzenią adresową! Jest to nic innego jak całkowity zakres pamięci w której funkcjonuje program. A jaki jest ten zakres? Niespodzianka od 0x00000000 do 0xFFFFFFFF! Czyli wszystkie możliwe wartości 4 bajtowego wskaźnika (mówię tu o systemie 32 bitowym, w 64 bitowym będzie tego duuuużo więcej). W sumie jest tego ponad 4 gigabajty, z tym że 2 gigabajty rezerwuje na swoje potrzeby Windows, a reszta jest do dyspozycji programu :D
Tak właśnie jest - program "myśli" że ma 2 gigabajty pamieci tylko dla siebie 8) Mało tego - on "myśli" że jest jedynym programem uruchomionym w systemie 8) Oczywiście na tym, że tak "myśli" się nie kończy - on może z tego korzystać :!
Dokładnie - program może sobie zaalokować trochę pamięci pod dowolnym adresem z tych dostępnych mu 2 gigabajtów np. chce mieć 20 bajtów pamięci zaczynających się od adresu 0x00543210 - nie ma sprawy. Program może sobie nawet przydzielić gigabajt albo i dwa pamięci na jakąś strukturę danych.
Dobra. Napewno dziwisz się jak to wszystko jest możliwe skoro tak naprawdę w systemie działa mnóstwo programów (a nie tylko jeden), a pamięci masz może 256MB (a nie 2GB).
Jest to możliwe, bo tak naprawdę program nie ma dostępu do prawdziwych adresów w pamięci. Windows daje każdemu programowi jego własną wirtualną pamięć. I np. program sobie alokuje zmienną:
int * pVar = new int;
wtedy Windows wybiera wolny adres z tej wirtualnej przestrzeni adresowej TEGO programu i zwraca mu np. adres 0x005FA21C
ale tak naprawdę Windows będzie korzystał z zupełnie innego adresu prawdziwej pamięci fizycznej np. 0x0041BF37
teraz kiedy program pisze coś pod swój adres:
* pVar = 5; // czyli pod 0x005FA21C
to Windows wie, że ten program chce dostać się do zmiennej która tak naprawdę znajduje się pod 0x0041BF37 i właśnie tą zmienną udostępnia.
Dzięki temu mechanizmowi dwa programy mogą mieć pod tym samym adresem zupełnie różne dane. Każdy program będzie widział adres np. 0x005FA21C, ale Windows oczywiście rozmieści je po swojemu pod zupełnie różnymi adresami pamięci fizycznej.
Pytanie - po co to? Odpowiedź jest prosta - pamięć tak samo jak dysk ulega defragmentacji, wyobraź sobie, że kolejno programy A, B i C alokują pamięć. Każdy z nich dostaje odpowiednią ilość pamięci:
AAAAABBBBCCCCCC
teraz program B zwalnie pamięć i wygląda ona tak:
AAAAA____CCCCCC
a teraz program D chce więcej pamięci i co się dzieje?
AAAAA(tu brakuje miejsca)CCCCCCDDDDDDDDDDDDDDDDDD
pozostaje luka, te luki się mnożą i chociaż w sumie jest dużo wolnej pamięci w postaci takich malutkich luk, to program nie może z niej korzystać, bo jest pofragmentowana!
ponieważ w Windowsie działa jednocześnie mnóstwo porgramów musi on cały czas defragmentować pamięć, a dzięki temu, że każdy program ma własną przestrzeń adresową Windows może dowolnie operować danymi w rzeczywistej pamięci fizycznej - w tym np. kopiować te dane na dysk do pliku wymiany
Dla programu też jest to ogromna zaleta, Windows udostępnia funkcję VirtualAlloc, dzięki której można rezerwować i przydzielać pamięć. Dzięki niej program może sobie zarezerwować np. 100MB pamięci:
pMemory = VirtualAlloc(NULL, 100 * 1024 * 1024, MEM_RESERVE, PAGE_READWRITE);
ale ta pamięć jest tylko zarezerwowana, twój program nie zabrał jeszcze nic z pamięci fizycznaj, ale może już te 100MB uważać za swoją własność :D Tych adresów juz nikt mu nie zabierze, a kiedy bedzie potrzebny np. 20 megabajt z tego 100MB obszaru np. na wczytanie obrazka może przydzielić tym razem już pamięć fizyczną:
pPicture20 = VirtualAlloc(pMemory + 20 * 1024 * 1024, 1024, MEM_COMMIT, PAGE_READWRITE);
a kiedy znów będzie potrzebna pamięć program znów ją przydzieli w dowolnym miejscu spośród tych 100MB, niezłe prawda? możesz sobie w zarezerwować miejsce na ogromną tablicę i traktować ją jak najzwyklejszą tablicę i łazić po niej posługując się indeksem np. Array[1223], tablica może mieć nawet gigabajt ;) chociaż zapewne tyle nie potrzebujesz, będziesz więc rezerwował tylko te komórki które będą ci potrzebne, a kiedy już przestaną byc potrzebne od razu zwolnisz je posługując się VirtualFree, w ten właśnie sposób tworzy się np. arkusze kalkulacyjne
i możesz zapomnieć o listach, które są zdecydowanie mniej wydajne hehe :twisted: