Linux SMP启动流程(一)
1 SMP硬件体系结构
- SMP的全称是"对称多处理"(Symmetrical Multi-Processing)技术,最简单可以理解为系统存在多个完全相同的CPU,所有CPU之间共享内存子系统以及共享总线,拥有自己的通用寄存器。对于内存和外部设备访问,由于共享总线,所以是共享的。Linux操作系统多个CPU共享在系统空间上映射相同,是完全对等的。
2 CPU拓扑结构简介
注:对于ARM 架构,目前由于不支持超线程技术,只有DIE和MC两个Topology Level。
-
内核有一个数据结构struct sched_domain_topology_level来描述CPU的层次关系,简称SDTL,请见[/include/linux/sched/topology.h:186]
struct sched_domain_topology_level { sched_domain_mask_f mask; //函数指针,用于指向某个SDTL的cpumask bitmap sched_domain_flags_f sd_flags; //函数指针,用于指定某个SDTL的标志位 int flags; int numa_level; struct sd_data data; #ifdef CONFIG_SCHED_DEBUG char *name; #endif };
-
另外,Linux内核定义了default_topology[]来概括CPU域的层次结构 ,顺序是自底向上,请见[/kernel/sched/topology.c:1205]
static struct sched_domain_topology_level default_topology[] = { #ifdef CONFIG_SCHED_SMT { cpu_smt_mask, cpu_smt_flags, SD_INIT_NAME(SMT) }, #endif #ifdef CONFIG_SCHED_MC { cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) }, #endif { cpu_cpu_mask, SD_INIT_NAME(DIE) }, { NULL, }, }; static struct sched_domain_topology_level *sched_domain_topology = default_topology;
-
从default_topology[]看,DIE类型是默认类型,而SMT和MC类型只有和具体的硬件架构匹配,才能发挥出效果。
内核对CPU的管理是通过bitmap管理的,可见[/include/linux/cpumask.h:16]typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
Linux定义了四种CPU状态:possible、present、online、active,可见[kernel/cpu.c:1960]
const unsigned long cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)] = {
MASK_DECLARE_8(0), MASK_DECLARE_8(8),
MASK_DECLARE_8(16), MASK_DECLARE_8(24),
#if BITS_PER_LONG > 32
MASK_DECLARE_8(32), MASK_DECLARE_8(40),
MASK_DECLARE_8(48), MASK_DECLARE_8(56),
#endif
};
EXPORT_SYMBOL_GPL(cpu_bit_bitmap);
const DECLARE_BITMAP(cpu_all_bits, NR_CPUS) = CPU_BITS_ALL;
EXPORT_SYMBOL(cpu_all_bits);
//表示系统中有多少可以运行的CPU核心
#ifdef CONFIG_INIT_ALL_POSSIBLE
struct cpumask __cpu_possible_mask __read_mostly
= {CPU_BITS_ALL};
#else
struct cpumask __cpu_possible_mask __read_mostly;
#endif
EXPORT_SYMBOL(__cpu_possible_mask);
//表示系统中有多少个处于工作状态的CPU核心
struct cpumask __cpu_online_mask __read_mostly;
EXPORT_SYMBOL(__cpu_online_mask);
//表示系统中有多少个具备online条件的CPU核心,不一定都处于online状态,
//有的CPU核心可能被热拔插了
struct cpumask __cpu_present_mask __read_mostly;
EXPORT_SYMBOL(__cpu_present_mask);
//表示系统中有多少个活跃的CPU
struct cpumask __cpu_active_mask __read_mostly;
EXPORT_SYMBOL(__cpu_active_mask);
- bitmap使用一个long型数组name[],每一位代表一个CPU。对于32位处理器来说,一个long类型最多只能支持32个CPU核心。假设CONFIG_NR_CPUS是8,那么只需要一个long类型的数组就行了,struct cpumask数据结构本质上也是bitmap,内核通常使用cpumask的相关接口函数来管理CPU核心数量,在[/lib/cpumask.c]和[\include\linux\cpumask.h]文件实现了大部分和cpumask有关的API。