- 論壇徽章:
- 2
|
本帖最后由 fireaway7 于 2014-05-11 14:47 編輯
第2章
2.3節(jié)重要數(shù)據(jù)結(jié)構(gòu)歸納(缺注釋的成員含義,等搞明白不斷添加,請知道的朋友給個提示,也請指出不對的地方):
a. 每個物理頁面都有一個page結(jié)構(gòu):
typedef struct page {
struct list_head list; // 鏈入管理區(qū)zone_t的空閑區(qū)域free_area[x].free_list
struct address_space *mapping; // 記錄內(nèi)存頁面與磁盤文件的映射關(guān)系(mmap()),結(jié)構(gòu)定義將在2.6節(jié)出現(xiàn)
unsigned long index; // 從盤區(qū)換入時,記錄來自頁面在文件中的序號;換出盤區(qū)時,記錄動向
struct page *next_hash; // 2.6節(jié),add_page_to_hash_queue()函數(shù)中使用到
atomic_t count; // 估計是連續(xù)個數(shù),如果count=2^n,則list會鏈入free_area[n].free_list
unsigned long flags;
struct list_head lru; // 鏈入LRU(最近最少使用)隊列
unsigned long age; // 頁面“年齡”,為換出到磁盤提供依據(jù)
wait_queue_head_t wait;
struct page **pprev_hash; // 2.6節(jié),add_page_to_hash_queue()函數(shù)中使用到
struct buffer_head * buffers;
void *virtual;
struct zone_struct *zone; // 所屬管理區(qū)
} mem_map_t;
b. 頁面管理區(qū)結(jié)構(gòu):
#define MAX_ORDER 10
typedef struct zone_struct {
spinlock_t lock;
unsigned long offset; // 在mem_map[]中的起始頁面號
unsigned long free_pages; // 空閑頁面?zhèn)數(shù)
unsigned long inactive_clean_pages; // 不活躍干凈頁面?zhèn)數(shù)
unsigned long inactive_dirty_pages; // 不活躍臟頁面?zhèn)數(shù)
unsigned long pages_min, pages_low, pages_high; // 水位情況
struct list_head inactive_clean_list; // 不活躍干凈頁面隊列
free_area_t free_area[MAX_ORDER]; // 空閑區(qū)域,不同下標對應(yīng)不同的“頁面連續(xù)規(guī)!
// 管理區(qū)名字??
char *name;
unsigned long size;
struct pglist_data *zone_pgdat; // 所屬存儲結(jié)點pglist_data結(jié)構(gòu),zone_struct為zone_pgdat一個子集
unsigned long zone_start_paddr;
unsigned long zone_start_mapnr;
struct page *zone_mem_map;
} zone_t;
頁面管理區(qū)空閑區(qū)域結(jié)構(gòu):
typedef struct free_area_struct {
struct list_head free_list; // page隊列,page后有2^n-1個連續(xù)的頁面
unsigned int *map;
} free_area_t;
c. 均質(zhì)存儲結(jié)構(gòu)(UMA)、非均質(zhì)存儲結(jié)構(gòu)(NUMA)
#define ZONE_DMA 0
#define ZONE_NORMAL 1
#define ZONE_HIGHMEM 2
#define MAX_NR_ZONES 3
pglist_data存儲結(jié)點結(jié)構(gòu),每個結(jié)點對應(yīng)一個UMA(mem_map[],以及劃分為三個管理區(qū)),并且相互連在一起:
typedef struct pglist_data {
zone_t node_zones[MAX_NR_ZONES]; // 每個模塊可能有三種管理區(qū)
zonelist_t node_zonelists[NR_GFPINDEX]; // 分配策略,但MAX_NR_ZONES種區(qū)域,能排除組合NR_GFPINDEX這麼多情況嗎??
struct page *node_mem_map; // 指向mem_map[] page數(shù)組
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; // 結(jié)點編號
struct pglist_data *node_next; // 一下個pglist_data存儲結(jié)點
} pg_data_t;
d. 分配策略結(jié)構(gòu):
#define NR_GFPINDEX 0x100 // 最多可以規(guī)定256種策略,不要被3種管理區(qū)組合不出來256種情況迷惑,因為pglist_data可能有多個
typedef struct zonelist_struct {
zone_t * zones [MAX_NR_ZONES+1]; // 以NULL結(jié)束,依次從zones[0]、zone[1]..分配,最多也只會有3種管理區(qū)
int gfp_mask; // 標號,node_zonelists[]下標
} zonelist_t;
e. 虛擬空間信息結(jié)構(gòu)(需要哪些),對應(yīng)每個屬性(vm_page_prot、vm_flags)相同,地址連續(xù)(vm_start->vm_end)的頁面集合:
struct vm_area_struct {
struct mm_struct * vm_mm; // 上級結(jié)構(gòu),進程完整虛擬空間,vm_area_struct為mm_struct一個子集
// [vm_start, vm_end),什么區(qū)間?當(dāng)然是虛擬地址區(qū)間
unsigned long vm_start; // 虛擬空間區(qū)間開始地址
unsigned long vm_end; // 虛擬空間區(qū)間結(jié)束地址
// 單向鏈表(虛擬地址由高到低排列),mm_struct->mmap
struct vm_area_struct *vm_next;
pgprot_t vm_page_prot; // 頁面屬性
unsigned long vm_flags; // 頁面標志
// AVL樹結(jié)點(進程使用虛擬空間區(qū)間較多時才需要建AVL樹),mm_struct->mmap_avl
short vm_avl_height;
struct vm_area_struct * vm_avl_left;
struct vm_area_struct * vm_avl_right;
struct vm_area_struct *vm_next_share; // 與磁盤文件交換或映射時用到
struct vm_area_struct **vm_pprev_share; // 與磁盤文件交換或映射時用到
struct vm_operations_struct * vm_ops; // 一組函數(shù)指針
unsigned long vm_pgoff; // 下標偏移,擴張時,-grow
struct file * vm_file; // 交換或映射到的磁盤文件
unsigned long vm_raend;
void * vm_private_data;
};
f. 進程整個虛擬空間信息結(jié)構(gòu):
struct mm_struct {
struct vm_area_struct * mmap; // vm_area_struct結(jié)構(gòu)結(jié)點隊列
struct vm_area_struct * mmap_avl; // vm_area_struct結(jié)構(gòu)結(jié)點樹
struct vm_area_struct * mmap_cache; // 最近使用的vm_area_struct結(jié)構(gòu)結(jié)點,程序使用的地址帶有局部性,35%概率下一次仍用該結(jié)點
pgd_t * pgd; // 進程頁面目錄位置,內(nèi)核將其寫入CR3,便可切換到該進程執(zhí)行
// 一個進程只使用一個mm,但一個mm可能被多個進程使用,如vfork()、clone()
atomic_t mm_users; // mm所屬用戶進程計數(shù)
atomic_t mm_count; // mm被引用計數(shù)
int map_count; // 包含虛擬空間區(qū)間個數(shù)
// 保護mm在不同上下文中受訪問,http://www.cnblogs.com/Anker/p/3269106.html
struct semaphore mmap_sem;
spinlock_t page_table_lock;
struct list_head mmlist; /* List of all active mm's */
// 該進程代碼段、數(shù)據(jù)段、存儲堆、堆棧段等的起點和終點
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/*頁面總數(shù)*/, locked_vm;
unsigned long def_flags;
unsigned long cpu_vm_mask;
unsigned long swap_cnt; /* number of pages to swap on next pass */
unsigned long swap_address;
mm_context_t context;
};
struct vm_operations_struct {
void (*open)(struct vm_area_struct * area); // 虛存打開
void (*close)(struct vm_area_struct * area); // 虛存關(guān)閉
// 缺頁異常處理函數(shù)
struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int write_access);
};
*struct page mem_map[],分為ZONE_DMA、ZONE_NORMAL、ZONE_HIGHMEM(http://blog.csdn.net/zhengaw/article/details/4537070)三個區(qū),又由于要將各小范圍的UMA區(qū)分開,又定義了更上層的結(jié)構(gòu)pglist_data
*page、zone_struct描述供應(yīng),mm_struct、vm_area_struct描述需求,還得與“倉庫”提供的物理頁面映射,才能真正得到存儲空間,頁面目錄、中間目錄、頁面表為兩者的橋梁
*ZONE_DMA區(qū)里面的頁面供DMA專用,原因:1.頁面換出操作本身需要物理頁面,而且換出時,肯定是頁面資源緊張了,所以要“預(yù)留”;2.DMA不經(jīng)過MMU提供的地址映射(不理解);3.保證DMA得到的頁面是一定是連續(xù)的 |
|