NUMA(Non-uniform memory access)是一个高级玩意,咱先来看看维基百科上的定义:
is a computer memory design used in multiprocessing, where the memory access time depends on the memory location relative to the processor. Under NUMA, a processor can access its own local memory faster than non-local memory (memory local to another processor or memory shared between processors). The benefits of NUMA are limited to particular workloads, notably on servers where the data are often associated strongly with certain tasks or users.
总的一句话来讲,就是分配内存时需要区别对待。不同区域的内存我们叫做不同的节点,节点之间我们又定义了个“距离”的概念用来衡量内存访问时间的差异。
好了,有了基本的概念,我们来看看linux内核中是如何获得NUMA信息的。
在x86平台,这个工作分成两步
- 将numa信息保存到numa_meminfo
- 将numa_meminfo映射到memblock结构
本文着重关注第一次获取到numa信息的过程,对node和zone的数据结构暂时不在本文中体现。
全局概览
做事儿最好有点大局观,看代码学内核也是这个道理。那就先来看看总体结构。
setup_arch()
initmem_init()
x86_numa_init()
numa_init()
x86_acpi_numa_init()
numa_cleanup_meminfo()
numa_register_memblks()
接下来我们关注的就是最后这两个函数的作用。
将numa信息保存到numa_meminfo
在x86架构上,numa信息第一次获取是通过acpi或者是读取北桥上的信息。具体的函数是numa_init()。不管是哪种方式,numa相关的信息都最后保存在了numa_meminfo这个数据结构中。
这个数据结构和memblock长得很像,展开看就是一个数组,每个元素记录了一段内存的起止地址和node信息。