红联Linux门户
Linux帮助

linux学习二内存管理重要的数据结构

发布时间:2008-05-15 15:45:20来源:红联作者:Dopsdck
这里只列举几个比较麻烦的数据结构

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是整个用户空间的抽象。
文章评论

共有 1 条评论

  1. lijiang 于 2012-01-09 22:33:28发表:

    深入一步的理解,还是得静学数据结构原理