千家信息网

怎么进行Linux系统内核架构分析

发表于:2024-11-21 作者:千家信息网编辑
千家信息网最后更新 2024年11月21日,这期内容当中小编将会给大家带来有关怎么进行Linux系统内核架构分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Linux系统中内核是一个非常重要的一部分,那么L
千家信息网最后更新 2024年11月21日怎么进行Linux系统内核架构分析

这期内容当中小编将会给大家带来有关怎么进行Linux系统内核架构分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

Linux系统中内核是一个非常重要的一部分,那么Linux内核具体是什么样子呢?下面本篇文章和大家深入讲解一下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结构来描述内存域。

  1. struct zone{

  2. /*通常由页分配器访问的字段*/

  3. unsigned long pages_min,pages_low,pages_high; 注:1)若空闲页的数目多于pages_high,则内存域的状态是理想的

  4. 2)若空闲页的数目低于pages_low,则内核开始将页换出到硬盘

  5. 3)若空闲页的数目低于pages_min,内存域急需空闲页,需页回收

  6. 4)数据结构中水印值得填充由init_per_zone_pages_min处理。

  7. 5)setup_per_zone_pages_min设置struct zone的pages_min,

  8. pages_low,pages_high成员。



  9. unsigned long lowmem_reserve[MAX_NR_ZONES]; 注:该数组分别为各种内存域指定了若干项,用于一些无论如何都不能失败 的关键性内存分配。

  10. struct per_cpu_pageset pageset[NR_CPUS]; 注:该数组用于实现每个CPU的热/冷页帧列表。内核使用这些列表保存可 用于满足实现的"新鲜"页。

  11. 热页帧:在高速缓存中,可以快速访问,

  12. 冷页帧:不在高速缓存中的页帧

  13. NR_CPUS是一个可以在编译时间配置的宏常数。

  14. 注:数组元素的类型为per_cpu_pageset

  15.         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的冷页或者热页*/}


  16. "


  1. /*

  2. *不同长度的空闲区域

  3. */

  4. spinlock_t lock;

  5. struct free_area free_area[MAX_OEDER]; 注:是同名数据结构的数组,用于实现伙伴系统,每个数组元素都表示某种 固定长度的一些连续的内存区。对于包含在每个区域中的空闲内存页 的管理。free_area是一个起点。

  6. ZONE_PAGGING(_pad1_)


  7. /*通常由页面收回扫描程序访问的字段*/

  8. spinlock_t lru_lock;

  9. struct list_head active_list; 注:是活动页的集合

  10. struct list_head inactive_list; 注:是不活动页的集合

  11. unsighed long nr_scan_active; 注:回收内存时需要扫描的活动页的数目

  12. unsighed long nr_scan_inactive; 注:回收内存时需要扫描的不活动页的数目

  13. unsighed long pages_scanned; 注:上次回收以来扫描过的页

  14. unsighed long flags; 注:描述内存域当前状态


  15.         typedef  enum {         ZONE_ALL_UNERCLAIMABLE,         /*所有的页都已经钉住,不能回收*/         ZONE_RECLAIM_LOCKED,            /*防止并发回收*/         ZONE_OOM_LOCKED,                /*内存域即可被回收*/}zone_flags_t;

  16. /*内存域统计量*/

  17. atmoic_long_t vm_stat[NR_VM_STAT_ITEMS]; 注:维护了大量有关内存域的统计信息。辅助函数zone_page_state用来 读取vm_stat中的信息

  18. int prev_priority; 注:存储了上一次扫描操作扫描该内存域的优先级。扫描操作是由try_to _free_pages进行的,直至释放了足够多的页帧。

  19. ZONE_PAGGING(_pad2_)

  20. /*很少使用或大多数情况下只读的字段*/

  21. wait_queue_head_t *wait_table; 注:是一个等待队列,可用于等待某一页变为可用进程。进程排成一个队 ``

  22. unsighed long wait_table_hash_nr_entries;列,等待某些条件, 在条件为真时,内核会通知进程恢复工作。

  23. unsighed long wait_table_bits;


  24. /*支持不连续内存模型的字段*/

  25. struct pglist_data *zone_pgdat; 注:内存域和父节点之间的关联由zone_pgdat建立,zone_pgdat指向对 应的pg_list_data实例

  26. unsighed long zone_start_pfn; 注:内存域第一个页帧的索引

  27. unsighed long spanned_pages; /*总长度,包括空洞*/

  28. unsighed long present_pages; /*总长度,不包括空洞*/实际上可用的页数目

  29. /*

  30. *很少使用的字段

  31. */

  32. char *name; 注:是一个字符串,保存该内存域的惯用名称。3个选项可用,Normal,

  33. DMA,HighMem

  34. }__cacheline_maxaligned_in_smp;

3.内存域水印的计算

在计算水印之前,内核首先确定需要为关键性分配保留的内存空间的最小值。该值随可用内存的大小而非线性增长,并保留在全局变量min_free_kbytes中。

注:1)高端内存域的下界SWAP_CLUSTER_MAX.

2)它定义了分组的大小。

3)setup_per_zone_lowmem_reserve计算出lowmem_reserve

上述就是小编为大家分享的怎么进行Linux系统内核架构分析了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

0