您好,登录后才能下订单哦!
这期内容当中小编将会给大家带来有关怎么进行Linux系统内核架构分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
1:在内核使用高端内存页之前,必须使用下文讨论的kmap和kunmap函数将其映射到内存虚拟地址空间中。
2:UMA计算机(一致内存访问,uniform memory access)将可用内存以连续方式组织起来。
3:NUMA计算机(非一致性内存访问,non-uniform memory access)系统的各个CPU都有本地内存,可支持特别快速的访问,各个处理器之间通过总线连接起来,以支持其他CPU的本地内存的访问。
4:内核会区分三种配置选项:FLATTMEM,DISCONTIGMEM,SPARSEMEM,DISCONTIGMEM.
5:内存划分为结 点。每个节点关联到系统中的一个处理器。在内核中表示为pg_data_t的实例。
6:各个结点又划分为 内存域,是内存域的进一步细分。
7:
注:zonelist:指向zonelist数据结构的指针,该数据结构按照优先次序描述了适于内存分配的内存管理区。
8:
1)ZONE_DMA标记适合DMA的内存域。
2)ZONE_DMA32标记了使用32位地址字可寻址,适合DMA的内存域。
3)ZONE_NORMAL标记了可直接映射到内核段的普通内存域,这是在所有体系结构上保证都会存在的唯一内存域,但无法保证该地址范围对应了实际的物理内存。
4)ZONE_HIGHMEM标记了超出内核段的物理内存。
5)伪内存域ZONE_MOVABLE.
6)MAX_NR_ZONES充当结束标志,在内核想要迭代系统中的所有内存域时,会用到该常量。
7)各个内存域都关联了一个数组,用来组织属于该内存域的物理内存页(页帧)。对每个页帧,都分配一个struct page实例以及所需的管理数据。
8)每个节点都提供了一个备用列表(借助struct zonelist)。该列表包含了其他节点(和相关的内存域),可用于代替当前节点分配内存。
3.2.2数据结构
1)结点管理
pg_data_t用于表示节点的基本元素。
typedef struct pglist_data{ struct zone node_zones[MAX_NR_ZONES]; struct zonelist node_zonelists[MAX_ZONELISTS]; int nr_zones; struct page*node_mem_map; struct bootmem_data *bdata; unsigned long node_start_pfn; unsigned long node_present_pages;/*物理内存页的总数*/ unsighed long node_spanned_pages;/*物理内存页的总数,包含洞在内*/ int node_id; struct pglist_data *pgdat_next; wait_queue_head_t kswapd_wait; struct task_struct *ksward; int ksward_max_order;}pg_data_t;
注:1)node_zones是一个数组,包含了节点中各内存域的数据结构。
2)node_zonelists指定了备用节点及其内存域的列表,以便在当前节点没有可用空间时,在备用节点分配内存。
3)节点中不同内存域的数目保存在nr_zones中
4)node_mem_map是指向page实例数组的指针,用于描述节点的所有物理内存页,它包含了节点中所有内存域的页。
5)bdata指向自举内存分配器数据结构的实例。
6)node_start_pfn是该NUMA节点第一个页帧的逻辑编号。所有页帧是依次编号的,每个页帧的号码都是全局唯一的。
在UMA中总是0.
7)node_present_pages指定了节点中页帧的数目,node_spanned_pages则给出了该节点以页帧 为单位计算的长度。
8)node_id是全局节点ID。
9)pgdat_next连接到下一个内存节点,系统中所有的内存节点都通过单链表连接起来,其末尾通过空指针标记。
10)kswapd_wait是交换守护进程(swap daemon)的等待队列,将在页帧换出节点时会用到。
kswapd指向负责该节点的交换守护进程的task_struct.
kswapd_max_order用于页交换子系统的实现,用来定义需要释放的区域的长度。
11)节点的内存域保存在node_zones[MAX_NR_ZONES].该数组总是有3项。即使节点没有那么多内存域,若不足3个,则其余的数组项用0填充。
enum node_states{ N_POSSIBLES, /*节点在某个时候可能变成联机*/ N_ONLINE, /*节点是联机的*/ N_NORMAL_MEMORY, /*几点有普通内存域*/#ifdef CONFIG_HIGHMEM N_HIGH_MEMORY, /*节点有普通或高端内存域*/#else N_HIGH_MEMORY = N_NORMAL_MEMORY,#endif N_CPU, /*节点有一个或者多个CPU*/ NR_NODE_STATES};
注:如果节点有普通或高端内存则使用N_HIGH_MEMORY,仅当节点没有高端内存才设置N_NORMAL_MEMORY.
2)内存域
内核使用zone结构来描述内存域。
struct zone{
/*通常由页分配器访问的字段*/
unsigned long pages_min,pages_low,pages_high; 注:1)若空闲页的数目多于pages_high,则内存域的状态是理想的
2)若空闲页的数目低于pages_low,则内核开始将页换出到硬盘
3)若空闲页的数目低于pages_min,内存域急需空闲页,需页回收
4)数据结构中水印值得填充由init_per_zone_pages_min处理。
5)setup_per_zone_pages_min设置struct zone的pages_min,
pages_low,pages_high成员。
unsigned long lowmem_reserve[MAX_NR_ZONES]; 注:该数组分别为各种内存域指定了若干项,用于一些无论如何都不能失败 的关键性内存分配。
struct per_cpu_pageset pageset[NR_CPUS]; 注:该数组用于实现每个CPU的热/冷页帧列表。内核使用这些列表保存可 用于满足实现的“新鲜”页。
热页帧:在高速缓存中,可以快速访问,
冷页帧:不在高速缓存中的页帧
NR_CPUS是一个可以在编译时间配置的宏常数。
注:数组元素的类型为per_cpu_pageset
struct per_cpu_pageset{ struct per_cpu_pages pcp[2];/*索引0对应热页,索引1对应冷页*/}__cacheline_aligned_in_smp;
注:该结构由一个带有数组项的数组构成,第一项管理热页。第二页管理冷页。
有用的数据保存在per_cpu_pages中。
struct per_cpu_pages{ int count; /*与该列表相关的页的数目*/ int high; /*high是页数上限水印,在需要的时候清空列表。若count的值超出high,即列表中的 页数太多*/ int batch; /*添加/删除多项页的时候,块的大小*/ struct list_head list; /*list是页的双链表,保存当前CPU的冷页或者热页*/}
“
/*
*不同长度的空闲区域
*/
spinlock_t lock;
struct free_area free_area[MAX_OEDER]; 注:是同名数据结构的数组,用于实现伙伴系统,每个数组元素都表示某种 固定长度的一些连续的内存区。对于包含在每个区域中的空闲内存页 的管理。free_area是一个起点。
ZONE_PAGGING(_pad1_)
/*通常由页面收回扫描程序访问的字段*/
spinlock_t lru_lock;
struct list_head active_list; 注:是活动页的集合
struct list_head inactive_list; 注:是不活动页的集合
unsighed long nr_scan_active; 注:回收内存时需要扫描的活动页的数目
unsighed long nr_scan_inactive; 注:回收内存时需要扫描的不活动页的数目
unsighed long pages_scanned; 注:上次回收以来扫描过的页
unsighed long flags; 注:描述内存域当前状态
typedef enum { ZONE_ALL_UNERCLAIMABLE, /*所有的页都已经钉住,不能回收*/ ZONE_RECLAIM_LOCKED, /*防止并发回收*/ ZONE_OOM_LOCKED, /*内存域即可被回收*/}zone_flags_t;
/*内存域统计量*/
atmoic_long_t vm_stat[NR_VM_STAT_ITEMS]; 注:维护了大量有关内存域的统计信息。辅助函数zone_page_state用来 读取vm_stat中的信息
int prev_priority; 注:存储了上一次扫描操作扫描该内存域的优先级。扫描操作是由try_to _free_pages进行的,直至释放了足够多的页帧。
ZONE_PAGGING(_pad2_)
/*很少使用或大多数情况下只读的字段*/
wait_queue_head_t *wait_table; 注:是一个等待队列,可用于等待某一页变为可用进程。进程排成一个队 ``
unsighed long wait_table_hash_nr_entries;列,等待某些条件, 在条件为真时,内核会通知进程恢复工作。
unsighed long wait_table_bits;
/*支持不连续内存模型的字段*/
struct pglist_data *zone_pgdat; 注:内存域和父节点之间的关联由zone_pgdat建立,zone_pgdat指向对 应的pg_list_data实例
unsighed long zone_start_pfn; 注:内存域第一个页帧的索引
unsighed long spanned_pages; /*总长度,包括空洞*/
unsighed long present_pages; /*总长度,不包括空洞*/实际上可用的页数目
/*
*很少使用的字段
*/
char *name; 注:是一个字符串,保存该内存域的惯用名称。3个选项可用,Normal,
DMA,HighMem
}__cacheline_maxaligned_in_smp;
3.内存域水印的计算
在计算水印之前,内核首先确定需要为关键性分配保留的内存空间的最小值。该值随可用内存的大小而非线性增长,并保留在全局变量min_free_kbytes中。
注:1)高端内存域的下界SWAP_CLUSTER_MAX.
2)它定义了分组的大小。
3)setup_per_zone_lowmem_reserve计算出lowmem_reserve
上述就是小编为大家分享的怎么进行Linux系统内核架构分析了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。