1、体系结构

     支持多核处理器的OS可能有几种结构:主从结构、粗加锁方式、细加锁方式。

   (1)主从结构:修改一个OS内核使其支持多处理器系统的最简单的方法,是将整个OS视为一个不可分割的整体,并限定所有内核模式的操作均运行于同一个处理器(即主处理器)上,而另一个处理器(即从处理器)只用来执行用户模式的操作,这样得到的软件结构就不再是对称的。

      系统维持两个队列:一个用来管理申请在主处理器上执行的任务,另一个用来管理申请在任意一个从处理器上执行的任务,都必须由旋转锁保护。只有大多数任务都以用户模式运行时,这种结构才能体现其优越性。

  (2)粗加锁结构:是将整个OS当作一个由旋转锁保护的整体单片电路,但又不会将内核模式的操作局限在某一个特定的处理器上。

任何一个要求内核模式操作的任务都可以获得粗加锁,并且继续在它正在使用的处理器上运行。但在某个特定的时刻,这种内核模式的操作仍然只能在某一个处理器上运行。当某项任务占用着粗加锁时,其它所有等待获得内核服务的任务都只能空闲。

      粗加锁的问题在于如果有几个任务都在等待获得内核服务,那么这些任务将像在单处理器系统中一样一个接一个地连续运行。

  (3)内核细加锁:设计内核细加锁(fine-grained locking)结构的目的是为了让不同处理器上运行的任务能够同时执行内核模式操作,采用这种结构的内核叫做线程化内核(threaded kernel),这是通过对不同的内核子系统分别采用旋转锁来实现的,以便企图访问这些子系统的任务能够并发执行。

      加锁机制的粒度(granularity)决定了最大可并发执行的内核线程数。


2
、系统引导和初始化

      OS的引导和初始化是指从系统加电到能够在多个处理器内核间平等地进行任务调度的过程,是建立平等调度实施的基础。虽然说SMP系统中,各处理器可以平等地并行工作,但这是建立在系统有多个可并行执行任务的基础上;而在引导和初始化过程中,由于很多工作只能串行执行,在这个阶段处理器内核是不平等的,有主次之分。系统加电后,受到硬件控制,只启动其中一个处理器,称为主CPU或引导处理器(Booting Processor,BP),而其它处理器称为次CPU或应用处理器(Application Processor,AP),处于停机等待状态。

      加电启动后,主CPU跳转到特定的内存地址(复位地址),通常映射到只读存储器,保存着整个计算机的引导程序(Bootloader),其任务是进行简单的硬件检测、初始化环境参数、将OS内核装载到内存中,跳转到OS的起始地址(这是在哪里呢,类似于NiosII Boot中的_start,.text段的入口地址)开始并执行。这段引导过程完全由BP完成。

      进入OS内核后,BP需要进行最初的草创性工作,完成运行环境准备、各种初识状态设置、基本读写数据段清零、Bootloader传递过来的各种环境参数保存、内存栈的开辟及栈指针、全局指针设置,前面这部分工作全部由底层汇编代码完成(_start至alt_main()之间的代码),之后BP跳转到由高级语言编写的函数,开始第二个阶段CPU本身的初始化(alt_main()函数)。

      在CPU初始化过程中,BP首先自检,收集CPU相关的指令集、存储管理、高速缓存及协处理器等基本信息,接着为AP准备运行环境,同时为AP准备一个锁,之后唤醒AP,AP转入主CPU设置好的地址,开始锁测试而进入等待状态。唤醒AP后,BP输出自身信息后,继续进行内存等各种资源的初始化。

      接下来的工作主要有BP进行开发板及外部设备初始化,之后准备用于所有CPU的空闲进程,这是一个不参与调度的进程。当某个CPU没有需要执行的任务,就转入这个进程。准备好空闲进程后,由BP解除对AP的锁,各AP逐个启动,进行各种关于各自CPU的初始化,将自身的状态填写到适当的数据结构,最后相继进入空闲状态。

      所有的AP都完成初始化并进入空闲状态后,由BP来完成整个系统最后阶段的初始化,并执行系统的第一个进程,之后真正步入SMP环境,所有的CPU进入正常、平等的调度。


3
、进程调度

      在CMP结构中,调度机制的重点在于更好地满足多处理机并行性上,核心思想是通过降低CPU间调度竞争和选择下一个运行进程的开销,以及提高系统整体负载平衡的能力,从而大幅度提高多处理机系统的执行效率。

  (1)调度算法:在支持CMP的OS中,每个CPU维护一个自己的就绪进程队列,称为局部任务队列。就绪进程按时间片是否用完分为active和expired两大类,active类包括那些时间片没用完、当前可被调度的就绪进程,expired类包括那些时间片已用完的就绪进程。同时,每类中的进程按照其优先级的不同处于不同的优先级链表中。

      调度时,active队列中非空的最高优先级链表的第一项被作为候选进程,使得选择下一个运行进程的操作可在固定时间内完成;同时内核建立了位映射数组对应每一个优先级链表,使用标志位极大降低了寻找非空链表的时间。

      当一个进程耗尽其时间片后,内核重新计算它的优先级,并把它放置在expired队列的相应优先级链表中。当active队列中没有可调度进程时,内核简单地对调active和expired队列,将原来的expired队列作为新的active队列后即可进行新一轮调度。

      此调度算法选择下一个运行进程的时间复杂度是O(1)。

  (2)系统负载平衡:支持CMP的OS内核的调度系统需要很好地解决进程与CPU间的“亲和”问题,尽量使得每个进程在固定CPU上执行,提高Cache命中率。无论当前CPU繁忙/空闲,时钟中断每隔一段时间都会启动以平衡负载。一旦当前CPU发现自己的就绪队列为空,也会主动进行负载平衡。

      OS内核根据系统结构的特点,引入调度域的概念将全体CPU一层一层地划分成不同的区域,每个调度域中的CPU分成若干个CPU组,且满足任一CPU惟一存在于一个组中。每个CPU属于一个基本的调度域(该域至少包括本CPU),但是CPU同时还属于一个或多个更大的调度域。每个CPU的最高层调度域必须包括系统中的全部处理器。

      对于CMP系统,每个芯片上的多个核天然地构成一层调度域。一个单芯片CMP系统和一个普通SMP系统的基本调度域的差别仅在于CMP基本调度域的CPU组包含的对象是一个“CPU核”,而SMP基本调度域的CPU组包含的是一个传统的物理CPU。

      负载平衡时,从当前CPU的基本调度域出发,遍历所有的调度域。如果某个域有一段时间没有进行过负载平衡,先寻找域中负载最大的CPU组,再寻找组中最繁忙的CPU,更新双方的负载记录,确定需要迁移的进程数为源CPU负载与本CPU负载之差的一半,然后按照从expired队列到active队列、从低优先级进程到高优先级进程的顺序进行迁移。


4
、中断处理

      传统的单处理器通常都采用一个外部中断控制器来解决外部设备到CPU的通信。对多处理器系统,处理器之间也需要通过中断方式通信。对CMP而言,多处理器的本地中断控制器需要和处理器一起封装到芯片内部,还需要一个全局中断控制器负责各个处理器内核间的中断分配,也要设计在芯片内部。

  (1)中断分配:全局中断控制器担负着把来自外部设备的中断请求提交和分配给片内各CPU的任务。对于每个中断向量,可采用静态和动态两种模式之一。如果某个中断向量是静态分配的,控制器把这种中断请求提交给预设的一个或多个CPU;动态模式则可以发送给所有CPU,或随机发送给某个处理器。本地中断控制器处理本地处理器内部产生的中断请求、来自外部中断控制器的中断请求及其它处理器发送过来的中断请求。

  (2)处理期间中断:在CMP系统中,芯片内部一个处理器常常要有目标地向系统中的其它处理器发出中断请求,这种中断被称为处理期间中断(IPI,Inter Processor Interrupt)。IPI至少应该包含两种:

      一、“重新调度”中断:当前CPU可以发送该中断来指示目标CPU可能需要一次进程调度,至于目标CPU在处理完该中断以后是否进行进程调度,得看事先或者在处理中断的过程中是否把当前进程设置为需要调度。

      二、“请求执行”中断:这个中断被用来请求目标CPU执行一个指定的函数,因为这些函数必须由目标CPU才能完成,而不能由别的CPU代替。

  (3)时钟中断:每个处理器都有自身的时钟发生器。在系统初始化阶段,系统先设置一个外部时钟中断源供所有CPU共享,并以此为基准测算各个CPU的运算速度,并校准自身的时钟中断发生间隔。所有CPU有基本相同的时钟脉冲周期,为了不让所有处理器都在同一时刻发生时钟中断,OS应该使各个CPU的时钟中断在相位上相互错开,把这些中断均匀地分布在时钟中断的周期中。


5
、同步与互斥技术

      同步与互斥机制需要底层硬件提供“读-修改-写”类型的访存原子操作,这样的操作能够让CPU从主存储器中读取一个值,修改之,再将修改过的值保存到存储器的相同位置中。整个过程是一次完整的总线交易,不能被其他CPU内核的访存操作所打断。“读-修改-写”类型的原子操作有多种实现方式,最常见的包括:test_and_set,swap,load-linked/store-conditional等方式。

版权声明:本文为sopc-mc原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/sopc-mc/archive/2010/04/18/1714744.html