這裡只列舉幾個比較麻煩的數據結構 struct list_head { struct list_head *next, *prev; } //linux通用的雙向鏈隊列,下面多處用到,這裡列出源代碼 linux對內存再用頁式管理,對於頁,就有個數據結構page加以描述。在內核中有個全局量mem-map指向的是一個page的數組,整個數組描述了整個物理內存,大家注意32位地址線,內存大小是2的32次方。由於頁大小是4k也就是2的12次方。每4K的頁就有一個page。那麼2的32次方共有2的20次方個頁,則mem-map指向的數組大小就是2的20次方。其中明顯對於頁的物理地址,一定是4K的倍數,因為它大小是4K,那麼這個數組就有個對應,數組下標後面12個0(2進位)對應了頁面的物理地址,他們在數值上是相等的。那麼我們在page數據結構中就沒有必要存貯它的物理地址。page數據結構定義位置include/linux/mm.h struct page{ struct list_head list; //通過使用它進入下面的數據結構free_area_struct結構中的雙向鏈隊列 struct address_space * mapping; unsigned long index; struct page *next_hash; //自身的指針,這樣就可以鏈接成一個鏈表 atomic t count; unsigned long flags; struct list_head lru; unsigned long age; wait_queue_head_t wait; struct page ** pprev_hash; struct buffer_head * buffers; void * virtual struct zone_struct * zone; } (對於每個項的說明,我會慢慢補上) 對內存,僅僅用page數據結構來描述肯定遠遠不夠,對於整個內存,我們在此之上分了管理區的概念,每個管理區管理數個頁面。我們先不關心這個有什麼用,我們先知道這個是怎麼回事。這個數據結構是 zone_struct定義位置是在include/linux/mmzone.h typedef struct free_area_struct { struct list_head free_list; //linux 中通用的雙向鏈隊列 unsigned int * map; } free_area_t; typedef struct zone_struct{ spinlock_t lock; unsigned long offset; //表示該管理區在mem-map數組中,起始的頁號 unsigned long free pages; unsigned long inactive_clean_pages; unsigned long inactive_dirty_pages; unsigned pages_min, pages_low, pages_high; struct list_head inactive_clean_list; free_area_t free_area[MAX_ORDER]; //一組「空閑區間」隊列,free_area_t定義在上面 char * name; unsigned long size; struct pglist_data * zone_pgdat; //用於指向它所屬的存貯節點,及下面的數據結構 unsigned long zone_start_paddr; unsigned long zone_start_mapnr; struct page * zone_mem_map; } zone_t; 我們知道內存的地位並不是「平等的」,例如主內存和圖形卡上的靜態內存ram就不是「平等地位」,因此我們頁面管理機製做了修正,管理區不是內存管理中最高層的概念,前述的page數組mem-map也不是全局,而是從屬於具體的節點,在zone_struct 上面有了一層代表存貯節點的數據結構pglist_data,定義於include/linux/mmzone.h 中 typedef struct pglist_data { zone_t node_zones[MAX_NR_ZONES]; //該節點最多的3個頁面管理區,MAX_NR_ZONE值是3,在linux中分為3個管理區,也可能是2個ZONE_DMA,ZONE_NORMAL,ZONE_HIGHMEM zonelist_t node_zonelist[NR_GFPINDEX]; //具體說明見下面的數據結構 struct page * node_mem_map; //用於指向屬於該存儲節點的page數組 unsigned long * valid_addr_bitmap; struct bootmem_data * bdata; unsigned long node_start_paddr; unsigned long node_start_mapnr; unsigned long node_size; int node_id; struct pglistdata * node_next; //用於形成一個單鏈隊列 } pg_data_t; typedef struct zonelist_struct { zone_t * zones [MAX_NR_ZONES+1]; //指針數組,指向每個具體的頁面管理區 int gfp_mask; } zonelist_t; 這些都是用於物理空間管理的,虛擬空間管理由下面的數據結構描述(我剛開始把虛擬空間弄成了虛擬內存,越看越糊塗,虛擬空間指的是,在linux中,4G內存被分為2塊,搞地址1G內存叫系統空間,所有進程共享,下面的3G便是虛擬空間,每個進程都佔有虛擬空間3G,在進程自己看來是這樣的,但實際上,他遠遠沒這麼多內存用),vm_area_struct數據結構,定義於 include/linux/mm.h struct vm_area_struct { struct mm_struct * vm_mm; //下面說明 unsigned long vm_start; unsigned long vm_end; //start和end決定了虛存空間,個人理解應該是mem-map表的下標,其中 start包含,end不包含,同時區間劃分不單單是地址連續,還要保證許可權的統一 struct vm_area_struct * vm_next; //將屬於同一進程的虛存區間按照虛存地址高低鏈接起來 pgrot t_vm_page_prot; unsigned long vm_flags; //存貯該區間的許可權 short vm_avl_height; struct vm_area_struct * vm_avl_left; struct vm_area_struct * vm_avl_rigth; //用於生成 avl樹,提高搜索效率 struct vm_area_struct * vm_next_share; struct vm_area_struct ** vm_pprev_share; struct vm_operations_struct * vm_ops; //下面說明 unsigned long vm_pgoff; struct file * vm_file; unsigned long vm_raend; void * vm_private_data; //這些屬性都是用於記錄頁面與文件關係,具體情況具體分析 } 定義於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); } //open, close,nopage用於虛存空間打開,關閉和建立印射 定義於include/linux/sched.h struct mm_struct{ struct vm_area_struct * mmap; //建立虛存空間的單鏈隊列 struct vm_area_struct * mmap_avl; //建立虛存空間的AVL樹 struct vm_area_struct * mmap_cache; //最近一次使用的虛存空間,由於內存訪問總是帶有局部性,命中率有35% pgd_t * pgd; //指向進程頁面目錄 atomic_t mm_users; atomic_t mm_count; int map_count; struct semaphore mmap_sem; //用於進程的間的互斥訪問 spinlock_t page_table_lock; struct list_head mmlist; unsigned long start_code, end_code, start_data, end_data unsigned long start_brk, brk, start_stack; unsigned long arg_start, arg_end, env_start, env_end; unsigned long rss, total_vm, locked_vm; unsigned long def_flags; unsigned long cpu_vm_mask; unsigned long swap_cnt; unsigned long swap_address; mm_context_t context; } 在操作系統中,有個進程式控制制塊(PCB)的概念,具體到linux裡面對應的數據結構是task_struct,它內部就有個mm_struct指針,mm_struct是整個用戶空間的抽象。
[火星人
]
linux學習二內存管理重要的數據結構 已經有645 次圍觀
本文地址: http://coctec.com/docs/linux/show-post-186648.html