Przewodnik po plikach modułu "Pamięć"
Do tematu: Struktury danych
1. Wymiana
pamięć-dysk, urządzenia wymiany
/linux/mm/swap.c - W pliku tym inicjalizowane
są tymczasowo zmienne mówiące o tym, przy jakiej ilości stron należy
zmieniać priorytety wymiany. Inicjalizacja ta nie jest ważna, bo przed
pierwszym użyciem są ponownie inicjalizowane w funkcji free_area_init
w pliku page_alloc.c. Inicjalizowane
są również parametry dotyczące wymiany. Są to: maksymalny wiek ramki
(tzn. najmłodszy), o ile odmładzamy stronę przy odwołaniu do niej, o ile
postarzamy stronę przy odwołaniu do niej.
/include/linux/swap.h - Plik ten zawiera
definicję powyższych struktur i funkcji:
- struct swap_info_struct
- Struktura informacji o urządzeniu wymiany.
- unsigned long in_swap_cache(unsigned long index) - Funkcja ta
zwraca klucz identyfikujący stronę na urządzeniu wymiany lub 0, gdy strony
z ramki o numerze index nie ma na urządzeniu wymiany.
- long find_in_swap_cache(unsigned long index) - Funkcja ta zwraca
klucz identyfikujący stronę na urządzeniu wymiany lub 0, gdy strony z
ramki o numerze index nie ma na urządzeniu wymiany i jednocześnie w miejsce
starego klucza wstawia 0 (tak jakby strony nie było na urządzeniu wymiany).
- int delete_from_swap_cache(unsigned long index) - Funkcja usuwająca
stronę ze swap cache
i jednocześnie usuwająca ją z urządzenia wymiany.
/linux/mm/swap_state.c - Plik
ten zawiera następujące funkcje:
- void show_swap_cache_info(void) - Funkcja ta wypisuje informacje
statystyczne o wykorzystaniu swap_cache.
- int add_to_swap_cache(unsigned long index, unsigned long entry)
- Funkcja dodaje stonę w ramce o indeksie index umieszczoną na urządzeniu
wymiany w miejscu oznaczonym kluczem entry do "do swap cache".
- unsigned long init_swap_cache(unsigned long mem_start, unsigned
long mem_end) - W funkcji tej inicjalizujemy tablicę swap_cache,
tak aby miała wielkość równą liczbie ramek w systemie, zerujemy tą tablicę;
tablica swap_cache będzie zaczynać się od słowa następnego wolnego po mem_start;
funkcja zwraca pierwszy wolny adres za swap_cache .
- void swap_duplicate(unsigned long entry) - W funkcji tej zwiększamy
ilość odwołań do strony o kluczu entry na urządzeniu wymiany.
/linux/mm/swapfile.c - Plik ten
zawiera następujące funkcje:
- int scan_swap_map(struct swap_info_struct *si) - Funkcja ta
zwraca offset wolnego miejsca na urządzeniu wymiany *si lub 0, gdy z jakiś
powodów nie można przydzielić wolnego miejsca.
- unsigned long get_swap_page(void) - Funkcja ta zwraca offset
wolnego miejsca na jednym z urządzeń wymiany lub 0, gdy z pewnych powodów
nie można przydzielić wolnego miejsca.
- void swap_free(unsigned long entry) - Funkcja zwalnia miejsce
o kluczu entry na odpowiednim (informacja o którym jest zawarta w entry)
urządzeniu wymiany.
- int unuse_pte(struct vm_area_struct * vma, unsigned long address,
pte_t *dir, unsigned int type, unsigned long page) - Funkcja sprawdza,
czy strona *dir jest wymieciona na urządzenie wymiany identyfikowane przez
type i jeśli tak, to zapisuje tę stronę do ramki page i zwraca 1. Wpp.
zwraca 0.
- int unuse_pmd(struct vm_area_struct * vma, pmd_t *dir, unsigned
long address, unsigned long size, unsigned long offset, unsigned int type,
unsigned long page) -Funkcja przegląda katalog stron *dir znajdujący
się w bloku pamięci vma, z katalogu tablic stron drugiego poziomu *pgdir,
od adresu address do address + size , o przesunięciu w katalogu tablic
stron drugiego poziomu offset i jeśli znajdzie stronę, która jest wymieciona
na urządzenie wymiany identyfikowane przez type, to wczytuje ją do ramki
page i zwraca 1, wpp zwraca 0.
- int unuse_pgd(struct vm_area_struct * vma, pgd_t *dir, unsigned
long address, unsigned long size, unsigned int type, unsigned long page)
- Funkcja przegląda katalog tablic stron drugiego poziomu dir od adresu
address do address + size i jeśli znajdzie stronę, która jest wymieciona
na urządzenie wymiany identyfikowane przez type, to wczytuje ją do ramki
page i zwraca 1, wpp zwraca 0 .
- int unuse_vma(struct vm_area_struct * vma, pgd_t *pgdir, unsigned
long start, unsigned long end, unsigned int type, unsigned long page)
- Funkcja przegląda katalog tablic stron pierwszego poziomu pgdir od adresu
start do end i jeśli znajdzie stronę, która jest wymieciona na urządzenie
wymiany identyfikowane przez type, to wczytuje ją do ramki page i zwraca
1, wpp zwraca 0.
- int unuse_process(struct mm_struct * mm, unsigned int type, unsigned
long page) - Funkcja przegląda strony procesu, którego struktura informacji
o pamięci jest *mm i jeśli znajdzie stronę, która jest wymieciona na urządzenie
wymiany identyfikowane przez type, to wczytuje ją do ramki page i zwraca
1, wpp zwraca 0.
- int try_to_unuse(unsigned int type) - Funkcja probująca zwolnić
dane z urządzenia wymiany identyfikowanego przez type. Funkcja przegląda
tablice procesów i po kolei dla każdego procesu zwalnia jego strony, które
są na urządzeniu wymiany przepisując je do ramek pobieranych z systemu.
Zwraca 0, gdy działanie kończy się bez błędów, lub zwraca -ENOMEM w przypadku
błędu.
- int sys_swapoff(const char * specialfile) -Funkcja odłączająca
urządzenie wymiany, które operuje na pliku specjalnym *specialfile .
- int sys_swapon(const char * specialfile, int swap_flags) - Funkcja
dołączająca urządzenie wymiany *specialfile do systemu.
- void si_swapinfo(struct sysinfo *val) - Funkcja wypełniająca
strukturę *val informacjami statystycznymi o działaniu urządzeń wymiany.
/linux/mm/vmscan.c - Plik zawiera
definicje następujących funkcji:
- int try_to_swap_out(struct task_struct * tsk, struct vm_area_struct*
vma, unsigned long address, pte_t * page_table, int dma, int wait, int
can_do_io) - Funkcja próbująca zwolnić jedną stronę z pamięci nie
bedącej pamięcią dzieloną używaną przez proces *tsk, mieszczącą się
w obszarze wirtualnej pamięci vma w tablicy stron w miejscu page_table.
- int swap_out_pmd(struct task_struct * tsk, struct vm_area_struct
* vma, pmd_t *dir, unsigned long address, unsigned long end, int dma, int
wait, int can_do_io) - Funkcja próbująca zwolnić jedną stronę z pamięci
nie będącej pamięcią dzieloną ani pamięcią używaną na mapowanie plików
używaną przez proces *tsk, mieszczącą się w obszarze wirtualnej pamięci
vma w katalogu tablic stron pgd .
- int swap_out_pgd(struct task_struct * tsk, struct vm_area_struct
* vma, pgd_t *dir, unsigned long address, unsigned long end, int dma, int
wait, int can_do_io) - Funkcja próbująca zwolnić jedną stronę z pamięci
nie będącej pamięcią dzieloną ani pamięcią używaną na mapowanie plików
używaną przez proces *tsk, mieszczącą się w obszarze wirtualnej pamieci
vma w katalogu tablic stron dir.
- int swap_out_vma(struct task_struct * tsk, struct vm_area_struct
* vma, pgd_t *pgdir, unsigned long start, int dma, int wait, int can_do_io)
- Funkcja próbujca zwolnić jedną stronę z pamięci nie będącej pamięcią
dzieloną ani pamięcią używaną na mapowanie plików używaną przez proces
*tsk, mieszczącą się w obszarze wirtualnej pamięci vma.
- int swap_out_process(struct task_struct * p, int dma, int wait,
int can_do_io) - Funkcja próbująca zwolnić jedną stronę z pamięci
nie będącej pamięcią dzieloną używaną przez proces p.
- int swap_out(unsigned int priority, int dma, int wait, int can_do_io)
- Funkcja próbująca zwolnić jedną stronę z pamięci nie będącej pamięcią
dzieloną.
- int try_to_free_page(int priority, int dma, int wait) - Funkcja
próbująca zwolnić jedną stronę.
- int kswapd(void *unused) - Funkcja będąca demonem wymiany
- void swap_tick(void) - Funkcja wołana przy każdym tyknięciu
zegara demona wymiany - decyduje o tym, czy zbudzić demona wymiany, czy
też nie.
- void init_swap_timer(void) - Funkcja inicjalizująca zegar budzący
demona wymiany.
2. Stronicowanie
plików
/linux/mm/filemap.c - Plik ten
zawiera następujące funkcje:
- int generic_file_mmap(struct inode * inode, struct file * file,
struct vm_area_struct * vma) - Powyższa funkcja wpisuje inode do vma->vm_inode
i zwiększa licznik dowiązań i-węzła. Inicjuje strukturę funkcji obsługi
stronicowania na "file_shared_mmap" dla obszarów dzielonych lub
na "file_private_mmap" dla prywatnych.
/linux/mm/mmap.c - Plik ten zawiera następujące
funkcje:
- unsigned long do_mmap(struct file * file, unsigned long addr, unsigned
long len, unsigned long prot, unsigned long flags, unsigned long off)
- Funkcja ta przydziela pamięć na nową strukturę typu vm_area_struct, następnie
ją inicjalizuje. Zwalnia poprzednie obszary o zachodzących adresach. Wywołuje
funkcję charakterystyczną dla danego systemu plików i kończy inicjalizowanie
struktury typu vm_area_struct.
Zwracany jest przydzielony adres lub odpowiedni kod błędu.
- int do_munmap(unsigned long addr, size_t len) - Funkcja ta wyjmuje
odpowiednią strukturę vm_area_struct
ze zbioru, następnie wywołuje funkcję specyficzną dla danej struktury i
zwalnia strony oraz pamięć jądra używaną przez vm_area_struct.
3. Pamięć
dzielona
/linux/ipc/shm.c - Plik ten zawiera dwie funkcje:
- pte_t shm_swap_in(struct vm_area_struct * shmd, unsigned long offset,
unsigned long code) -
- int shm_swap (int prio, int dma) -
/include/ipc.h -
/include/shm.h - Plik ten zawiera następujące struktury:
- struct shm_info
- Struktura ta wykorzystywana jest przy przekazywaniu informacji o pamięci
dzielonej podczas operacji shmctl.
- struct shminfo
- Struktura ta wykorzystywana jest przy przekazywaniu informacji o pamięci
dzielonej podczas operacji shmctl.
4. Segmentacja
5. Algorytm fork
/linux/kernel/fork.c -Plik ten zawiera
następujące funkcje:
- int do_fork(unsigned long clone_flags, unsigned long usp, struct
pt_regs *regs) - Główna funkcja tworząca nowy proces wywoływana przez
sys_fork.
- int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
- Funkcja tworząca struktury nowego procesu dotyczące pamieci wirtualnej.
- int dup_mmap(struct mm_struct * mm) - Funkcja tworząca listę
i drzewo AVL struktur vm_area_struct,
dokładnie: kopiująca struktury opisujące pamieć wirtualną procesu.
6. Zarządzanie
ramkami i stronicowanie
/linux/mm/memory.c - Plik zawiera
funkcje wykonujące operacje na ramkach.Najważniejsze z nich to:
- void copy_page(unsigned long from, unsigned long to) - Funkcja
kopiująca ramkę ze szczególnym potraktowaniem przypadku kopiowania "ramki
zerowej".
- void free_one_pmd(pmd_t * dir) - Funkcja ta po sprawdzeniu poprawności
ramki zwalnia ją wywołując funkcję "pte_free" z pliku pgtable.h
, która z kolei nie robi nic innego, jak tylko wywołuje funkcję "free_page"
z pliku page_alloc.c - funkcję rzeczywiście
zwalniającą ramki.
- void free_one_pgd(pgd_t * dir) - Funkcja ta działa analogicznie
jak poprzednia, z tym, że zwalnia strukturę o poziom wyższą.
- void clear_page_tables(struct task_struct * tsk) - Funkcja ta
zwalnia wszystkie ramki (z poziomu użytkownika) danego procesu.
- void free_page_tables(struct mm_struct * mm) - Funkcja ta zachowuje
się analogicznie jak poprzednia, z tym, że dodatkowo zmienia elementy katalogu
ramek procesu na element katalogu ramek jądra i zwalnia dotychczas zajmowany.
Używana przy kończeniu procesu.
- int new_page_tables(struct task_struct * tsk) - Funkcja ta tworzy
nowy katalog stron dla procesu.
- void copy_one_pte(pte_t * old_pte, pte_t * new_pte, int cow)
- Funkcja ta kopiuje pojedynczą ramkę. Jeśli funkcja zostanie wywołana
z argumentem cow różnym od zera to ramka, do której kopiujemy zostanie
oznaczona jako tylko-do-odczytu i ewentualna próba pisania do niej spowoduje
wywołanie błędu ochrony strony.
- int copy_pte_range(pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long
address, unsigned long size, int cow) - Funkcja ta kopiuje ramki z
podanego przedziału. Adres ramki nie jest podany jawnie jak w poprzedniej
funkcji. Podany jest adres tablicy ramek, do której ramka należy (*src_pmd)
i przesunięcie (offset) początkowej ramki względem tego adresu. Wielkość
fragmentu do skopiowania określona jest argumentem size.
- int copy_pmd_range(pgd_t *dst_pgd, pgd_t *src_pgd, unsigned long
address, unsigned long size, int cow) - Funkcja ta działa analogicznie
jak poprzednia, z tym, że kopiowane są nie strony, a tablice stron (pmd).
- int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
struct vm_area_struct *vma) - Funkcja analogiczna do copy_pte_range
z tym, że tamta kopiowała spójny fragment pamięci fizycznej, a ta kopiuje
spójny fragment pamięci wirtualnej.
- void free_pte(pte_t page) - Funkcja zwalnia ramkę (wywołując
free_page), jeżeli ramka istnieje i ma utawiony bit _PAGE_PRESENT, następnie
zmniejszana jest liczba ramek procesu, do którego ta ramka należała , jeśli
proces miał jeszcze jakieś ramki.Ramka zostaje usunięta z pamięci (funkcja
swap_free ) w każdym przypadku.
- void zap_pte_range(pmd_t * pmd, unsigned long address, unsigned
long size) - Usuwa wszystkie ramki z podanego przedziału. Przedział
określony jak w funkcji copy_pte_range.
- void zap_pmd_range(pgd_t * dir, unsigned long address, unsigned
long size) - Funkcja zupełnie analogiczna do copy_pmd_range.
- int zap_page_range(struct mm_struct *mm, unsigned long address,
unsigned long size) - Funkcja usuwa z pamięci strony z podanego zakresu.
/include/asm-i386/page.h - W pliku
tym zdefiniowany jest rozmiar ramki (strony).Zawiera on stałe, makra odwołujące
się do elementów tablic.
/include/asm-i386/pgtable.h - Plik
ten zawiera funkcje obsługujące pamięć podręczną, alokujące struktury
i kontrolujące ich poprawność.
/linux/mm/page_alloc.c - Plik
ten zawiera funkcje i struktury służące do przechowywania wolnych ramek:
- struct free_area_struct
free_area[NR_MEM_LISTS] - Tablica zawierająca początki cyklicznych
list spójnych wolnych obszarów pamięci. Lista o początku free_area[i]
zawiera spójne obszary wielkości PAGE_SIZE*(2i).
- void free_pages_ok(unsigned long map_nr, unsigned long order)
,
- void __free_page(struct page *page) ,
- void free_pages(unsigned long addr, unsigned long order) - Trzy
powyższe funkcje służą do zwalniania ramek pamięci. Funkcja __free_page(struct
page *page) - zwalnia jedną ramkę , natomiast funkcja free_pages (unsigned
long addr, unsigned long order) - zwalnia spójny obszar pamięci złożony
z 2(order) ramek o adresie początkowym addr; obie wywołują
funkcję free_pages_ok realizującą strategię "buddy".
- unsigned long __get_free_pages(int priority, unsigned long order,
int dma) - Funkcja służąca do pobierania ramek. Realizuje ona strategię
"buddy".
- void show_free_areas(void) - Funkcja obliczająca ilość dostępnej
wolnej pamięci oraz jej procentową fragmentację.
- unsigned long free_area_init(unsigned long start_mem, unsigned long
end_mem) - Funkcja uruchamiana podczas startu systemu. Inicjuje struktury
służące do zarządzania ramkami.
/include/linux/mm.h - Plik zawierający
definicje struktur:
- struct vm_area_struct
- Struktura służąca do obsługi wirtualnej przestrzeni adresowej.Pamięć
wirtualna procesu reprezentowana jest przez listę i drzewo AVL struktur
vm_area_struct opisujących przyznane procesowi spójne obszary wirtualnej
przestrzeni adresowej.
- struct vm_operations_struct
- Struktura zawierająca funkcje obsługujące strukturę vm_area_struct.
- struct page
- Struktura zawierająca informacje o poszczególnych ramkach.
/include/linux/swapctl.h - Plik
ten zawiera funkcje służące do postarzania i odmładzania ramek.Są to
następujące funkcje:
- void touch_page(struct page *page) - Funkcja odmładzająca ramki.
- void age_page(struct page *page) - Funkcja postarzająca ramki.
- void age_of(unsigned long addr) - Funkcja zwracająca wiek ramki
o adresie: addr.
- void set_page_new(unsigned long addr) -Funkcja inicjująca wiek
ramki jako PAGE_INITIAL_AGE.
7. Błędy
braku i ochrony strony
/linux/arch/i386/mm/fault.c - Plik
ten zawiera funkcję:
- void do_page_fault(struct pt_regs *regs, unsigned long error_code)
- Funkcja ta niemal bezpośrednio obsługuje przerwanie błędu strony.Argumenty
to wskaźnik do kopii zawartości rejestrów w momencie powstania wyjątku
oraz kod błędu.Pierwsze trzy bity kodu błędu informują czy nastąpił błąd
braku strony, czy ochrony strony, to determinuje czy wołana jest funkcja
obsługi ochrony, czy braku strony.
/linux/mm/memory.c - Plik ten zawiera
następujące funkcje:
- void do_wp_page(struct task_struct * tsk, struct vm_area_struct
* vma, unsigned long address, int write_access) - Funkcja ta jest wywoływana
przez niskopoziomowy handler "do_page_fault" w przypadku, gdy
wystąpiło odwołanie do strony, do której proces nie ma praw zapisu. Ma
to miejsce w przypadku, gdy strona pamięci jest dzielona lub została niedawno
wykonana operacja fork() i nie zostały fizycznie skopiowane strony procesu
macierzystego do potomnego.
- void do_swap_page(struct task_struct * tsk, struct vm_area_struct
* vma, unsigned long address, pte_t * page_table, pte_t entry, int write_access)
-Funkcja wczytuje strony z dysku.
- void do_no_page(struct task_struct * tsk, struct vm_area_struct
* vma, unsigned long address, int write_access) - Funkcja ta jest wywoływana
przez niskopoziomowy handler "do_page_fault" w przypadku, gdy
wystapiło odwołanie do strony, której jeszcze nie ma w pamięci. Jest to
wielka rozdzielnia, która sprawdza stan ramki w pamieci i w zależności
od tego wywołuje odpowiednie akcje: 1. jeśli strona znajduje się w pamięci
(przydzielona innemu procesowi) następuje uaktualnienie deskryptora strony,
jeśli strona jest dostępna na urządzeniu wymiany następuje wczytanie strony
z dysku, jeśli strona jest niezainicjalizowana następuje pobranie nowej
strony z puli systemu i uaktualnienie deskryptorów).
8. Pamięć dla jądra
/linux/mm/kmalloc.c - Plik ten
zawiera implementację mechanizmu przydziału pamięci dla jądra. Zawiera
on dwie funkcje oraz definicję tablicy, na której te funkcje operują:
- struct size_descriptor
sizes[]- Tablica zawierająca początki list wolnych obszarów pamięci
ramek, które moduł odpowiedzialny za przydział pamięci dla jądra otrzymał
od modułu zarządzającego ramkami. Lista o początku sizes[i] zawiera
obszary pamięci rozmiaru 2(i+5).
- struct block_header
- Struktura opisująca pojedynczy blok przydzielany jądru.
- struct page_descriptor
- Struktura opisująca pojedynczy element listy, której dowiązanie do
początku przechowuje element sizes[i].
- void* kmalloc(int size, int priority) - Funkcja przydzielająca
jądru obszar pamięci rozmiaru size.Przegląda tablicę SIZES w poszukiwaniu
odpowiedniego obszaru lub żąda przydziału ramki pamięci, z której wycina
odpowiedni obszar, a resztę zapamiętuje w tablicy SIZES.
- int kfree(void * __ptr) - Funkcja zwalniająca obszar pamięci
wskazywany przez argument __ptr.
Przygotował na podstawie skomentowanych źródeł: Jacek Korkuć