在32位的系統上,線性地址空間可達到4GB,這4GB一般按照3:1的比例進行分配,也就是說用戶進程享有前3GB線性地址空間,而內核獨享最後1GB線性地址空間。由於虛擬內存的引入,每個進程都可擁有3GB的虛擬內存,並且用戶進程之間的地址空間是互不可見、互不影響的,也就是說即使兩個進程對同一個地址進行操作,也不會產生問題。在前面介紹的一些分配內存的途徑中,無論是伙伴系統中分配頁的函數,還是slab分配器中分配對象的函數,它們都會盡量快速地響應內核的分配請求,將相應的內存提交給內核使用,而內核對待用戶空間顯然不能如此。用戶空間動態申請內存時往往只是獲得一塊線性地址的使用權,而並沒有將這塊線性地址區域與實際的物理內存對應上,只有當用戶空間真正操作申請的內存時,才會觸發一次缺頁異常,這時內核才會分配實際的物理內存給用戶空間。
用戶進程的虛擬地址空間包含了若干區域,這些區域的分布方式是特定於體系結構的,不過所有的方式都包含下列成分:
可執行文件的二進制代碼,也就是程序的代碼段
存儲全局變量的數據段
用於保存局部變量和實現函數調用的棧
環境變量和命令行參數
程序使用的動態庫的代碼
用於映射文件內容的區域
由此可以看到進程的虛擬內存空間會被分成不同的若干區域,每個區域都有其相關的屬性和用途,一個合法的地址總是落在某個區域當中的,這些區域也不會重疊。在linux內核中,這樣的區域被稱之為虛擬內存區域(virtual memory areas),簡稱vma。一個vma就是一塊連續的線性地址空間的抽象,它擁有自身的權限(可讀,可寫,可執行等等) ,每一個虛擬內存區域都由一個相關的struct vm_area_struct結構來描述
- struct vm_area_struct {
- struct mm_struct * vm_mm; /* 所屬的內存描述符 */
- unsigned long vm_start; /* vma的起始地址 */
- unsigned long vm_end; /* vma的結束地址 */
-
- /* 該vma的在一個進程的vma鏈表中的前驅vma和後驅vma指針,鏈表中的vma都是按地址來排序的*/
- struct vm_area_struct *vm_next, *vm_prev;
-
- pgprot_t vm_page_prot; /* vma的訪問權限 */
- unsigned long vm_flags; /* 標識集 */
-
- struct rb_node vm_rb; /* 紅黑樹中對應的節點 */
-
- /*
- * For areas with an address space and backing store,
- * linkage into the address_space->i_mmap prio tree, or
- * linkage to the list of like vmas hanging off its node, or
- * linkage of vma in the address_space->i_mmap_nonlinear list.
- */
- /* shared聯合體用於和address space關聯 */
- union {
- struct {
- struct list_head list;/* 用於鏈入非線性映射的鏈表 */
- void *parent; /* aligns with prio_tree_node parent */
- struct vm_area_struct *head;
- } vm_set;
-
- struct raw_prio_tree_node prio_tree_node;/*線性映射則鏈入i_mmap優先樹*/
- } shared;
-
- /*
- * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
- * list, after a COW of one of the file pages. A MAP_SHARED vma
- * can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack
- * or brk vma (with NULL file) can only be in an anon_vma list.
- */
- /*anno_vma_node和annon_vma用於管理源自匿名映射的共享頁*/
- struct list_head anon_vma_node; /* Serialized by anon_vma->lock */
- struct anon_vma *anon_vma; /* Serialized by page_table_lock */
-
- /* Function pointers to deal with this struct. */
- /*該vma上的各種標准操作函數指針集*/
- const struct vm_operations_struct *vm_ops;
-
- /* Information about our backing store: */
- unsigned long vm_pgoff; /* 映射文件的偏移量,以PAGE_SIZE為單位 */
- struct file * vm_file; /* 映射的文件,沒有則為NULL */
- void * vm_private_data; /* was vm_pte (shared mem) */
- unsigned long vm_truncate_count;/* truncate_count or restart_addr */
-
- #ifndef CONFIG_MMU
- struct vm_region *vm_region; /* NOMMU mapping region */
- #endif
- #ifdef CONFIG_NUMA
- struct mempolicy *vm_policy; /* NUMA policy for the VMA */
- #endif
- };