percpu内存分配器

percpu变量指的是为每个CPU都创建一个同样的变量,也就是为每个CPU分配一份单独的内存空间,用来保存各自私有的数据。在SMP「Symmetry Multi-Processor」系统中,为了确保多个CPU能够正确地访问同一个资源,同步机制是必不可少的,比如缓存一致性「cache coherence」和自旋锁「spinlock」。但是通过使用percpu变量,内核能够使每个CPU只访问自己私有的内存空间,因此可以避免使用同步机制「free-lock」。本文将逐步揭开percpu内存管理机制的面纱。


  • Target Platform: Rock960c
  • ARCH: arm64
  • Linux Kernel: linux-4.19.27

概述

percpu是一种内存管理机制,它不仅能为每个CPU私有的变量分配内存空间,并且对percpu变量所用的内存空间进行集中统一管理。通过使用每个CPU自己的单独内存空间,内核既能够避免多CPU并发访问需要的锁机制不仅能够提高系统的性能,还能够改善处理器(CPU)的缓存命中率「cache hit rate」。

percpu机制主要特点

percpu内存管理机制是在内核2.6版本引入的。在SMP系统中,如果只访问CPU私有的数据,那么将极大减少对同步机制的依赖。为此,内核可以借助percpu机制在其管理的区域「percpu chunk」内为每个CPU分配一段内存空间,用于保存各自私有的数据,也就是每个CPU都有一份自己的数据副本。当你想在不使用锁机制的情况实现大量的写操作时,percpu机制在设计阶段就应该首先考虑进去。不过,percpu机制不是无条件的,在使用时还是需要考虑中断和内核抢占时的保护任务。不管怎样,percpu机制在内核被广泛使用,比如网络报文统计、磁盘IO统计和内核对象计数等。由于不需要使用锁机制,所以在需要完成每秒上千次的数据更新时percpu机制的性能还是有大幅提升和改进的。

percpu_count.svg

图1 percpu count

percpu_unit_size.svg

图2 percpu chunck

percpu_chunck_layout.svg

图3 percpu chunck layout

percpu_unit_map.svg

图4 数组pcpu_unit_map[]

percpu_unit_offset.svg

图5 数组pcpu_unit_offsets[]

percpu_alloc_info.jpg

图6 设置struct pcpu_alloc_info实例

pcpu_cpu_to_unit.svg

图7 cpu->unit映射

pcpu_chunk_configuration.svg

图8 chunk配置

percpu_base_addr_location.svg

图9 pcpu_base_addr定位

percpu_first_chunk.svg

图10 first chunk与unit的关系

percpu_mapping_management.svg

图11 first chunk的地址空间映射