fireaway7 发表于 2014-05-06 16:30

《LINUX内核源代码情景分析》第2章笔记

本帖最后由 fireaway7 于 2014-05-11 14:47 编辑

第2章
2.3节重要数据结构归纳(缺注释的成员含义,等搞明白不断添加,请知道的朋友给个提示,也请指出不对的地方):
a. 每个物理页面都有一个page结构:
   typedef struct page {
       struct list_head list;                     // 链入管理区zone_t的空闲区域free_area.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.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;   // 空闲区域,不同下标对应不同的“页面连续规模”
      
       // 管理区名字??
       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;       // 每个模块可能有三种管理区
       zonelist_t node_zonelists;// 分配策略,但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 ; // 以NULL结束,依次从zones、zone..分配,最多也只会有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得到的页面是一定是连续的
页: [1]
查看完整版本: 《LINUX内核源代码情景分析》第2章笔记