Witam
Pytanie może głupie, ale po zapoznaniu się z modelem przestrzeni adresowej procesu w linuxie to nie wiem.
Do tej pory w przypadku new i malloc myślałem że od razu jest alokowana pamięć wirtualna procesu na stercie oraz od razu też pamięć fizyczna (czyli dla stron w tablicy stron procesu są przypisane jakieś ramki fizyczne od razu po wywołaniu operatora new np. new int [90]). Dla mmap sądziłem że po alokacji jest tylko pamięć wirtualna alokowana i dopiero jak sie odwołujesz pod konkretny indeks to jest przerwanie page faulty i system operacyjny przypisuje jakąś ramkę fizyczną.
Ale teraz już zgłupiałem i być może żyję w błędzie i malloc/new działa tak samo - czyli ramki fizyczne z pamięci RAM są dopiero przypisywane do stron w momencie odwoływania się do poszczególnych indeksów.
Ponadto zastanawiam się co zwracają nam adresy zmiennych lokalnych, zmiennych zarezerwowanych przez new/malloc? To są adresy pamięci wirtualnej, nie fizycznej? Czy z poziomu user spejsa da radę jakoś dowiedzieć się jakie są adresy z pamięci RAM?
Działanie malloc
jest zależne od implementacji w danej bibliotece standardowej, zwykle ma pod spodem jakiś tam bufor z którego dokonuje alokacji, natomiast ten bufor jest już normalnie alokowany mmapem. Polecam napisanie prostego programu robiącego coś z alokacjami i użycie strace
do zaobserwowania co się dzieje, ja np. napisałem teraz program który robi malloc(20000000)
i w wyjściu strace mam coś takiego:
mmap(NULL, 20000768, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f27db3ea000
Po kolei:
- Nie, zawsze alokujesz tylko pamięć wirtualną, dzięki temu aplikacja nie musi się przejmować gdzie fizycznie ta pamięć się znajduje.
- To zależy, ale możesz przyjąć, że to pamięć wirtualna
- Nie, ze względu na to, że jak masz stronicowanie, to fizyczny adres zmiennej może się zmieniać pomiędzy odwołaniami.
ja np. napisałem teraz program który robi
malloc(20000000)
i w wyjściu strace mam coś takiego:mmap(NULL, 20000768, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f27db3ea000
Zmień ilość bajtow na 4 i zobacz czy dalej jest mmap
Pod Windows (i Visual C++) malloc/new wywołują za każdym razem funkcję systemową HeapAlloc. Czyli microsoftowa biblioteka standardowa C nie ma własnej implementacji sterty, tylko używa systemowej nawet dla najmniejszych alokacji. To wewnątrz HeapAlloc jest obsługa sterty, czyli przydzielanie pamięci pod poszczególne obiekty w ramach większych zaalokowanych wcześniej bloków.
W razie konieczności zaalokowania nowego bloku, HeapAlloc wywołuje VirtualAlloc, która to funkcja alokuje bloki pamięci wirtualnej (ściślej: wywołuje funkcję kernela NtAllocateVirtualMemory która to robi).
Pamięć fizyczna jest alokowana i zerowana dopiero w momencie pierwszego użycia pamięci wirtualnej: pierwsza próba odczytu lub zapisu do bloku pamięci (tzw. strony, zwykle 4 kB) zwróconego przez VirtualAlloc powoduje wyjątek page fault, w ramach którego zaalokowana zostaje pamięć fizyczna i przypisana do danego adresu przestrzeni wirtualnej, po czym program jest wznawiany.