歡迎您光臨本站 註冊首頁

linux學習二內存管理重要的數據結構

←手機掃碼閱讀     火星人 @ 2014-03-26 , reply:0

這裡只列舉幾個比較麻煩的數據結構

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學習二內存管理重要的數據結構已經有440次圍觀

http://coctec.com/docs/linux/show-post-186648.html