forkexitbrkmalloc);
execvemmapmunmapPAGE_OFFSET zdefiniowana
w include/asm-i386/page.h na 0xC0000000 = 3*230, co oznacza
maksymalny rozmiar przestrzeni adresowej procesu równy 3GB.
task_struct (include/linux/sched.h)
struct task_struct {
/* ... */
struct mm_struct *mm;
/* ... */
struct mm_struct *active_mm;
/* ... */
};
mm
active_mm
mm, dla wątków jądra
jest to przestrzeń adresowa ostatnio wykonywanego procesu użytkownika.
mm_struct (include/linux/sched.h)
struct mm_struct {
struct vm_area_struct * mmap; /* list of VMAs */
struct vm_area_struct * mmap_avl; /* tree of VMAs */
struct vm_area_struct * mmap_cache; /* last find_vma result */
pgd_t * pgd;
atomic_t mm_users; /* How many users with user space? */
atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */
int map_count; /* number of VMAs */
struct rw_semaphore mmap_sem;
/* ... */
struct list_head mmlist; /* List of all active mm's. These are globally strung
* together off init_mm.mmlist, and are protected
* by mmlist_lock
*/
/* ... */
unsigned long rss, total_vm, locked_vm;
unsigned long def_flags;
/* ... */
};
mmapmmap_avlmmap_cachefind_vma;
pgdmm_usersmm_countmap_countmmap_semmmlistmm_struct w listę cykliczną;
rsstotal_vmlocked_vmdef_flagsmmap_avl jest wykorzystywane tylko dla dużej liczby
struktur VMA. Gdy map_count < AVL_MIN_MAP_COUNT (obecnie 32) to mmap_avl == NULL.
Ponieważ obszary przestrzeni adresowej opisywane przez struktury VMA nie zachodzą na siebie nie ma znaczenia
czy mmap i mmap_avl są sortowane według ich adresów początkowych, czy końcowych.
vm_area_struct (include/linux/mm.h)
struct vm_area_struct {
struct mm_struct * vm_mm; /* The address space we belong to. */
unsigned long vm_start; /* Our start address within vm_mm. */
unsigned long vm_end; /* Our end address within vm_mm. */
/* linked list of VM areas per task, sorted by address */
struct vm_area_struct *vm_next;
pgprot_t vm_page_prot; /* Access permissions of this VMA. */
unsigned long vm_flags; /* Flags, listed below. */
/* AVL tree of VM areas per task, sorted by address */
short vm_avl_height;
struct vm_area_struct * vm_avl_left;
struct vm_area_struct * vm_avl_right;
/* ... */
/* Function pointers to deal with this struct. */
struct vm_operations_struct * vm_ops;
/* Information about our backing store: */
unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
units, *not* PAGE_CACHE_SIZE */
struct file * vm_file; /* File we map to (can be NULL). */
/* ... */
};
vm_mmvm_startvm_endvm_nextvm_mm->mmap;
vm_page_protvm_flagsvm_avl_height, vm_avl_left, vm_avl_rightvm_mm->mmap_avl
o korzeniu w danej strukturze,
vm_opsvm_pgoffvm_fileNULL;
vm_area_struct obejmuje pewną całkowitą liczbę stron, a vm_start
i vm_end są zawsze wielokrotnościami rozmiaru strony.
Obszary przestrzeni adresowej mogą być rozdzielane na mniejsze przy usuwaniu fragmentu przestrzeni
adresowej lub zmianie jego praw dostępu. Sąsiednie obszary mogą też być łączone jeśli spełnione są odpowiednie
kryteria zgodności: mają one takie same prawa dostępu i nie są odwzorowaniem plików.
Niektóre flagi dla obszarów pamięci (vm_flags):
VM_READ, VM_WRITE, VM_EXECVM_MAYREAD, VM_MAYWRITE, VM_MAYEXECVM_SHAREDVM_GROWSDOWNVM_GROWSUPVM_DENYWRITEVM_LOCKEDVM_IOvm_page_prot, zapisane w tablicach stron i kontrolowane przez
jednostkę zarządzania pamięcią (MMU) nie mogą odpowiadać wszystkim możliwym kombinacjom
flag VM_READ, VM_WRITE i VM_EXEC.
W związku z tym w praktyce posiadanie prawa do zapisu oznacza także posiadanie prawa do odczytu,
zaś posiadanie prawa do odczytu - posiadanie prawa do wykonywania.
vm_operations_struct (include/linux/mm.h)
struct vm_operations_struct {
void (*open)(struct vm_area_struct * area);
void (*close)(struct vm_area_struct * area);
struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int write_access);
};
copy_mm (kernel/fork.c)copy_mm(unsigned long clone_flags, struct task_struct * tsk)
jest wołana przez do_fork w celu utworzenia struktur opisujących przestrzeń adresową
procesu potomnego na podstawie przestrzeni adresowej rodzica.
Linux wykorzystuje mechanizm kopiowania przy zapisie (COW - Copy On Write),
co oznacza, że same dane ze stron przestrzeni adresowej kopiowane są dopiero przy próbie ich
modyfikacji przez jeden z procesów.
Parametry:
clone_flagsdo_vfork;
dla copy_mm istotna jest tylko flaga CLONE_VM oznaczająca tworzenie
nowego wątku - procesu współdzielącego przestrzeń adresową z rodzicem.
tskcurrent).
CLONE_VM zwiększa current->mm->mm_users,
i przypisuje na tsk->mm oraz tsk->active_mm bieżącą przestrzeń adresową
(current->mm).
-ENOMEM;
mm_init) ustawia w nowym deskryptorze niektóre pola (w szczególności mm_users
i mm_count na 1); przydziela pamięć na nowy katalog stron, w razie niepowodzenia zwracając -ENOMEM;
dup_mmap
kopiującą struktury VMA oraz (przy wykorzystaniu copy_page_range)
tablice stron (i oznaczającą strony jako przeznaczone do kopiowania przy zapisie);
current->mm->mmlist).
__exit_mm (kernel/exit.c)__exit_mm(struct task_struct * tsk)
jest wołana przez do_exit w celu zwolnienia struktur opisujących przestrzeń adresową
procesu.
Istnieje też funkcja exit_mm, której jedynym działaniem jest wywołanie __exit_mm.
Parametr:
tsk__exit_mm
jest wywołanie mmput (z kernel/fork.c) dla tsk->mm.
mmput:
mm->mm_users
mm->mmlist
exit_mmap (z mm/mmap.c) zwalniającą struktury VMA i tablice stron;
mmdrop zwalniającą pamięć zajętą przez katalog stron i deskryptor pamięci
do_mmap_pgoff (mm/mmap.c)sys_mmap2 lub dla zachowania zgodności old_mmap wywołuje funkcjęstatic inline long do_mmap2(
unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)current->mm->mmap_sem
wołaunsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long pgoff).
Parametry:
filestruktura określająca plik do odwzorowania (jeśli nowy obszar ma odwzorowywać
plik)
addradres liniowy, od którego należy rozpocząć szukanie wolnego obszaru
len długość żądanego obszaru
protżądane prawa dostępu do obszaru: PROT_NONE dla obszaru niedostępnego
lub bitowa suma dowolnych spośród PROT_READ, PROT_WRITE, PROT_EXEC
flagsflagi dla regionu
pgoffprzesunięcie wewnątrz pliku file obszaru do odwzorowania
(w wielokrotnościach rozmiaru strony)
MAP_ANONYMOUSMAP_SHAREDMAP_PRIVATEMAP_SHARED
MAP_FIXEDaddr
MAP_NORESERVEMAP_LOCKEDMAP_GROWSDOWNMAP_ANONYMOUS) sprawdza istnienie operacji
file->f_op->mmap
addr
MAX_MAP_COUNT == 65536 (include/linux/sched.h)
get_unmapped_area, która:
MAP_FIXED sprawdza czy addr jest wielokrotnością rozmiaru strony;
jeśli tak to go zwraca, jeśli nie - zwraca -EIVAL
file ma specjalną operację file->f_op->get_unmapped_area
(system plików ext2 nie ma takiej operacji)
zwraca zwrócony przez nią adres
arch_get_unmapped_area, która
przeglądając przy użyciu funkcji find_vma przestrzeń adresową procesu
znajduje pierwszy wolny obszar addresów liniowych odpowiedniej długości za addr lub zwraca -ENOMEM
MAP_SHARED lub MAP_PRIVATE) i czy nie zachodzi
jeden z następujących błędnych przypadków:
do_munmap w celu usunięcia poprzedniego mapowania obejmującego ten sam obszar
MAP_PRIVATE (więc zmian nie można zapisać w pliku)
sprawdza czy dostępne jest wystarczająco dużo pamięci (chyba że ustawiono MAP_NORESERVE)
file->f_op->mmap
do_munmap (mm/mmap.c)sys_munmap wywołuje z zamkniętym semaforem current->mm->mmap_sem funkcjęint do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
Parametry:
mmaddrlenaddr
addr zwraca 0
addr a kończy za addr + len
i należy go podzielić na dwa, sprawdza czy nie spowoduje to przekroczenia maksymalnej liczby obszarów
unmap_fixup, która:
addr+len, skraca oryginalny obszar uaktualniając jego strukturę VMA
i wstawia obie do struktur deskryptora pamięci