Linux SMP启动流程(一)

Linux SMP启动流程(一)

1 SMP硬件体系结构

  • SMP的全称是"对称多处理"(Symmetrical Multi-Processing)技术,最简单可以理解为系统存在多个完全相同的CPU,所有CPU之间共享内存子系统以及共享总线,拥有自己的通用寄存器。对于内存和外部设备访问,由于共享总线,所以是共享的。Linux操作系统多个CPU共享在系统空间上映射相同,是完全对等的。

2 CPU拓扑结构简介

Linux SMP启动流程(一)
注:对于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。
上一篇:我怎么知道进程正在运行哪个核心?


下一篇:Linux 和 SMP(对称多处理)