一种面向多核处理器的操作系统噪声控制方法转让专利

申请号 : CN201110061401.4

文献号 : CN102117224B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 王雷谭成鑫陈佳捷

申请人 : 北京航空航天大学

摘要 :

本发明为一种面向多核处理器的操作系统噪声控制方法,属于操作系统和程序分析领域。本发明的噪声控制方法基于隔离控制的方法,在Linux内核上实现,首先设置一套内核控制接口,通过该接口动态地设置静化处理器,并指定进程到静化处理器上运行;然后设置支持静化控制的内核机制,主要包括:内核工程的修改、基本数据结构的增加和修改、设置新的静化处理器和保护静化处理器不受影响。本发明的噪声控制方法可以不用重启地重新设置某些需要隔离的静化处理器,使这些处理器避免任务的再平衡,从而实现了对操作系统噪声的控制,并给操作系统用户提供了良好的一致性体验。

权利要求 :

1.一种面向多核处理器的操作系统噪声控制方法,其特征在于,该方法在Linux内核上实现,具体为:

第一步、配置一套内核的控制接口,包括:

步骤1.1、虚拟/proc文件系统接口初始化:首先创建静化处理器子系统的目录quietcpu,然后在目录quietcpu下为每个处理器创建各自的子目录以及控制项,最后为每个控制项注册相应的读写操作函数,并将操作系统中的数据结构proc_dir_entry中的参数data中存储的数据修改为指针形式的处理器编号;

步骤1.2、访问虚拟/proc文件系统的文件接口:当静化处理器子系统中的某个静化处理器的控制项文件中被写入数据时,写操作函数被调用,写操作函数从数据结构proc_dir_entry中的参数data中获得处理器的编号,再对写入的数据进行分析,在写入数据有效且写入的数据为非零值时,调用与从参数data中获得的处理器编号对应的静化处理器设置函数,若写入的数据为0,则恢复静化处理器到正常模式;从静化处理器子系统中的某个静化处理器的控制项文件读取数据时,读操作函数同样从参数data中取得处理器编号后,从静化处理器子系统获得对应处理器的静化状态;

步骤1.3、指定进程到静化处理器上运行:将操作系统中原函数set_cpus_allowed_ptr替换为带有静化处理器子系统标志的新函数__set_cpus_allowed,新函数较原函数增加了一个用于标志调用是否是来自静化处理器子系统的参数,对系统调用函数sched_setaffinity的实现进行修改,在修改进程与处理器的现有分配关系时会调用函数__set_cpus_allowed,通过使用taskset工具,先启动进程执行,再设置进程的亲和性属性,从而制定进程在静化处理器上运行;所述的进程的亲和性属性具体是通过调用新函数__set_cpus_allowed,修改处理器亲和性位图cpus_allowed来设置的;

第二步、设置支持静化控制的内核机制,包括:

步骤2.1、内核工程的修改:通过在操作系统内核kernel目录下创建静化处理器子目录,编写内核配置菜单Kconfig文件,为静化处理器子系统提供一个被内核识别的配置选项;

步骤2.2、基本数据结构的增加和修改:为静化处理器子系统设置一个全局数据结构,该全局数据结构包括静化处理器位图mask、静化处理器计数number、以及具体处理器静化信息cpu_info,具体处理器静化信息cpu_info中存储每个处理器的静化状态;在进程数据结构task_struct中,添加表示静化处理器进程状态的数据结构quitecup_task_info;

步骤2.3、设置静化处理器,包括设置新的静化处理器和还原静化处理器,每次设置新的静化处理器时,要对静化处理器计数进行累计,若已存在的静化处理器数目等于操作系统中能用处理器-1时,终止增加新的静化处理器,在还原静化处理器时,减少静化处理器计数;所述的设置新的静化处理器,具体过程是:遍历操作系统中所有的进程,修改进程运行执行的处理器亲和性位图cpus_allowed,同时保存旧处理器亲和性位图;在该过程中,要判断获得的进程是否还存活,获得读写自旋锁tasklist_lock,保护以init_task为头节点的进程链表,修改处理器亲和性位图前释放读写自旋锁tasklist_lock,在处理器亲和性选项生效后对进程进行迁移;所述的还原静化处理器,具体过程是:先将静化处理器从静化处理器子系统的静化处理器位图中移除,再根据系统中可用的处理器位图判断当前要还原的静化处理器是否可用,如果该处理器可用,则将该当前要还原的静化处理器还原为正常模式的处理器;

步骤2.4、保护静化处理器不受影响:对于非静化处理器,避免将进程从静化处理器上迁移走,以及避免将进程迁移到静化处理器上;对于静化处理器,避免外部进程被迁移到静化处理器上,避免将进程从静化处理器上迁移走,以及避免激活本地的处理器平衡软中断。

2.根据权利要求1所述的一种面向多核处理器的操作系统噪声控制方法,其特征在于,步骤2.1所述的编写内核配置菜单Kconfig文件,为静化处理器子系统提供一个被内核识别的配置选项,具体是在内核配置菜单Kconfig文件中生成宏CONFIG_QUIETCPU,在内核Makefile文件中添加静化处理器子系统的目录。

3.根据权利要求1所述的一种面向多核处理器的操作系统噪声控制方法,其特征在于,步骤2.2所述的具体处理器静化信息cpu_info包括:表示该处理器是否已经被静化的数据项shield,以及该处理器是否锁定的数据项lock;所述的数据结构quitecup_task_info包含:保存正常设置处理器亲和性位图oldmask和表示具体处理器的静化信息的指针info,其中,指针info指向具体处理器静化信息cpu_info。

4.根据权利要求1所述的一种面向多核处理器的操作系统噪声控制方法,其特征在于,步骤2.4所述的对于非静化处理器,避免将进程从静化处理器上迁移走,具体过程是:

在调度域上根据函数load_balance中的变量cpus,寻找任务最频繁的队列,若该队列所在的处理器为静化处理器,则做如下操作:(1)设置函数load_balance中的all_pinned标志;(2)将该处理器从cpus位图中移出;(3)如果cpus位图为空,从函数load_balance中退出,否则重新寻找繁忙的就绪队列。

5.根据权利要求1所述的一种面向多核处理器的操作系统噪声控制方法,其特征在于,步骤2.4所述的对于非静化处理器,避免将进程迁移到静化处理器上,具体过程是:遍历调度域中的所有处理器,根据操作系统函数sched_balance_self返回最空闲的处理器,若返回的最空闲的处理器被静化,则跳过该处理器,检查下一个。

6.根据权利要求1所述的一种面向多核处理器的操作系统噪声控制方法,其特征在于,步骤2.4所述的对于静化处理器,避免外部进程被迁移到静化处理器上,具体方法是:

如果当前处理器的本地运行队列中没有能运行的进程存在,通过函数schedule调用函数idle_balance,从另外一个运行队列迁移进程到本地运行队列中,如果当前处理器是静化处理器,函数idle_balance直接返回。

7.根据权利要求1所述的一种面向多核处理器的操作系统噪声控制方法,其特征在于,步骤2.4所述的对于静化处理器,避免将进程从静化处理器上迁移走,具体方法是:在进程刚创建的时候,用exec系统调用启动一个新进程时,调度器将跨越处理器移动该进程,exec系统调用会调用挂钩函数sched_exec,挂钩函数sched_exec中调用函数sched_balance_self挑选当前负荷最少,且进程能被允许在该处理器上运行的目标处理器,在函数sched_balance_self中,添加目标处理器的判断,如果目标处理器是静化处理器,则直接返回,否则正常执行后续的平衡操作。

8.根据权利要求1所述的一种面向多核处理器的操作系统噪声控制方法,其特征在于,步骤2.4所述的对于静化处理器,避免激活本地的处理器平衡软中断,具体方法是:在函数scheduler_tick中激活任务平衡软中断之前,判断当前处理器是否是静化处理器,如果是直接返回,否则正常激活软中断程序。

说明书 :

一种面向多核处理器的操作系统噪声控制方法

技术领域

[0001] 本发明涉及操作系统和程序分析领域,具体涉及一种面向多核处理器的操作系统噪声控制方法。

背景技术

[0002] 传统的程序优化思路是:通过程序剖析(Profile)寻找程序的性能瓶颈(如Cache失效、负载失衡、资源竞争等),再对代码结构进行重新组织来解决问题。
[0003] 但是近年来的研究显示,伴随着硬件性能的提升,特别是系统中可用处理器数目的增加和网络连接速度提高,操作系统本身正在逐渐成为应用程序性能提升的障碍。原本操作系统中的一些正常活动,有可能成为导致应用程序性能下降的有害“噪声”。一些应用程序的关键代码,会由于操作系统活动的影响,其运行时间将出现经常性波动。操作系统噪声是指操作系统活动对应用程序执行流的中断,如图1所示为操作系统噪声示意图。由于引发干涉的操作系统噪声是正常的系统活动,并且是通过应用程序的运行间接起作用的,操作系统噪声问题在被发现后的很长一段时间内并未引起广泛的关注。直到最近,高性能计算领域集群的使用越来越普遍,规模也不断扩大,但是集群的性能扩展性却遭遇瓶颈,操作系统噪声问题才重新被重视。并随着商用计算机硬件设备的升级更新,原本高性能领域使用的多处理器平台、高速连接设备正在逐渐向中低端应用普及,这也带来操作系统噪声问题影响范围的扩大。
[0004] 操作系统噪声问题目前在高性能计算领域表现的比较突出,因为高性能并行计算程序多数由一系列计算和同步阶段组成,考虑每个进程运行在不同操作系统上,如图1所示,在不同进程的不同计算阶段发生操作系统噪声,整个并行程序的执行时间就增加。
[0005] 我们的环境资源正在日益紧缺,而伴随操作系统噪声问题的,实际上是能源的无意义的损耗,这和我们所追求的绿色计算的目标是格格不入的。因此,对操作系统噪声的控制方法的研究显得越来越重要。在FastOS(Forum to Address Scalable Technology for runtimeand Operating Systems)支持的10个项目中,8个项目将操作系统噪声列为待解决的问题。
[0006] 由于内核活动占总操作系统噪声比例的66%,而内核中重要的噪声来源是时钟中断(tick),所以关于操作系统噪声的抑制和消除方法的研究主要集中在时钟中断(tick)的处理方面。
[0007] Ronald Mraz采用的方法是提高应用程序相对守护进程的权限,同步所有节点的时钟。Dan Tsafrir等人否定了对全局时钟进行同步的解决方案,说明了同步全局时钟在大规模集群中实现困难,并且会带来额外的性能开销。另外即使全局时钟同步,本地的时钟中断依然会带来间接影响。根本的方法是消除时钟中断。Tsafrir指出,消除时钟中断的解决方案需要考虑解决方案本身是否具有域局限性(domain-specific),也就是说在集群下,一个域解决方案可能影响其他域的情况。Tsafrir提到了几个实例:同步全局时钟的方法,带来的额外性能损耗;采用实时系统的单次触发(one-shot)的方法,不适合可能在一个纳秒(ns)级别引发大量事件的通用操作系统;软时钟的方法,实际基于扩展了时钟中断机制;节能的时钟降低时钟中断方法,噪声在系统非空闲状态依然存在。
[0008] Tsafrir等人提出了智能时钟(smart-tick)的概念,建议使用智能时钟(smart tick),进行事件合并,减少时钟中断。
[0009] Ferreira等人认为时钟中断是Linux上操作系统噪声的主要来源,通过实现动态时钟(tickless)解决噪声问题。但噪声问题并不因此完全被解决,在大规模并行处理系统(MPP)上,相比集群系统会增加一个心跳线的机制,而心跳线的特征同时钟中断十分相似。他们对系统服务设计的建议是,将系统服务拆分成更小,更频繁运行的任务。他们认为之前许多设计者采用了相反的思路——将周期性服务设计成周期更长,更少中断,可能对微观测试基准很有效,但是可能带来实际应用程序的性能下降。所以Ferreira强调使用实际的应用程序来评测性能。
[0010] 开源High Res POSIX timers项目,包括了Linux内核的Tickless补丁。但是Linux内核的研究人员Christopher Lameter认为现在的动态时钟实现并不能称的上名副其实。Tickless系统只在处理器空闲的时候起作用,而时钟中断仍然在多进程争用处理器的时候起作用,即用于时间片检查。
[0011] 另外,Lameter还对抑制非时钟中断导致操作系统噪声提出了建议,如采用cache感知的调度算法,或者对多处理器系统中CPUO的工作进行特别调度:CPUO负责更新系统时间;时间敏感的程序不应该被调度到CPUO上;CPUO可以接管其他处理器的事务性工作,如管理调度队列和外设中断等。
[0012] 现有的减少操作系统噪声的基本方法主要有:1)限制守护进程的执行;2)限制硬件中断分发。但是这类操作系统噪声控制手段并不是特别针对操作系统噪声的,在面对操作系统噪声控制方面存在一些局限性。如修改启动脚本、守护进程在固定的处理器上运行,但是内核的任务平衡算法仍然在起作用,内核活动仍然会被调度到不同的处理器上,使得操作系统噪声控制不能很好实现。

发明内容

[0013] 本发明的目的是为了减少并行进程受到的操作系统噪声,提出一种面向多核处理器的操作系统噪声控制方法。基于隔离控制的方法,在Linux内核上实现,考虑多核环境下,并行应用程序由一组进程组成,每个进程运行在一个处理器核上,处理器核数目增加时,通过本发明实现的隔离控制方法可以在新增处理器核上减少并行进程受到的操作系统噪声,来实现性能优化。
[0014] 一种面向多核处理器的操作系统噪声控制方法,具体是:第一步、配置一套内核的控制接口,包括:
[0015] 步骤1.1、虚拟文件系统/proc接口初始化:首先创建静化处理器子系统的目录quietcpu,然后在目录quietcpu下为每个处理器创建各自的子目录以及控制项,最后为每个控制项注册相应的读写操作函数,并将操作系统中的数据结构proc_dir_entry中的参数data中存储的数据修改为指针形式的处理器编号;
[0016] 步骤1.2、访问虚拟文件系统/proc文件接口:当静化处理器子系统中的某个静化处理器的控制项文件中被写入数据时,写操作函数被调用,写操作函数从数据结构proc_dir_entry中的参数data中获得处理器的编号,再对写入的数据进行分析,在写入数据有效且写入的数据为非零值时,调用与从参数data中获得的处理器编号对应的静化处理器设置函数,若写入的数据为0,则恢复静化处理器到正常模式;从静化处理器子系统中的某个静化处理器的控制项文件读取数据时,读操作函数同样从data参数中取得处理器编号后,从静化处理器子系统获得对应处理器的静化状态;
[0017] 将操作系统中原函数set_cpus_allowed_ptr替换为带有静化处理器子系统标志的新函数_set_cpus_allowed,新函数较原函数增加了一个用于标志是否是来自处理器静化子系统调用的参数,对系统调用函数sched_setaffinity的实现进行修改,在修改进程与处理器的现有分配关系时会调用函数_set_cpus_allowed,通过使用taskset工具,先启动进程执行,再设置进程的亲和性属性,从而制定进程在静化处理器上运行;所述的进程的亲和性属性具体是通过调用新函数_set_cpus_allowed,修改位图cpus_allowed来设置的;
[0018] 第二步、设置支持静化控制的内核机制,包括:
[0019] 步骤2.1、内核工程的修改:通过在操作系统内核kernel目录下创建静化处理器子目录,编写内核配置菜单Kconfig文件,为静化处理器子系统提供一个被内核识别的配置选项;
[0020] 步骤2.2、基本数据结构的增加和修改:为静化处理器子系统设置一个全局数据结构,该全局数据结构包括静化处理器位图mask、静化处理器计数number、以及具体处理器静化信息cpu_info;在进程数据结构task_struct中,添加表示静化处理器进程状态的数据结构quitecup_task_info;
[0021] 步骤2.3、设置静化处理器,包括设置新的静化处理器和还原静化处理器,每次设置新的静化处理器时,要对静化处理器计数进行累计,若已存在的静化处理器数等于操作系统中能用处理器-1时,终止增加新的静化处理器,在解除处理器静化时,减少静化处理器计数;步骤2.4、保护静化处理器不受影响:对于非静化处理器,避免将进程从静化处理器上迁移走,以及避免将进程迁移到静化处理器上;对于静化处理器,避免外部进程被迁移到静化处理器上,避免将进程从静化处理器上迁移走,以及然后避免激活本地的处理器平衡软中断。
[0022] 本发明的优点与积极效果在于:(1)本发明的操作系统噪声控制方法可以不用重启地重新设置某些需要隔离的静化处理器,使这些处理器避免任务的再平衡,从而实现了对操作系统噪声的控制;(2)本发明的操作系统噪声控制方法给操作系统用户提供了良好的一致性体验。

附图说明

[0023] 图1是现有的操作系统噪声的示意图;
[0024] 图2是本发明的噪声控制方法的步骤流程图;
[0025] 图3是proc文件系统中的静化处理器的目录结构示意图;
[0026] 图4是静化处理器框架中的数据结构;
[0027] 图5是使用本发明噪声控制方法的操作系统噪声和与标准内核的操作系统噪声的最大延迟的对比示意图;
[0028] 图6是使用本发明噪声控制方法的操作系统噪声和与标准内核的操作系统噪声的平均延迟的对比示意图。

具体实施方式

[0029] 下面将结合附图和实施例对本发明作进一步的详细说明。
[0030] 本发明的噪声控制方法在对Linux内核中处理器隔离相关的机制进行比较分析的基础上,添加了一个新的静化处理器子系统(quietcpu)来抑制操作系统噪声在多处理器系统上的平衡现象。所述的静化处理器子系统是通过提供一个简单有效的配置接口,使得不用重启系统而能重新设置某些需要隔离的静化处理器,使这些处理器避免任务的再平衡,从而实现对操作系统噪声的控制。
[0031] 本发明的噪声控制方法,如图2所示,具体为如下步骤。
[0032] 第一步、设置一套内核的控制接口,通过该接口可以动态地设置静化处理器,并可以指定进程到静化处理器上运行。
[0033] 接口设计方面需要考虑和目前Linux操作系统接口的一致性。基本的设计思路如下:
[0034] ·使用虚拟文件系统/proc文件系统指定哪些处理器设置为静化处理器;
[0035] ·使用操作系统工具taskset指定哪些任务可以调度到静化处理器上;
[0036] ·内核调度进程运行到静化处理器上时,当发现处理器的亲和性位图上有该静化处理器时,则成功调度,否则调度失败。
[0037] 通过所述的内核控制接口,无论用户是否启用静化处理器子系统,工具taskset的结果都和标准版本相同,可以提供给操作系统用户良好的一致性体验。
[0038] 内核控制接口,具体是利用内核提供的相关机制将配置静化处理器的接口作为一个内核模块,集成到/proc文件系统中,通过下面三个步骤实现。
[0039] 步骤1.1、proc文件接口初始化。
[0040] 如图3所示,首先创建静化处理器子系统的目录quietcpu,然后在目录quietcpu下为每个处理器创建各自的子目录cpuX以及控制项quiet,最后为每个控制项注册相应的读写操作函数。本发明的操作系统噪声控制方法中,将数据结构proc_dir_entry中的参数data中存储指针形式的处理器编号,而不是存储原来指向额外数据区的指针,这样做是为了简化实现,避免额外的内存使用,后面提到的处理函数接收到的data参数实际为处理器编号而不是指针。所述的数据结构proc_dir_entry,它的主要成员是各种/proc文件系统操作的函数指针。
[0041] 步骤1.2、访问proc文件接口。
[0042] 当静化处理器X的控制项/proc/quietcpu/cpuX/quiet文件中被写入数据时,初始化时注册的写操作函数就被调用,写操作函数从data参数中获得处理器的编号,再对写入的数据进行分析,当写入数据有效,并为非零值时,调用从data参数中获得的相应的静化处理器设置函数。当写入的数据为0时,恢复静化处理器到正常模式。例如,用户可以在命令行下通过输出重定向功能修改控制项文件:
[0043] echo1>/proc/quietcpu/cpu1/quiet
[0044] echo0>/proc/quietcpu/cpu1/quiet
[0045] 命令echo是linux命令,默认将后面的内容输出到控制台上,后面跟重定向符“>”可将内容直接输出到文件中,上例是将“1”/“0”输出到静化处理器cpu1的控制项中。
[0046] 从/proc/quietcpu/cpuX/quiet文件读取数据时,初始化时注册的读操作函数就会被调用,读操作函数同样从data参数中取得处理器编号后,然后从静化处理器子系统获得对应处理器的静化状态,正常的处理器将缓冲区数据设置为0,静化处理器将缓冲区数据设置为1。
[0047] 步骤1.3、指定进程到静化处理器上运行。
[0048] 可以使用taskset工具,该工具的基本原理是先启动进程执行,再设置进程的亲和性属性。操作系统函数set_cpus_allowed_ptr是用于设置处理器可用性的,通过修改参数cpus_allowed来设置,参数cpus_allowed以位图形式描述可运行进程的处理器。设置处理器亲和性,通过系统调用上述函数set_cpus_allowed_ptr修改cpus_allowed实现。由于是来自静化处理器子系统外的调用,函数_set_cpus_allowed将在非静化的处理器集合中选取有效的处理器,这样在一组非静化处理器中选取静化处理器,一定会失败。本发明的噪声控制方法对系统调用函数sched_setaffinity的实现进行了修改,采用带有静化处理器子系统标志的_set_cpus_allowed函数替换原本的set_cpus_allowed_ptr函数。新函数_set_cpus_allowed较原函数set_cpus_allowed_ptr增加了一个用于标志是否是自处理器静化子系统的调用的参数。通过调用新函数_set_cpus_allowed,修改位图形式的cpus_allowed实现处理器亲和属性,这样使用taskset工具就可以自由的修改进程的处理器亲和性属性,从而制定进程在静化处理器上运行。所述的操作系统函数sched_setaffinity可用于修改进程与处理器的现有分配关系。所述的cpus_allowed表示的是进程的亲和性,即进程可以在哪些处理器上运行,而函数_set_cpus_allowed是通过修改cpus_allowed来指定进程可以在哪些处理器上运行的,而静化处理器本身就是为了只运行一些系统进程而不能将其他进程绑定到其上运行的,因此函数sched_setaffinity在修改进程与处理器的现有分配关系时会调用函数_set_cpus_allowed设置进程可运行在哪些处理器上,当指定进程运行在静化处理器时会出错,所以本发明要对函数sched_setaffinity进行修改,需要判断是否在一组非静化处理器中选取静化处理器,从而在调用函数_set_cpus_allowed时传递一个标志参数,表明是否来自处理器静化子系统的调用。
[0049] 第二步、设置支持静化控制的内核机制,主要包括:内核工程的修改、基本数据结构的增加和修改、设置新的静化处理器和保护静化处理器不受影响。
[0050] 步骤2.1、内核工程的修改。
[0051] 添加一个静化处理器子系统,需要在内核源代码树下添加新的目录,并且修改内核的Makefile文件。所述的Makefile文件是用于管理大规模工程的编译的规则文件。
[0052] 为方便用户选择,将静化处理器子系统实现为一个可选择的内核模块。在操作系统内核kernel目录下创建静化处理器子系统目录quietcpu,编写内核配置菜单Kconfig文件(kernel/quietcpu/Kconfig),为静化处理器子系统提供一个可被内核识别的配置选项。在内核配置菜单Kconfig文件中生成宏CONFIG_QUIETCPU:
[0053] config QUIETCPU
[0054] 在内核Makefile文件:$(srctree)/kernel/Makefile中,添加静化处理器子系统的目录:obj-$(CONFIG_QUIETCPU)+=quietcpu/后,内核编译工具就可以编译quietcpu目录下的源程序了。
[0055] 这样在具体的平台Kconfig文件,如$(srctree)/arch/mips/Kconfig中引用内核配置菜单Kconfig文件,CONFIG_QUIETCPU宏定义就在内核源代码中可以被操作系统识别了。
[0056] 例如在文件$(srctree)/arch/mips/Kconfig中,添加:
[0057] source“kernel/quietcpu/Kconfig”
[0058] 在编译过程中通过文件kernel/quietcpu/Kconfig中的config QUIETCPU语句生成指示内核编译工具去编译quietcpu目录下的源程序的宏。
[0059] 步骤2.2、基本数据结构的增加和修改,是指管理静化处理器子系统的全局数据结构的增加,以及进程数据结构的修改。
[0060] 静化处理器子系统设置一个全局描述符,管理静化处理器子系统的各个状态,包括静化处理器位图mask,静化处理器计数number,具体处理器静化信息cpu_info等。同时,需要扩展进程描述符task_struct,添加信息保存正常设置处理器亲和性位图oldmask和表示具体处理器的静化信息的指针info,其中只有运行在静化处理器上的进程,才有对应的静化处理器。
[0061] 如图4所示,总体结构quietcpu是一个全局数据结构,表示整个静化处理器子系统,结构中嵌入一个数据cpu_info存储每个处理器的静化状态,NR_CPU表示处理器的编号,具体处理器静化信息cpu_info中包括有表示该处理器是否已经被静化的数据项shield,以及该处理器是否锁定的数据项lock。判断一个处理器是否是静化处理器,从全局数据结构quietcpu中取得每个处理器的状态,查看所查询的处理器是否已经被静化。在进程数据结构task_struct中,添加表示静化处理器进程状态的数据结构quitecup_task_info,数据结构quitecup_task_info中包含:保存正常设置处理器亲和性位图oldmask和表示具体处理器的静化信息的指针info,指针info指向总体结构quietcpu中具体处理器静化信息cpu_info。
[0062] 步骤2.3、设置静化处理器。
[0063] 设置静化处理器的过程中,需要修改进程可用处理器。内核进程结构中的cpus_allowed位图形式描述可运行进程的处理器。操作系统内核中实现的set_cpus_allowed_ptr函数完成cpus_allowed的修改,但是本发明的噪声控制方法中的静化处理器功能需要判断可用处理器修改是否是来源于处理器静化子系统的调用,如果是,则拥有最大的自由度,可以直接修改cpus_allowed,否则,需要同静化处理器位图mask做一个按位与操作,再将新位图设置成cpus_allowed,同时保存最初始的亲和性设置到oldmask中,以便撤销静化操作时,进行还原。为次,本发明的噪声控制方法对原函数set_cpus_allowed_ptr作了修改,将该函数原先的内部实现移到新函数_set_cpus_allowed中,新函数较原函数增加了一个参数,标志是否是来自处理器静化子系统的调用,在这个过程中保存进程旧的处理器亲和性位图。
[0064] 1)设置新的静化处理器。
[0065] 遍历系统中所有的进程,修改程序运行执行的处理器亲和性位图cpus_allowed,同时将旧位图保留。在该过程中,需要判断获得的进程是否还存活alive;获得读写自旋锁tasklist_lock,保护以init_task为头节点的进程链表;修改设置位图前需要释放tasklist_lock,设置过程可能需要对进程进行迁移,过程中可能需要访问tasklist_lock;处理器亲和性选项生效之后,内核将对进程进行迁移。
[0066] 2)还原静化处理器。
[0067] 先将静化处理器从静化处理器子系统的静化处理器位图mask中移除,然后取得系统中可用的处理器位图,最终还原静化处理器为正常模式的处理器。具体在操作系统中,将静化处理器从静化处理器子系统的静化处理器位图中移除的函数如下:
[0068] cpus_complement(unshielded,asmp_descr.mask);
[0069] 函数cpus_complement中,asmp_descr.mask的值是被静化的处理器位图,该函数执行的操作是:变量unshieded=~asmp_descr.mask,执行后变量unshielded的值是没被静化的处理器位图。根据可用的处理器位图还原静化处理器,其函数如下:
[0070] cpus_and(unshielded,unshielded,cpu_online_map);
[0071] 函数cpus_and中,第二项的变量unshielded的值都是函数cpus_complement执行后的变量unshielded的值,cpu_online_map是内核中在线的处理位图,执行的操作是:第一项变量unshielded=unshieded&cpu_online_map,执行后第一项变量unshielded的值就是还原静化处理后的处理器位图了。
[0072] 在可用的处理器位图中修改,如果该处理器是可用的则还原为正常模式的处理器,否则为不可用的处理器。
[0073] 处理器静化子系统的一个核心问题是修改进程的处理器亲和性位图,而进程的运行至少且必须有一个处理器,因此处理器静化子系统不允许将系统中的所有处理器都设置成静化状态。设置静化处理器时,需要进行一个静化处理器计数,每次增加静化处理器都需要对计数进行累加,若内核中已存在的静化处理器数等于系统中可用处理器-1时,终止新的静化处理器设置;在解除处理器静化时,减少静化处理器计数。此外,在计数时还要注意考虑静化处理器重复设置和移除的情况。
[0074] 步骤2.4、保护静化处理器不受影响。
[0075] 由调度域的标志位flags可知,系统中有几个时机会进行进程迁移。
[0076] 本发明的噪声控制方法中的静化处理器的功能需要对所有进程迁移情况都进行考虑,才能保证静化处理器上应用程序不受操作系统噪声干涉。下面将从非静化处理器和静化处理器两个角度出发,说明保护静化处理器不受影响的具体实现方式。
[0077] 针对非静化处理器,首先避免将进程从静化处理器上迁移走。
[0078] 系统负载均衡函数load_balance在软中断中被执行,该函数首先调用函数cpumask_setall(cpus),将所有的处理器cpu在变量cpus中置位,即将cpus位图中的nr_cpumask_bits位都设置上,变量cpus的每一位表示一个处理器,开始时将系统中所有可用的处理器的相应位都置上位,而nr_cpumask_bits在内核中被宏定义为nr_cpu_ids,nr_cpu_ids为系统的处理器数,变量possible_cpus会更改变量nr_cpu_ids的数值。在调度域上根据变量cpus,寻找任务最频繁的队列,若该队列所在的处理器启用静化功能,则做如下操作:
[0079] ·相当于该队列上的所有进程都处于绑定状态,通过设置load_balance函数中的all_pinned标志,使该队列上的所有进程都处于绑定状态;
[0080] ·将该处理器从cpus位图中移出;
[0081] ·之后如果cpus位图为空,则从函数load_balance中退出,否则重新寻找繁忙的就绪队列。
[0082] 当处理器被设置为静化处理器时,需要将该处理器上运行的进程迁移到其它非静化处理器上。
[0083] 其次避免非静化处理器将进程迁移到静化处理器上。根据操作系统函数sched_balance_self返回最空闲的处理器,遍历调度域中的所有处理器,发现最空闲的处理器如果被静化,则跳过该处理器,检查下一个。
[0084] 针对静化处理器,首先避免外部进程被迁移到静化处理器上。
[0085] 如果静化处理器的运行队列中没有可运行的进程存在,从另外一个运行队列迁移一些可运行进程到本地运行队列中,具体是通过函数schedule调用函数idle_balance来实现。
[0086] 如果一个处理器进入了空闲(IDLE)状态,并且它所属的调度域(domain)设置了SD_BALANCE_NEWIDLE标志,则马上就会进行负载平衡(balance),把忙的处理器上的进程迁移过来,从而最大的发挥多处理器的优势。
[0087] 函数idle_balance中,如果当前处理器是被静化的,则直接返回,如果不是,继续执行。
[0088] 其次避免将进程从静化处理器上迁移走。
[0089] 在进程刚创建的时候,用exec系统调用启动一个新进程时,调度器将跨越处理器移动该进程。exec系统调用会调用挂钩函数sched_exec,挂钩函数sched_exec中调用函数sched_balance_self挑选当前负荷最少,且进程能被允许在该处理器上运行的处理器。如果不是当前处理器,那么会使用sched_migrate_task,向迁移线程发送一个迁移请求。
[0090] 在函数sched_balance_self中,需要添加目标处理器的判断,如果目标处理器是被静化的,是则直接返回,否则正常执行后续的平衡操作。
[0091] 然后避免激活本地的处理器平衡软中断。
[0092] 在Linux操作系统2.6的早期版本内核中,任务平衡算法被实现在时钟中断函数里,而在Linux操作系统2.6.28版本以后的内核中,任务平衡算法被移至软中断处理例程中执行,软中断中调用函数rebalance_domains中再调用函数load_balance。
[0093] 在函数scheduler_tick()中激活任务平衡软中断之前,需要判断当前处理器是否是静化处理器,是则返回,否则正常激活软中断程序。所述的函数scheduler_tick()在时钟中断处理程序中被调用,函数scheduler_tick()更新当前进程的时间片time_slice;并根据所分配的时间片time_slice的使用情况是剩余还是耗尽,来做进一步处理。
[0094] 为了对本发明的面向多核的操作系统噪声控制方法的噪声控制效果进行测试,在IBMx3500服务器上,使用本发明方法,将1号到3号处理器设置为静化处理器。然后,使用taskset命令接口运行针对串行应用的操作系统噪声度量工具来对启用静化处理器功能后的操作系统噪声控制效果进行测试。
[0095] 如图5和图6所示,是IBM x3500服务器上开启静化处理器子系统前后的实验结果中的最大延迟和平均延迟的数据对比图。竖轴表示延迟的大小,单位为us。
[0096] 在该实验中,打开静化功能的1号、2号、3号处理器上的操作系统噪声的最大延迟和平均延迟均发生了下降,由于没有对0号处理器实施特殊的控制,因此被静化处理器排除的系统任务就被集中在0号处理器上运行,表现为图6中在0号处理器上测量到的操作系统噪声平均延迟较开启静化功能前略有增加。
[0097] 由图5中可以看出,使用本发明方法操作系统噪声的最大延迟下降了50%左右。由图6中可以看出,使用本发明方法操作系统噪声平均延迟下降10%左右(0.1us)。由此说明本发明的控制方法确实有效的减少了多核系统上的操作系统噪声。