多核调度
SMP(Symmetric Multiprocessing,对称多处理)是一种常见的多核处理器架构。它将多个处理器集成到一个计算机系统中,并通过共享系统总线和内存子系统来实现处理器之间的通信。
首先,SMP架构将一组处理器集中在同一个计算机上。这些处理器可以是物理上独立的芯片,也可以是在同一芯片上集成的多个核心。无论是物理上独立的处理器还是集成在同一芯片上的核心,它们都可以同时工作,处理不同的任务。
在SMP架构中,各处理器是对等的,也就是说它们具有相同的权限和地位。每个处理器都可以独立地执行任务,并且可以访问共享的系统总线和内存子系统。这意味着不同的处理器可以同时读取和写入内存,从而实现数据的共享和协同处理。
通过共享系统总线和内存子系统,SMP架构实现了处理器之间的通信和协作。处理器可以通过总线发送和接收数据,从而进行协同工作。例如,一个处理器可以将计算结果存储在内存中,而另一个处理器可以读取该结果并继续后续的计算。
根据处理器的实际物理属性,CPU可以分为超线程和多核。
超线程(SMT,Simultaneous Multithreading):超线程是一种技术,允许单个物理处理器核心模拟出多个逻辑处理器核心。这意味着在一个物理处理器核心上可以并行执行多个线程,从而提高处理器的利用率和性能。在Linux内核中,针对超线程技术,可以使用CONFIG_SCHED_SMT进行分类和配置。
多核(MC,Multiple Cores):多核处理器是指在一个集成电路芯片上集成了多个独立的物理处理器核心。每个核心都可以独立地执行任务,因此多核处理器可以同时处理多个线程或进程,从而提高系统的并行处理能力和整体性能。在Linux内核中,针对多核处理器,可以使用CONFIG_SCHED_MC进行分类和配置。
Linux内核对CPU管理主要是通过使用bitmap来实现,同时定义了四种状态:possible、online、active、present。
1. 可能状态(possible):表示系统中存在但尚未启用的CPU。这意味着该CPU是硬件上存在的,但由于某些原因(例如节能策略或热插拔功能),暂时没有被激活。
2. 在线状态(online):表示CPU已经被启用并且处于可用状态。在线状态的CPU可以处理任务和线程,并参与系统的运行。
3. 活跃状态(active):表示CPU正在执行任务或线程,即处于活动状态。这是指当前正在被利用的CPU核心。
4. 存在状态(present):表示该CPU核心是物理上存在的,即硬件上存在该CPU核心。
在Linux内核中,为了实现对多核处理器的调度和管理,将同一个级别的CPU核心归纳为一个调度组(scheduling group),然后将同一个级别的调度组组合成一个调度域(scheduling domain)。
调度组是一组具有相似特性的CPU核心。比如,它们可能位于同一个物理芯片上、共享同一个高速缓存等。通过将这些核心组织在一起,内核可以更有效地进行资源分配和任务调度。调度组通常由内核自动创建,并根据硬件拓扑关系进行组织。
调度域是一组调度组的集合,它们具有相同的调度策略和目标。调度域用于确定任务在系统中的调度范围和选择可用的CPU核心。通过将调度组组合在一起,内核可以更好地控制任务的调度和负载均衡。
调度域的几个常见级别包括:
-
CPU级别调度域:表示同一个物理芯片上的多个调度组。这个级别的调度域被称为cpu_domain。
-
NUMA级别调度域:表示非一致性内存访问(NUMA)架构中的不同内存节点。这个级别的调度域被称为node_domain。
-
系统级别调度域:表示整个系统中的所有调度组,也可以包括多个NUMA节点。这个级别的调度域被称为sched_domain。
调度域和调度组
调度域(scheduling domain)和调度组(scheduling group)是Linux内核中用于管理多核处理器调度的重要概念。
-
调度组:Linux内核将同一个级别的CPU核心归纳为一个调度组。调度组是一组具有相似特性的CPU核心,它们通常位于同一个物理芯片上,或者共享同一个高速缓存。通过将这些核心组织在一起,内核可以更好地进行资源分配和任务调度。每个调度组都有自己的调度队列,内核根据调度策略从不同的调度组中选择适当的CPU核心来运行任务。
-
调度域:调度域是一组调度组的集合,它们具有相同的调度策略和目标。调度域用于确定任务在系统中的调度范围和选择可用的CPU核心。调度域的层次结构从低到高包括:硬件线程调度域、核调度域、处理器调度域和NUMA节点调度域。每个调度域都负责管理和调度其下一级调度域中的任务。通过将调度组组合在一起形成调度域,内核可以更好地控制任务的调度和负载均衡。
处理器拓扑结构
处理器拓扑结构是指处理器内部各个组件之间的连接关系和层次结构。在多核处理器中,常见的两种拓扑结构是NUMA(Non-Uniform Memory Access)和SMP(Symmetric Multiprocessing)。
-
NUMA结构:在NUMA结构中,处理器由多个物理节点组成,每个节点包含一部分处理器核心、内存和I/O设备。不同节点之间的访问延迟和带宽不同,因此是“非均匀内存访问”结构。在NUMA结构下,任务调度算法需要考虑到任务在不同节点之间的迁移和负载均衡,以优化系统性能。
-
SMP结构:在SMP结构中,所有处理器核心都共享同一个物理地址空间,内存访问延迟和带宽相同,因此是“对称多处理”结构。在SMP结构下,任务调度算法可以采用简单的轮转或抢占式算法来实现任务的负载均衡。
通常来说,在多核处理器中,处理器拓扑结构是由多个层次结构组成的。在最底层是核心层,一个处理器可以包含多个核心,每个核心有独立的一级缓存,所有核心共享二级缓存。在核心层之上是硬件线程层,也称为虚拟处理器或逻辑处理器,一个核心可以包含多个硬件线程,这些线程共享一级缓存和二级缓存。在硬件线程层之上是处理器层,一个处理器由多个核心和硬件线程组成,处理器共享内存和I/O资源。最高层是NUMA层,它由多个处理器组成,每个处理器可以包含多个处理器层,每个处理器层可以包含多个核心和硬件线程。
SMP
对称多处理器结构(SMP)是一种多处理器计算机系统架构,其中多个处理器核心共享同一个内存和I/O资源。SMP系统中的所有处理器核心都可以平等地访问整个内存地址空间,因此被称为"对称"。这意味着任何处理器核心都可以访问内存中的任何位置,而且内存访问的延迟和带宽在各个处理器核心之间是相同的。
SMP又称为UMA(Uniform Memory Access),全称为"统一内存访问架构"。UMA指的是系统中所有处理器核心对内存的访问具有相同的延迟和带宽,即内存的访问是均匀的,不论是哪个处理器核心发起的访问,所需的时间和速度都是一样的。
在SMP结构中,处理器核心通常被视为平等的,没有主次之分。这意味着在正常运行状态下,多个处理器核心都可以同时运行不同的进程,并且没有优先级差异。每个处理器核心都有相同的访问权限和能力,可以独立执行任务。
然而,在系统启动的特定阶段,SMP结构中存在一个引导处理器和其他暂停的应用处理器之间的区别。这是由于在系统刚刚上电或进行总清时,只有一个处理器核心能够执行引导程序并进行系统引导和初始化过程。
引导处理器负责执行引导程序,它负责初始化系统硬件、加载操作系统内核,并协调其他处理器核心的启动和初始化过程。引导处理器在启动完成后会将控制权转交给操作系统内核,然后其他应用处理器才会被激活并开始执行任务。
其他暂停的应用处理器处于待机状态,等待引导处理器的指示。一旦引导处理器完成了系统初始化,并将控制权交给操作系统内核,应用处理器也会被唤醒,并开始参与系统的正常运行。
引导处理器首先完成整个系统的引导和初始化,并创建起多个进程,从而确保系统能够正常运行。一旦引导处理器完成了这些任务,它会启动所有的应用处理器,让它们完成自身的初始化以后,投入到系统的运行当中。
在系统启动阶段,引导处理器负责执行引导程序,初始化硬件设备,并加载操作系统内核。然后,它会创建起多个进程,使得系统能够同时运行多个任务或应用程序。一旦系统达到了可以并行处理多个任务的状态,引导处理器会启动所有的应用处理器,让它们完成自身的初始化工作,并加入到系统的运行中。
SMP系统启动流程:
-
引导处理器(BP)先完成自身的初始化,然后从start_kernel()调用smp_init()进行SMP结构初始化。
-
smp_init()的主体是smp_prepare_cpus(),它会为每个处理器核心分配并初始化一个cpu结构体,并设置相应的标志位。
-
BP使用smp_callin_map[]表格记录每个处理器核心的状态,并向每个AP发送一个初始化IPI(Inter-Processor Interrupt),通知AP进入start_secondary()函数进行进一步初始化。
-
AP接收到IPI后,会执行trampoline.S中的一段跳板程序,在跳板程序中会将AP的状态设置为SMP_CALLIN,并调用startup_32()函数完成一些基本的初始化工作。
-
在start_secondary()函数中,AP会进行进一步的初始化,并等待全局变量smp_commenced变为1。这个变量是在BP完成所有AP的启动后被设置为1的。
-
BP调用smp_cpus_done()函数等待所有AP完成初始化,并最终调用smp_commence()函数发出起跑命令。
-
每个CPU进入cpu_idle()函数,等待调度。在这个函数中,处理器核心会处于空闲状态,并等待操作系统调度器分配任务给它。一旦有任务需要执行,处理器核心就会被唤醒并开始执行任务。