多核CPU现在很常见,那么问题来了,一个程序在运行时,只在一个CPU核上运行?还是交替在多个CPU核上运行呢?LINUX内核是如何在多核间调度进程的呢?又是内核又是CPU核,两个核有点绕,下面称CPU处理器来代替CPU核。
实际上,如果你没有对你的进程做过特殊处理的话,LINUX内核是有可能把它放到多个CPU处理器上运行的,这是内核的负载均衡。上文说过,每个处理器上有一个runqueue队列,表示这颗处理器上处于run状态的进程链表,在多处理器的内核中,就会有多个runqueue,而如果他们的大小很不均衡,就会触发内核的load_balance函数。这个函数会把某个CPU处理器上过多的进程移到runqueue元素相对少的CPU处理器上。
举个例子来简单说明这个过程吧。当我们刚fork出一个子进程时,子进程也还在当前CPU处理器的runqueue里,它与父进程均分父进程的时间片。当然,时间片与多处理器间的负载均衡没有关系。假设我们的系统是双核的,父进程运行在cpu0上,那么这个fork出来的进程也是在cpu0的runqueue中。
那么,什么时候会发生负载均衡呢?
1、当cpu1上的runqueue里一个可运行进程都没有的时候。这点很好理解,cpu1无事可作了,这时在cpu1上会调用load_balance,发现在cpu0上还有许多进程等待运行,那么它会从cpu0上的可运行进程里找到优先级最高的进程,拿到自己的runqueue里开始执行。
2、第1种情形不适用于运行队列一直不为空的情况。例如,cpu0上一直有10个可运行进程,cpu1上一直有1个可运行进程,显然,cpu0上的进程们得到了不公平的对待,它们拿到cpu的时间要小得多,第1种情形下的load_balance也一直不会调用。所以,实际上,每经过一个时钟节拍,内核会调用scheduler_tick函数,而这个函数会做许多事,例如减少当前正在执行的进程的时间片,在函数结尾处则会调用rebalance_tick函数。rebalance_tick函数决定以什么样的频率执行负载均衡。
static void rebalance_tick(int this_cpu, runqueue_t *this_rq,
enum idle_type idle)
{
unsigned long old_load, this_load;
unsigned long j = jiffies + CPU_OFFSET(this_cpu);
struct sched_domain *sd;
/* Update our load */
old_load = this_rq->cpu_load;
this_load = this_rq->nr_running * SCHED_LOAD_SCALE;
/*
* Round up the averaging division if load is increasing. This
* prevents us from getting stuck on 9 if the load is 10, for
* example.
*/
if (this_load > old_load)
old_load++;
this_rq->cpu_load = (old_load + this_load) / 2;
for_each_domain(this_cpu, sd) {
unsigned long interval;
if (!(sd->flags & SD_LOAD_BALANCE))
continue;
interval = sd->balance_interval;
if (idle != SCHED_IDLE)
interval *= sd->busy_factor;
/* scale ms to jiffies */
interval = msecs_to_jiffies(interval);
if (unlikely(!interval))
interval = 1;
if (j - sd->last_balance >= interval) {
if (load_balance(this_cpu, this_rq, sd, idle)) {
/* We've pulled tasks over so no longer idle */
idle = NOT_IDLE;
}
sd->last_balance += interval;
}
}
}
当idle标志位是SCHED_IDLE时,表示当前CPU处理器空闲,就会以很高的频繁来调用load_balance(1、2个时钟节拍),反之表示当前CPU并不空闲,会以很低的频繁调用load_balance(10-100ms)。具体的数值要看上面的interval了。
当然,多核CPU也有许多种,例如INTEL的超线程技术,而LINUX内核对一个INTEL超线程CPU会看成多个不同的CPU处理器。
上面说过,如果你没有对你的进程做过特殊处理的话,LINUX内核是有可能把它放到多个CPU处理器上运行的,但是,有时我们如果希望我们的进程一直运行在某个CPU处理器上,可以做到吗?内核提供了这样的系统调用。系统调用sched_getaffinity会返回当前进程使用的cpu掩码,而sched_setaffinity则可以设定该进程只能在哪几颗cpu处理器上执行。当我们对某些进程有强烈的期待,或者想自己来考虑CPU间的负载均衡,可以这么试试哈。
分享到:
相关推荐
本文将深入探讨由裴颂文、宁静和张俊格等人提出的针对CPU-GPU异构多核系统的动态任务调度算法,该算法旨在解决负载均衡问题,提高系统效率。 首先,理解CPU-GPU异构计算系统的基本概念至关重要。CPU擅长于执行复杂...
Linux内核进程调度算法是操作系统设计的关键组成部分,它决定了系统如何高效地分配CPU时间给不同的进程,以确保系统的响应速度和整体性能。Linux内核从诞生至今,其进程调度算法经历了多次重大改进和发展,以适应...
Linux内核中的负载均衡算法负责在多核或多线程系统中分配任务,以确保所有处理器核心的工作负载平衡。在Linux 2.6及后续版本中,内核的调度器(scheduler)支持多种架构,包括CMP(Chip Multi-Processor)、CMT、SMP...
【标题】:“温度感知的Linux多核调度算法研究” 【摘要】:该研究探讨了针对多核处理器的温度感知Linux调度算法,旨在解决处理器温度上升对性能的影响。传统的硬件层面的动态热管理(DTM)机制虽然能降低功耗,但...
本章将涵盖Linux内核中的时钟源、定时器子系统以及调度算法的相关知识。时钟源如pit( Programmable Interval Timer)和hpet(High Precision Event Timer)为系统提供基本的时间基准。定时器子系统则负责管理和触发...
此外,随着多核处理器的发展,调度器的负载均衡问题变得更为复杂,如何有效地在多个处理器之间分配任务以保持系统整体性能的平衡是一个持续挑战。 综上所述,Linux内核调度器从2.4到2.6的演进,反映了操作系统设计...
数据包负载均衡是优化这类多核处理器性能的关键技术,它能确保工作负载均匀分布在各个核心上,避免单个核心过载,从而提高整体系统性能。 在Cavium多核处理器平台上,数据包负载均衡的实现方法通常涉及以下几个关键...
【基于异构多核处理器的高效任务调度算法】 在现代计算机系统中,异构多核处理器已经成为提升计算性能的关键技术。然而,如何有效地调度这些处理器上的任务以达到最佳性能是面临的一大挑战。针对这一问题,一种名为...
以上只是《深入理解Linux内核》第7章“进程调度”部分的一些基本知识点,实际内容可能还包括更多细节,如调度算法的具体实现、调度器的参数调整、以及与内存管理、I/O子系统等其他模块的交互。通过深入学习这一章,...
这类调度算法要考虑到处理器之间的负载均衡、通信开销以及并行执行的效率问题。 处理器调度算法的选择和实现直接影响着系统的响应时间、吞吐量和公平性。不同的调度策略适用于不同的应用场景。例如,批处理系统倾向...
在本文中,我们将深入探讨“Linux进程调度”这一主题,特别是O(1)调度算法,以及当前Linux内核所采用的调度策略。 首先,让我们了解什么是O(1)调度算法。在早期的Linux版本中,为了实现高效和快速的调度,设计了一...
CFS调度算法是从Linux 2.6.23内核到最新的 Linux 3.3.5内核中普通进程(采用SCHED_NORMAL调度策略)的默认调度算法。 CFS调度算法的主要思想是完全公平,不再跟踪进程的睡眠时间,也不再区分交互式进程。它将所有的...
实验结果显示,与Linux标准调度算法相比,该算法在各种负载组合下可以减少动态热管理操作的次数,降低幅度在9.6%至78.5%之间。同时,吞吐率平均提升了5.2%,最高提升可达9.7%,表明性能有显著改善。 实现方面,该...
5. `kernel`:核心的内核功能,如进程管理、内存管理和调度算法。 6. `include`:包含各种头文件,定义了内核API和数据结构。 7. `scripts`:用于配置和构建内核的脚本。 对于Android开发者来说,理解这些源代码是...
在IT领域,Linux内核是操作系统的核心,负责管理和协调计算机硬件资源,为各种应用程序提供服务。深入理解Linux内核对于系统管理员、软件开发者以及任何与Linux系统打交道的专业人士来说至关重要。本节我们将聚焦于...