per-CPU(未完待续)

简介

  • per-CPU变量是内核的一个重要机制,正如名称所示,per-CPU变量为每个cpu单独提供内存空间,每个cpu只访问修改各自的空间
  • 一个per-CPU变量所需要的内存大小为:变量类型大小乘以cpu数量,即sizeof(type) x (number of cpus)
    • 在NUMA系统中,计算所占内存大小的公式与上面类似,但是实际上cpu数量的计算更复杂
  • 事实上,不管哪一种同步API都会带来或多或少的性能开销,但是一个per-CPU数据包含每个cpu自己的唯一私有数据,一个cpu不应该访问其他cpu对应的数据,所以按照这样逻辑不再需要使用同步API。注意:“只有这个cpu能访问这个数据“就是一种编程约定,我们需要确保当前cpu只会访问它自己的唯一数据。
  • 很多内核子系统使用了这个机制:
    • 内存管理的高速缓存机制
      • Page分配器
      • SLUB/SLAB分配器
    • 经常需要更新的性能统计计数器,需要高效同步机制的例子
      • vm统计
      • 网络统计
    • 基础设施RCU
    • 性能剖析profiling、Ftrace
    • VFS虚拟文件系统

下图是一个简单的per-CPU计数器例子
这里写图片描述

特点

Unit

  • 每个cpu数据将放入每个cpu对应的unit内存空间
  • unit不仅可能包含三种不同类型的内存区域,也有可能只包含一种内存区域
    • Static内存区域
      • 使用DEFINE_PER_CPU()宏声明per-CPU变量,其被编译进kernel映像中,在系统启动时为每个cpu定义这个变量
      • 默认大小0x3ec0
    • Reserved内存区域
      • 使用DEDINE_PER_CPU()宏声明per-CPU变量,其被编译进模块文件中,在加载模块时为每个cpu定义这个变量
      • 默认大小0x2000(8KiB)
    • Dynamic 内存区域
      • 借助alloc_percpu函数动态地分配每个cpu变量所占的内存空间
      • 默认大小0x5000(20KiB)
        • 在64位系统上,默认大小28KiB
  • unit大小等于
    • pcpu_unit_pages
      • 组成一个Unit的页帧数
      • 通常大小为 16
    • pcpu_unit_szie
      • 组成一个Unit的字节大小(单位Byte)
      • 通常大小为 0x10000(64KiB = 16 * 4KiB (PAGE_SIZE))

这里写图片描述

这里写图片描述

CPU -> Unit 映射

下图是一个在NUMA系统中cpu与unit映射的例子,(这个NUMA系统最大支持32CPU,实际有12CPU可用)
这里写图片描述

Chunk

per-CPU机制初始化

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章