struct list_head *next, *prev;
} //linux通用的双向链队列,下面多处用到,这里列出源代码
struct list_head free_list; //linux 中通用的双向链队列
unsigned int * map;
} free_area_t;
unsigned long inactive_clean_pages;
unsigned long inactive_dirty_pages;
unsigned pages_min, pages_low, pages_high;
struct list_head inactive_clean_list; //用于页面交换的队列,基于linux页面交换的机制。这里存贮的是不活动“干净”页面
free_area_t free_area[MAX_ORDER];
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 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;
zone_t * zones [MAX_NR_ZONES+1]; //指针数组,指向每个具体的页面管理区
int gfp_mask;
} zonelist_t; //用于描述内存分配策略的数据结构,比如内存中最小适应法则的分配策略,我们就可以将区放入zones数组中,按照区内空闲页面从小到大的原则,但我们要实现这个法则,我们只需要从头到尾便利这个数组,那么找到第一个大于你要求的页面个数的区就是最小适应区
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; //这些属性都是用于记录页面与文件关系,具体情况具体分析
}
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用于虚存空间打开,关闭和建立印射
struct vm_area_struct * mmap; //建立虚存空间的单链队列
struct vm_area_struct * mmap_avl; //建立虚存空间的AVL树
struct vm_area_struct * mmap_cache; //最近一次使用的虚存空间,由于内存访问总是带有局部性,命中率有35%
pgd_t * pgd; //指向进程页面目录,在载入进程时候这个值会被载入到cr3寄存器中
atomic_t mm_users;
atomic_t mm_count;
//这2个变量比较令人费解,mm_users记录是虚存空间的使用者,而mm_count记录的是mm_struct使用的计数。首先虚存空间是可以多个进程使用的,比如如果父进程调用vfork创建子线程,此时2者使用的是同一个虚存空间。线程是没有自己的虚存空间。其次一个mm_struct对应一个虚存,有几个使用者那么就有几个进程通过指针共享了这个mm_struct,按理说这2个计数应该是一个,不应该分成2个。大部分可能性2者是相同的。但又特殊情况,比如内核线程是没有虚存空间,他是需要暂借调用者的虚存空间,只是虚存空间使用者和mm_struct使用计数就不统一
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;
}