linux内存管理之数据结构 您所在的位置:网站首页 expdp表结构 linux内存管理之数据结构

linux内存管理之数据结构

2023-03-20 07:23| 来源: 网络整理| 查看: 265

【推荐阅读】

一文看懂linux内核详解

linux内核内存管理-写时复制

深入了解使用linux查看磁盘io使用情况

一、物理空间管理1.1 页表项

[include /asm-i386/page.h: 39]

39 #if CONFIG_X86_PAE 40 typedef struct { unsigned long pte_low, pte_high; } pte_t; 41 typedef struct { unsigned long long pmd; } pmd_t; 42 typedef struct { unsigned long long pgd; } pgd_t; 43 #define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high

内核资料直通车:Linux内核源码技术学习路线+视频教程代码资料

学习直通车:Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈

2.2 当下的分区情况

但随着NUMA*(非均质储存结构)的引入,分区发生了变化。NUMA指的是,在当下多处理器结构中,每一个CPU都具有本地储存,称之为内存节点,而多个CPU之间又有共享的内存。

CPU訪问本地储存的速度要快于訪问共享储存的速度。也就是说,在一个连续的物理地址上,储存器的訪问速度不一致,这就叫做NUMA。在NUMA结构中。假设要分配几个连续的物理页,一般要求分配在质地同样的储存器内。为此,内核定义了一个pglist_data结构,每一个pglist_data代表这一个内存节点。每一个内存节点都能够拥有ZONE_DMA和ZONE_NORMAL(依据配置还可能有ZONE_HIGHMEN)两个区,也就意味这每一个内存节点都有一个page数组和一个zone_t数组,用于管理该节点上两个区的全部page。 总的来说。原来将整个物理空间分为三个区来管理的模式,如今变成了将整个物理空间分为若干内存节点。各个内存节点将节点上的全部物理空间进行分区管理*。pglist_data定义例如以下:[include/linux/mmzone.h : 79]

79 typedef struct pglist_data { 80 zone_t node_zones[MAX_NR_ZONES]; 81 zonelist_t node_zonelists[NR_GFPINDEX]; 82 struct page *node_mem_map; 83 unsigned long *valid_addr_bitmap; 84 struct bootmem_data *bdata; 85 unsigned long node_start_paddr; 86 unsigned long node_start_mapnr; 87 unsigned long node_size; 88 int node_id; 89 struct pglist_data *node_next; 90 } pg_data_t;

80: node_zones为该内存节点上的三个分区管理结构。81: node_zonelists为一个指向zone_t指针数组链表*(链表的每一个节点上都挂着一个数组)* ,链表上的每一个节点包括一个指针数组。该数组的元素依照待定的次序指向每一个储存节点的node_zones的数组。前面说过。在NUMA中分配物理页,往往要求在同一内存节点上分配,假设这时当前节点的空暇连续物理页无法满足分配,则能够通过这个指针数组依照0、1、2、3、4……的次序查找其他储存节点上的node_zones,直到找到一个能够满足分配的储存节点。指针数组中的元素排列次序,就称为一种分配策略。比方说有储存节点A、B、C、D、E。而node_zoneslist某节点上的指针数组元素排列次序为pA、pC、pD、pB。这个策略就规定了:要分配物理页的时候首先尝试从A分配。假设A不能满足,就查找B,假设B不能满足就查找C….而假设该点的指针数组为pC、pA、pD、pB。则这个策略规定:要分配物理页的时候首先尝试从C分配,假设C不能满足,就查找A。假设A不能满足就查找D….所以把node_zonelists称为分配策略链表也不为过。82: node_mem_map数组包括了该内存节点上的全部page结构。

三、 虚拟空间管理3.1 进程虚存区域

每一个进程都拥有自己的3G进程空间和1G共享的内核空间。

非常少会有进程占用到3G的空间,往往是占用多个离的虚存区域。虚存区域的抽象数据结构定义例如以下:[include/linux/mm.h : 41]

41 struct vm_area_struct { 42 struct mm_struct * vm_mm; /* VM area parameters */ 43 unsigned long vm_start; 44 unsigned long vm_end; 45 46 /* linked list of VM areas per task, sorted by address */ 47 struct vm_area_struct *vm_next; 48 49 pgprot_t vm_page_prot; 50 unsigned long vm_flags; 51 52 /* AVL tree of VM areas per task, sorted by address */ 53 short vm_avl_height; 54 struct vm_area_struct * vm_avl_left; 55 struct vm_area_struct * vm_avl_right; 56 57 /* For areas with an address space and backing store, 58 * one of the address_space->i_mmap{,shared} lists, 59 * for shm areas, the list of attaches, otherwise unused. 60 */ 61 struct vm_area_struct *vm_next_share; 62 struct vm_area_struct **vm_pprev_share; 63 64 struct vm_operations_struct * vm_ops; 65 unsigned long vm_pgoff; /* offset in PAGE_SIZE units, *not* PAGE_CACHE_SIZE */ 66 struct file * vm_file; 67 unsigned long vm_raend; 68 void * vm_private_data; /* was vm_pte (shared mem) */ 69 };

43: vm_start 该虚存区域的開始地址44: vm_end 该虚存区域的结束地址47: vm_next 用于将进程空间内全部的内存区域组成一个单项链表进行管理49: pgprot_t 页面保护权限,由于一个内存区域中仅仅有一个用于描写叙述页面訪问权限pgprot_t这意味这在允许个区域中的全部页面訪问权限是一致的。

54~55:

53 short vm_avl_height; 54 struct vm_area_struct * vm_avl_left; 55 struct vm_area_struct * vm_avl_right;

这三个成员用于将内存区域组成一棵AVL树,由于经常须要在进程空间中查找某个内存区域。假设用线性链表查找的方式,会影响效率。61: vm_next_share ????62 vm_pprev_share ???64 vm_ops指向一个struct ,实际上是一个跳转表:

120 struct vm_operations_struct { 121 void (*open)(struct vm_area_struct * area); 122 void (*close)(struct vm_area_struct * area); 123 struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int write_access); 124 };

该跳转表用于虚存区间的打开,关闭和建立,当中nopage在发生缺页中断的时候会被调用。

3.2 进程地址空间

在vm_area_struct结构中有一个成员vm_mm指向了mm_struct结构。这个结构是整个进程虚存空间的数据抽象。它管理这进程中的全部vm_area_struct抽象,换句话mm_struct是一个更高层的数据结构。定义例如以下:[include/linux/mm.h : 203]

203 struct mm_struct { 204 struct vm_area_struct * mmap; /* list of VMAs */ 205 struct vm_area_struct * mmap_avl; /* tree of VMAs */ 206 struct vm_area_struct * mmap_cache; /* last find_vma result */ 207 pgd_t * pgd; 208 atomic_t mm_users; /* How many users with user space? */ 209 atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */ 210 int map_count; /* number of VMAs */ 211 struct semaphore mmap_sem; 212 spinlock_t page_table_lock; 213 214 struct list_head mmlist; /* List of all active mm's */ 215 216 unsigned long start_code, end_code, start_data, end_data; 217 unsigned long start_brk, brk, start_stack; 218 unsigned long arg_start, arg_end, env_start, env_end; 219 unsigned long rss, total_vm, locked_vm; 220 unsigned long def_flags; 221 unsigned long cpu_vm_mask; 222 unsigned long swap_cnt; /* number of pages to swap on next pass */ 223 unsigned long swap_address; 224 225 /* Architecture-specific MM context */ 226 mm_context_t context; 227 };

204: mmap作为进程的所虚存区域构成的链表的链表头。205: mmap_avl指向进程全部虚存区域构成的AVL树的根节点。

206: mmap_cache指向近期一次使用的虚存空间。由于程序具有局部性。经常连续訪问同一片区域的空间。所以这里记录了近期一次使用的虚存区域。是一种缓存机制。207: pgd指向了进程的页文件夹208~212:尽管每一个进程仅仅能拥有一个mm_struct,可是一个mm_struct却能为多个进程所用。最显著的样例就是父进程使用vfork创建子进程。这样就会涉及到资源进程和引用计数的问题,当中mm_users、mm_count、map_count作为引用计数,而mmap_sem、page_table_lock则用来保证訪问的相互排斥。

216~219:用于说明整个进程地址空间中各个段的起始和结束地址,比方代码段。数据段,栈段。环境变量段等等。(注,这里的段是指镜像段,不能与段页管理中的段相混淆)

3.3 进程地址空间和进程虚存区域的关系

每一个进程都拥有一份mm_struct,它是整个3G进程空间的数据抽象,而由于进程往往不会整个3G空间都使用,而是使用不同的离散虚存区域。而且每一个离散区域的使用都不一样,比方说栈所在的区域和代码段所在的区域的使用就不一样,从而导致各个区域的属性、须要的管理操作都不一致,所以就将各个虚存区域提炼出来单独管理,然后就再将全部虚存区域组成一颗AVL树交由mm_struct统一管理。这中设计思想属于提炼差异,或者说提炼子类的思想。

原文作者:首页 - 内核技术中文网 - 构建全国最权威的内核技术交流分享论坛

原文地址:linux内存管理之数据结构 - 圈点 - 内核技术中文网 - 构建全国最权威的内核技术交流分享论坛(版权归原文作者所有,侵权留言联系删除)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有