基于SPARC多核SOC的Linux操作系统研究

2017-07-21 05:13王海峰蒋晓华
航天控制 2017年3期

王海峰 蒋晓华

1.广东科学技术职业学院,珠海 519090 2.珠海欧比特控制工程股份有限公司,珠海 519080

基于SPARC多核SOC的Linux操作系统研究

王海峰1蒋晓华2

1.广东科学技术职业学院,珠海 519090 2.珠海欧比特控制工程股份有限公司,珠海 519080

通过移植启动代码,实现了Linux在SPARC多核处理器上的运行,重点剖析Linux针对SMP多核系统的进程管理机制、同步机制、进程调度和负载平衡等,在S698PM多核处理器平台进行了验证。 关键词 多核系统;SPARC SOC;Linux;进程调度;S698PM

Linux作为一种开源操作系统,具有内核精简、应用程序丰富、开发成本低廉和组件可配置等特点,广泛运用在桌面端和嵌入式领域。

目前在嵌入式领域,多核处理器已经大量应用,而多核处理器中又以SMP架构最为常见。所谓SMP 架构,即是2个或多个同样的处理器通过一块共享内存彼此连接,每个处理器可同等地访问共享内存(具有相同的内存空间访问延迟)。SMP技术提升了系统的性能,但同时也增加了操作系统内核的复杂度和协同开销,如何更好的支持SMP硬件系统是每个操作系统都面临的棘手问题[1]。

SPARC是国际上流行的RISC处理器体系架构

之一, SPARC V7/V8 是目前嵌入式控制系统常用的处理器标准版本,并在航天设备的电子系统中得到广泛应用。基于SPARC SMP的多核处理器应用前景较好,由于SPARC嵌入式处理器主要应用在航天军工领域,Linux系统本身对SPARC架构的支持有限,对SPARC SMP的支持更是空白,一般需要进行平台移植[2-3]。本文以此为出发点,研究SMP系统中的几个关键技术,阐述了Linux 2.6系统针对SPARC多核处理器中的移植过程,并详细分析研究了在Linux操作系统下如何更好地解决多个CPU之间的同步机制、负载平衡和进程调度问题。

1 SPARC对称多核SOC

以多核处理器S698PM为硬件实验平台。S698PM是基于SPARC V8架构的高性能的32位RISC嵌入式4核SOC处理器,其内部采用SMP“对称多处理”技术,各CPU之间共享内存子系统以及总线结构,总线竞争和仲裁由硬件自动完成,为了支持SMP,硬件上还集成了APIC中断控制系统[4]。

2 Linux在SPARC多核SOC中的引导

在Linux2.6 SMP结构中,CPU平等是建立在系

统中有多个进程或者多个执行上下文的前提下,由于在系统的引导和初始化阶段只有一个上下文,而同一时间,一个上下文只能有1个CPU来处理,所以在CPU系统初始化阶段只能有1个引导处理器CPU0工作,而其余的应用处理器CPU1,CPU2和CPU3处于暂停状态。CPU0完成系统的引导和初始化,并创建1号进程kernel_init和3个idle进程,在kernel_init中通过LOCAL APIC发送IPI消息控制CPU1,CPU2和CPU3从指定的起始地址运行,实现逐个启动CPU1,CPU2和CPU3的功能,达到SMP并行处理的要求。

在操作系统中,可能会随机分配某个CPU为启动CPU,因此,为确保CPU0为启动CPU,必须修改head.s文件中的trapbase为CPU0,如下所示。

图1 S698PM功能结构

start:trapbase:#ifdefCONFIG_SMPtrapbase_cpu0:#endif

此外引导部分还需要针对SPARC架构进行内存管理单元、中断控制器和时钟的设置,并进行内存清空和内存读写测试等操作,只有部分工作统一由CPU0来完成。添加及修改的几个主要文件包括:

1)device.c和init.c:完成处理器信息和驱动信息的扫描。如果扫描符合要求,系统才允许进入引导程序,并做出下一步的初始化;

2)prom.c:在rootnode中建立驱动树,为后续开发驱动应用程序提供帮助,使驱动设备和其相应的驱动程序以及设备号能很好地对应起来;

3)leon_irq.c:实现对SPARC系统中断的管理,用来对中断初始化、中断设置和中断错误报告相关信息的跟踪等。

移植完成后Linux对SMP的引导过程如下:

(1)加载Linux内核映像到内存

Linux内核映像存贮在Flash中,当系统加电时,利用Bootloader将初始化信息传递给Linux内核,Bootloader把Linux内核复制到0开始的物理内存处开始执行。

(2)执行Linux系统初始化

成功加载内核映像之后,Boot Loader将指引CPU0跳转到Linux内核映像的入口地址_start函数处执行。这时,由于MMU地址映射还没启用,因此需要将链接地址转换成物理地址来实现CPU中Cache,TLB以及寄存器的初始化。

初始化后,临时MMU地址映射开启,CPU0跳转到 start_kernel()继续执行,并构造0号进程rest_init运行上下文,rest_init完成初始化部分并调用kernel_thread()函数创建第一个核心进程kernel_init。kernel_init函数代码如下:

Statickernel_init(void){smp_prepare_cpus(max_cpus);smp_boot_cpus(max_cpus);connect_bsp_APIC();setup_local_APIC();map_cpu_to_logical_apicid();do_boot_cpu(apicid,cpu)}

do_boot_cpu会完成应用处理器的初始化,并通过中断方式通知主CPU,次CPU可以启动。

(3)应用程序初始化

init完成Linux的各项配置后,会在/sbin,/etc和/bin中寻找init程序来运行。该init程序会替换kernel_init()进程,此时处于内核态的1号进程kernel_init()将转换为用户空间内的1号进程init,开始系统的正常运行。

在Linux中,SMP系统的多核引导是一个分阶段的过程,这中间需要主CPU和次CPU在几个地方进行同步,最终基本在同一时间进入SMP的进程调度。

图2 Linux SMP多核引导流程图

3 Linux内核针对SMP的进程管理

3.1 同步机制

在Linux SMP中,多个CPU可以并行运行内核代码,当内核数据被多个内核控制路径共享存取时,就会产生资源竞争。根据资源竞争产生的原因及所保护的数据不同,Linux操作系统为内核代码提供了多种同步与互斥机制,如原子操作、信号量、读写、大内核锁、读写锁和自旋锁等方法,来保护内核数据的安全共享。操作系统锁机制的基本原理是在某个锁操作过程中不能与其他锁操作交织执行,以免多个执行路径对内核中某些重要的数据及数据结构进行同时操作而造成混乱,本文主要利用自旋锁来确保CPU的同步互斥操作。

自旋锁(spinlock)是使用忙等待锁来确保互斥的一种特殊方法。每个自旋锁都是用1个spinlock_t数据结构来表示。只有spinlock_t的最低位被使用,如果锁可用,则它是0;如果被取走,则它是1。

在可抢占内核和SMP情况下,如果2个任务竞争1个共享的资源,没有得到资源的任务将自旋以等待另一个任务使用完该共享资源,自旋锁的实现如下:自旋锁在使用前必须先初始化,自旋锁有完全锁和读写锁2种形式。在SMP系统中主要用的是完全锁。

首先创建一个新的自旋锁,

spinlock_tpm_spinlock=SPIN_LOCK_UNLOCKED;SPINLOCK(pm_spinlock);spin_lock_init(&pm_spinlock);

自旋锁被初始化为值SPIN_LOCK_UNLOCKED,它也可以用spin_lock_init函数来初始化。这两者都把spinlock_t的lock成员设置成0,也就是未锁状态。定义自旋锁后,就可以使用锁变量,每个变量用于不同的上下文。

实际运行时通过函数spin_lock_irqsave和spin_unlock_irqrestore来实现自旋锁的获取和释放。当进程在某个CPU上运行时,需要通过spin_lock_irqsave获取自旋锁,并在本地处理器上禁用中断。运行完成之后,需要通过spin_unlock_irqrestore释放自旋锁,并且(通过flags参数)恢复中断,实现CPU之间的互斥功能。

3.2 进程调度

Linux 操作系统在处理进程调度时,Task起关键作用。任务的基本数据结构为task_struct,包涵了任务的当前状态、优先级、剩余时间片、进程号、正在使用的CPU和上一次使用的CPU以及内核锁的深度等参数。

Linux 操作系统内核中负责进程调度的具体函数是Schedule,当已经不在运行队列里的进程被唤醒时,Wake up process( ) 函数将调用Reschedule idle( ) 函数,尝试在一个空闲的CPU 上运行被唤醒的进程,它使高优先级的进程得到占用CPU 的机会。此时函数Reschedule idle 被调用, 尝试在别的CPU 上调度该进程。

函数Reschedule idle首先检查进程上次运行的CPU,如果该CPU处于忙状态,则找其它合适的CPU,查看SMP中的每个CPU上运行的进程,并与现有进程相比优先权,把具有最高的抢先权值的进程记录在target_task中。 如target_task为空,说明没有找到合适的CPU;如果target_task不为空,则说明找到了合适的CPU,将target_task->need_resched置为1。如果运行target_task的CPU不是当前运行的CPU,则向运行target_task的CPU发送一个IPI中断,让它重新调度,实现对进程的调度功能。

3.3 负载均衡

在SMP多核系统中,每个处理器都有独立的运行队列runqueue,当存在多个就绪进程队列runqueue,CPU会一直处于忙状态。相反,当runqueue较少时,相应的CPU可能会经常处于空转状态,这会导致CPU负载不均衡。Linux对负载均衡的实现重点体现在何时检查负载,如何调整负载。

检查负载有2种方法:1)在进程的启动、睡眠时进行检查;2)定时检查。

当进程调用了sleep,pause等操作时,schedule()函数会调用idle_balance(),从其他CPU挪用进程过来。定时检查利用函数rebalance_tick()来实现,在每个CPU上的每个定时器的tick时刻调用rebalance_tick(),检查每个调度域,在一定的时间间隔内调用函数load_balance()进行负载平衡。

Linux系统中,在load_balance函数及idle_balance函数中调用pull_task函数以从重载CPU上将进程“搬运”到轻载CPU上,实现负载平衡。函数load_balance根据当前CPU是否空闲分为“忙平衡”和“空闲平衡”。每tick时钟中断会启动一次函数rebalance_tick来计算合适的时间间隔,启动函数load_balance平衡负载。另外,在调度器schedule中,如果本CPU的就绪队列为空也会调用idle_balance函数进行“空闲平衡”。函数pull_task实现任务的搬运工作,更新进程的timestamp属性,如果搬运过来的进程优先级比本CPU正运行的进程高,则当前进程被抢占。

staticvoidrebalance_tick(){……if(idle!=SCHED_IDLE)interval∗=sd->busy_factor;……}

4 Linux在S698PM中的应用验证

移植完成后,Linux可以在S698PM平台正确运行,本文以S698PM处理器的1553B应用为例,验证Linux SMP系统的运行过程。

应用程序中使片内1553B为RT模式,同时打开1553B的2路接收,相当于在Linux操作系统中开启了2个进程来实现RT的接收功能,在RT接收过程中,Linux操作系统还需要处理其他的进程,如:sshd守护进程、shell进程等,观察程序的运行过程可以大概了解Linux的进程管理方法。

执行user/custom/Makefile脚本文件编译应用并生成image.dsu文件,下载到S698PM板卡中运行,并连续向这2路1553B接口发送数据,程序运行如图3所示。

从图4 可以看出,当2路1553B同时接收时,Linux会根据SMP调度机制将2路接收进程分配在CPU0和CPU1上同时运行,实现了资源合理分配和负载平衡。并且2路之间没有出现延时和漏数的现象,证明系统的进程调度和同步机制工作正常。

5 结论

通过修改Linux的启动代码,实现了对基于SPARC的SMP对称多核SOC处理器的支持,通过在S698PM处理器平台上运行Linux,验证了Linux针对SMP系统的同步机制、进程调度和负载平衡这3个重要特性。

[1] [美]ScottMaxwell. Linux 内核源代码分析[M]. 冯锐, 等. 译.北京: 机械工业出版社, 2000.

[2] Bovet, Cesati .深入理解Linux 内核[M]. 陈莉君, 等. 译.北京:中国电力出版社, 2001.

[3] [美]李(Li,Q),等.嵌入式系统的实时概念[M].王安生.译.北京:北京航空航天大学出版社,2004.

[4] S698PM用户手册[Z].珠海欧比特控制工程股份有限公司,2014,6.

Study on Linux Application Based on Multi-Core SPARC SOC

Wang Haifeng1, Jiang Xiaohua2

1. Guangdong Institute of Science and Technology, Zhuhai 519090, China 2.Orbita Control Engineering Co.,Ltd., Zhuhai 519080, China

Firstly,bythetransplantationofthestartupcode, LinuxcanrunontheSPARCmulti-coreprocessor.Then,theLinuxprocessmanagementfortheSMPmulti-coresystemisfocused,includingsynchronizationmechanism,processschedulingandloadbalance.Finally,theactualverificationisimplementedinS698PMmulti-coreprocessorplatform.

Multi-coresystem;SPARC SOC;Linux;Dispatchprocessing;S698PM

图3 Linux在S698PM运行

图4 Linux 1553B RT运行截图

TP316

A

1006-3242(2017)03-0049-05

2015-06-10

王海峰(1974-),男,山西永济人,硕士,副教授,主要研究方向为电子与信息系统;蒋晓华(1978-),男,湖南衡阳人,硕士,高级工程师,主要研究方向为集成电路设计。