- 论坛徽章:
- 2
|
本帖最后由 fireaway7 于 2014-05-11 14:47 编辑
第2章
2.3节重要数据结构归纳(缺注释的成员含义,等搞明白不断添加,请知道的朋友给个提示,也请指出不对的地方):
a. 每个物理页面都有一个page结构:
typedef struct page {
struct list_head list; // 链入管理区zone_t的空闲区域free_area[x].free_list
struct address_space *mapping; // 记录内存页面与磁盘文件的映射关系(mmap()),结构定义将在2.6节出现
unsigned long index; // 从盘区换入时,记录来自页面在文件中的序号;换出盘区时,记录动向
struct page *next_hash; // 2.6节,add_page_to_hash_queue()函数中使用到
atomic_t count; // 估计是连续个数,如果count=2^n,则list会链入free_area[n].free_list
unsigned long flags;
struct list_head lru; // 链入LRU(最近最少使用)队列
unsigned long age; // 页面“年龄”,为换出到磁盘提供依据
wait_queue_head_t wait;
struct page **pprev_hash; // 2.6节,add_page_to_hash_queue()函数中使用到
struct buffer_head * buffers;
void *virtual;
struct zone_struct *zone; // 所属管理区
} mem_map_t;
b. 页面管理区结构:
#define MAX_ORDER 10
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 long pages_min, pages_low, pages_high; // 水位情况
struct list_head inactive_clean_list; // 不活跃干净页面队列
free_area_t free_area[MAX_ORDER]; // 空闲区域,不同下标对应不同的“页面连续规模”
// 管理区名字??
char *name;
unsigned long size;
struct pglist_data *zone_pgdat; // 所属存储结点pglist_data结构,zone_struct为zone_pgdat一个子集
unsigned long zone_start_paddr;
unsigned long zone_start_mapnr;
struct page *zone_mem_map;
} zone_t;
页面管理区空闲区域结构:
typedef struct free_area_struct {
struct list_head free_list; // page队列,page后有2^n-1个连续的页面
unsigned int *map;
} free_area_t;
c. 均质存储结构(UMA)、非均质存储结构(NUMA)
#define ZONE_DMA 0
#define ZONE_NORMAL 1
#define ZONE_HIGHMEM 2
#define MAX_NR_ZONES 3
pglist_data存储结点结构,每个结点对应一个UMA(mem_map[],以及划分为三个管理区),并且相互连在一起:
typedef struct pglist_data {
zone_t node_zones[MAX_NR_ZONES]; // 每个模块可能有三种管理区
zonelist_t node_zonelists[NR_GFPINDEX]; // 分配策略,但MAX_NR_ZONES种区域,能排除组合NR_GFPINDEX这麽多情况吗??
struct page *node_mem_map; // 指向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 pglist_data *node_next; // 一下个pglist_data存储结点
} pg_data_t;
d. 分配策略结构:
#define NR_GFPINDEX 0x100 // 最多可以规定256种策略,不要被3种管理区组合不出来256种情况迷惑,因为pglist_data可能有多个
typedef struct zonelist_struct {
zone_t * zones [MAX_NR_ZONES+1]; // 以NULL结束,依次从zones[0]、zone[1]..分配,最多也只会有3种管理区
int gfp_mask; // 标号,node_zonelists[]下标
} zonelist_t;
e. 虚拟空间信息结构(需要哪些),对应每个属性(vm_page_prot、vm_flags)相同,地址连续(vm_start->vm_end)的页面集合:
struct vm_area_struct {
struct mm_struct * vm_mm; // 上级结构,进程完整虚拟空间,vm_area_struct为mm_struct一个子集
// [vm_start, vm_end),什么区间?当然是虚拟地址区间
unsigned long vm_start; // 虚拟空间区间开始地址
unsigned long vm_end; // 虚拟空间区间结束地址
// 单向链表(虚拟地址由高到低排列),mm_struct->mmap
struct vm_area_struct *vm_next;
pgprot_t vm_page_prot; // 页面属性
unsigned long vm_flags; // 页面标志
// AVL树结点(进程使用虚拟空间区间较多时才需要建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; // 一组函数指针
unsigned long vm_pgoff; // 下标偏移,扩张时,-grow
struct file * vm_file; // 交换或映射到的磁盘文件
unsigned long vm_raend;
void * vm_private_data;
};
f. 进程整个虚拟空间信息结构:
struct mm_struct {
struct vm_area_struct * mmap; // vm_area_struct结构结点队列
struct vm_area_struct * mmap_avl; // vm_area_struct结构结点树
struct vm_area_struct * mmap_cache; // 最近使用的vm_area_struct结构结点,程序使用的地址带有局部性,35%概率下一次仍用该结点
pgd_t * pgd; // 进程页面目录位置,内核将其写入CR3,便可切换到该进程执行
// 一个进程只使用一个mm,但一个mm可能被多个进程使用,如vfork()、clone()
atomic_t mm_users; // mm所属用户进程计数
atomic_t mm_count; // mm被引用计数
int map_count; // 包含虚拟空间区间个数
// 保护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 */
// 该进程代码段、数据段、存储堆、堆栈段等的起点和终点
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; /* 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); // 虚存关闭
// 缺页异常处理函数
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)三个区,又由于要将各小范围的UMA区分开,又定义了更上层的结构pglist_data
*page、zone_struct描述供应,mm_struct、vm_area_struct描述需求,还得与“仓库”提供的物理页面映射,才能真正得到存储空间,页面目录、中间目录、页面表为两者的桥梁
*ZONE_DMA区里面的页面供DMA专用,原因:1.页面换出操作本身需要物理页面,而且换出时,肯定是页面资源紧张了,所以要“预留”;2.DMA不经过MMU提供的地址映射(不理解);3.保证DMA得到的页面是一定是连续的 |
|