linux线程调度策略
linux线程调度策略这是一篇非常好的关于线程调度的资料,翻译自shed 目录
从Linux 2.6.23开始,默认的调度器为CFS,即"完全公平调度器"(Completely Fair Scheduler)。CFS调度器取代了之前的"O(1)"调度器。 CFS的实现细节可以参见sched-design-CFS。cgroup的CPU调度也属于CFS扩展的一部分。 Scheduling policies内核模块使用调度器来决定下一个CPU时钟周期执行的线程。每个线程都包含一个调度策略以及一个静态的调度优先级 对于使用普通调度策略(SCHED_OTHER,SCHED_IDLE,SCHED_BATCH)的线程来说, 对于使用实时策略(SCHED_FIFO,SCHED_RR)的进程,其 调度器会为每个 线程的调度策略决定了如何根据静态优先级来将一个线程插入到同静态优先级的线程列表(list of runnable threads)中,以及如何在该列表中调整线程的位置。 所有的调度都具有抢占性:如果一个具有更高静态优先级的线程准备运行,当前运行的线程会被抢占并返回到其静态优先级对应的等待列表中。调度策略仅根据具有相同静态优先级的可运行线程列表来决定调度顺序。 进程调度中使用了2个队列:进程一开始会进入ready队列等待调度;当进程执行中遇到I/O阻塞,等待子进程结束或软中断等原因会进入wait队列,等阻塞结束后会返回到ready队列 SCHED_FIFO: First in-first out scheduling(实时线程)SCHED_FIFO仅适用于静态优先级大于0的线程,即当一个SCHED_FIFO的线程变为可运行(runnable)状态时,它会立即抢占所有当前运行的SCHED_OTHER,SCHED_BATCH或SCHED_IDLE 线程。SCHED_FIFO不使用时间片进行调度,所有使用SCHED_FIFO调度策略的线程应该遵守如下规则:
SCHED_FIFO 线程将会一直运行,直到被更高优先级的线程抢占,或调用了sched_yield(2) 。 SCHED_RR: Round-robin scheduling(轮询调度)SCHED_RR对SCHED_FIFO做了简单增强。除每个线程仅允许运行在一个最大时间段下外,SCHED_FIFO中的所有规则都适用于SCHED_RR。如果一个SCHED_RR线程已经运行了等于或大于该最大时间段时,该线程会被放置到其优先级列表的末尾。当一个SCHED_RR线程被更高优先级的线程抢占,并在后续恢复运行后,会在先前未过期的时间段下运行。最大时间段可以通过sched_rr_get_interval(2)获得。 SCHED_DEADLINE: Sporadic task model deadline scheduling3.14版本之后的Linux提供了一个新的调度策略SCHED_DEADLINE。该策略结合了GEDF(Global Earliest Deadline First)和 CBS (Constant Bandwidth Server)。必须通sched_setattr(2)和sched_getattr(2)来设置和获取该策略。 一个Sporadic task被定义为一系列任务,且每个任务每次仅激活一次。每个任务都有一个
当使用sched_setattr(2)给一个线程设置SCHED_DEADLINE 策略时,可以设置3个参数:
3个deadline调度参数对应 内核要求:
此外,在当前实现中,所有参数的值至少为1024(即,大于1微秒),小于2^63。如果有效性校验失败,sched_setattr(2)返回EINVAL错误。 CBS通过阻止线程超出其运行时间 为了确保deadline调度,当SCHED_DEADLINE线程在给定的条件下不可运行时,此时内核必须阻止这些线程的运行。内核必须在设置或修改SCHED_DEADLINE策略和属性时执行准入测试。准入测试用于计算这些修改是否可行,如果不可行,sched_setattr(2)将返回EBUSY错误。 例如,总的CPU利用率应该小于或等于总的可用的CPU。由于每个线程可以在每个 为了满足SCHED_DEADLINE的条件,使用SCHED_DEADLINE策略的线程的优先级是系统中最高的。当一个SCHED_DEADLINE线程运行时,该线程会抢占其他策略下调度的线程。 对SCHED_DEADLINE策略调度的线程调用fork(2)会返回EAGAIN错误(除非该线程设置了reset-on-fork标记)。 当一个SCHED_DEADLINE线程调用了sched_yield(2)将会停止当前任务,并等待新的周期。 SCHED_OTHER: Default Linux time-sharing scheduling(默认策略)SCHED_OTHER只能在静态优先级为0时使用(普通线程)。SCHED_OTHER是标准的Linux分时调度策略(不需要实时机制)。 如何从静态优先级为0的列表中选择运行的线程取决于列表中的 在Linux内核源码中,SCHED_OTHER被称为SCHED_NORMAL。 The nice valuenice值用于影响CPU调度器对进程的调度偏好。适用于SCHED_OTHER和SCHED_BATCH调度处理。可以通过nice(2),setpriority(2)或sched_setattr(2)修改nice值。 根据POSIX.1,nice值是一个单进程属性,即进程中的所有线程共享一个nice值。然而,在Linux中,nice值是一个单线程属性,相同进程中的不同线程可能使用不同的nice值。 nice值的取值范围根据UNIX系统的不同而不同。在现代Linux系统中,取值为-20(高优先级)到+19(低优先级),而一些系统中的取值为-20..20。在一些非常早期的Linux 内核(Linux 2.0之前)中的取值为-infinity..15。 nice值对相应的SCHED_OTHER 进程的影响根据UNIX系统和Linux内核版本的不同而不同。 2.6.23版本的Linux内核中引入了CFS调度,并采用了一种能根据nice的差值产生更显著影响的算法。在当前的实现下,两个进程的nice差值中,每单位的nice差值对CFS调度的影响因子为1.25 (参见how-is-nice-working,CFS根据虚拟时间进行CPU调度: Linux系统可以使用RLIMIT_NICE资源来限制非特权进程的nice值的上限,参见setrlimit(2)。 更多nice值的用法,参见下面的autogroup。 SCHED_BATCH: Scheduling batch processes从Linux 2.6.16开始,SCHED_BATCH可以用于静态优先级为0的线程。该策略类似SCHED_OTHER,并根据动态优先级(nice值)进行调度。区别是使用该策略时,调度器会假设线程是CPU密集型的,因此,该调度器会根据线程的唤醒行为施加调度惩罚,因此这种调度策略比较不受欢迎。 该策略比较适用于非交互且不期望降低nice值的负载,以及需要不因为交互而(在负载之间)造成额外抢占的调度策略的负载。下面引用自PHP-FPM on Linux,SCHED_BATCH or SCHED_OTHER?,更多参见[batch/idle priority scheduling,SCHED_BATCH](batch/idle priority scheduling,SCHED_BATCH)
SCHED_IDLE: Scheduling very low priority jobs从Linux 2.6.23开始,SCHED_IDLE可以用于静态优先级为0的线程。nice值不会影响该策略。 该策略用于运行非常低优先级的任务(低于nice值为+19的SCHED_OTHER或SCHED_BATCH策略)。 Resetting scheduling policy for child processes每个线程都有一个reset-on-fork调度标识。当设置该标识后,使用fork(2)创建的子进程不会继承特权调度策略。可以通过如下方式设置reset-on-fork:
注意上面两个函数的常量名称不一样。使用sched_getscheduler(2)和sched_getattr(2)获取reset-on-fork状态的用法与上面类似。 reset-on-fork特性用于媒体播放的应用,可以防止应用在创建多个子进程时规避RLIMIT_RTTIME设置的资源限制。 更精确地讲,如果设置了reset-on-fork,后续创建地子进程会遵循下面规则:
在设置reset-on-fork之后,只有线程拥有CAP_SYS_NICE的capability时才能重置reset-on-fork。使用fork(2)创建的子进程会disable reset-on-fork标识。 Privileges and resource limits在Linux 2.6.12之前,只有拥有特权(CAP_SYS_NICE)的线程才能设置非0的静态优先级(即设置实时调度策略)。后续版本对如下实现进行了修改:非特权的线程仅在调用者的effective user ID(EID)与目标线程的real或effective user ID相同的情况下才能且仅能设置SCHED_OTHER策略。 为了设置或修改SCHED_DEADLINE策略。线程必须是特权(CAP_SYS_NICE)的。 从Linux 2.6.12开始,RLIMIT_RTPRIO(可以使用ulimit -e设置)资源限制定义了非特权线程设置SCHED_RR 和SCHED_FIFIO策略的静态优先级的上限。修改调度策略和优先级的规则如下:
特权(CAP_SYS_NICE)线程会忽略RLIMIT_RTPRIO限制。在一些老的内核中,特权线程可以任意修改策略和优先级。参见 getrlimit(2)获取更多信息。 Limiting the CPU usage of real-time and deadline processes(限制实时进程或deadline进程)SCHED_FIFO,SCHED_RR或SCHED_DEADLINE策略下调度的线程中的非阻塞无限循环处理可能会阻塞其他线程获取CPU。在Linux 2.6.25之前,阻止实时进程冻结系统的唯一方式是通过shell启动一个静态优先级更高的程序,如通过这种方式来停止实施程序,并释放CPU资源。 从Linux 2.6.25开始,引进了其他技术手段来处理实时(SCHED_FIFO,SCHED_RR)和deadline(SCHED_DEADLINE)进程。一种方式是通过RLIMIT_RTTIME 来限制实时进程可能使用到的CPU的上限。参见 getrlimit(2)获取更多信息。 从Linux 2.6.25开始,Linux提供了2个
Response time一个阻塞的高优先级的线程(在调度前)等待I/O时会有一个确定的响应时间。设备驱动作者可以使用"slow interrupt"中断句柄来减少响应时间 Miscellaneous子进程会通过fork(2)继承调度策略和参数。可以使用execve(2)来保存调度策略和参数。 实时进程通常会使用memory locking特性来防止内存页的延迟。可以使用mlock(2) 或mlockall(2)设置memory locking。 The autogroup feature从Linux 2.6.38开始,内核提供了一种被称为autogrouping的特性来为多进程和CPU密集型负载(如Linux内核中的大量并行进程)提升交互式桌面性能。 该特性结合CFS调度策略,需要内核设置CONFIG_SCHED_AUTOGROUP。在一个运行的系统中,该特性可以通过文件 当通过setsid(2) (setsid会将一个进程脱离父进程)创建一个新的会话时会创建一个新的autogroup,这种情况可能发生在一个新的终端窗口启动时。使用fork(2)创建的进程会继承父辈的autogroup成员。因此,一个会话中的所有进程都属于同一个autogroup。当最后一个进程结束后,autogroup会被自动销毁。 当使能autogrouping时,一个autogroup中的所有成员都属于同一个内核调度器"任务组"。CFS调度器使用了在任务组间均衡分配CPU时钟周期的算法。可以使用下面例子进行展示提升交互式桌面性能的好处。 假设有2个竞争相同CPU的autogroup(即,单核系统或使用taskset设置所有SMP系统的进程使用相同的CPU),第一个group包含10个用于构建内核的CPU密集型进程 进程的autogroup成员可以通过
该文件可以通过为autogroup设置 autogroup的nice值的意义与进程的nice值意义相同,区别是前者为将autogroup作为一个整体,并基于相对其他autogroups设置的nice值来分配CPU时钟周期。对于一个autogroup内的进程,其CPU时钟周期为autogroup(相对于其他autogroups)的nice值和进程的nice值(相对于其他进程)的产物(即首先根据autogroup的nice值计算该autogroup所占用的CPU,然后根据进程的nice值计算该进程所占用的(属于其autogroup的)CPU)。 可以使用cgroups(7) CPU控制器来设置(非root CPU cgroup的)cgroups中的进程所占用的CPU,该设置会覆盖掉autogrouping。 所有的cgroup都由可选择的内核配置CONFIG_CGROUPS控制。在Linux 3.2引入了CPU带宽控制(bandwidth control)。cgroup对CFS的扩展有如下三种:
可以用如下方式查看是否启用了cgroup
autogroup特性仅用于非实时调度策略(SCHED_OTHER,SCHED_BATCH和SCHED_IDLE)。它不会为实时和deadline策略分组。 The nice value and group scheduling当调度非实时进程时,CFS调度器会使用一种称为"group scheduling"的技术(如果内核设置了CONFIG_FAIR_GROUP_SCHED 选项) 在group scheduling下,进程以"任务组"方式进行调度。任务组间有继承关系,会继承系统上被称为"root任务组"的初始化任务组。任务组遵循以下条件(按顺序):
在group调度下,线程的nice值仅会影响到相同任务组的其他线程的调度。这会在一些使用传统nice语义的UNIX系统上会导致惊人的后果。实践中,如果使能了autogrouping,则会使用setpriority(2)或nice(1)来影响相同会话(通常为相同的终端窗口)中的一个进程相对于其他进程的调度。 相反的,对于不同会话(如,不同的终端窗口,这些任务都绑定到不同的autogroups)中绑定了唯一的CPU的2个进程,修改一个会话中的进程的nice值不会影响其他会话中的进程的调度。使用如下命令可以修改一个终端会话中所有进程对于的autogroup nice值。
autogroup和进程都有一个nice值,autogroup的nice值用于在autogroup之间分配CPU;autogroup内的进程的nice值用于在进程间分配autogroup的CPU。cgroup的配置会覆盖autogroup Real-time features in the mainline Linux kernel从Linux 2.6.18开始,Linux逐渐具备实时功能,其中大部分来源于
可以从这里下载。 如果没有补丁且在这些补丁完全合并到主线之前的内核提供了3中抢占类,CONFIG_PREEMPT_NONE,CONFIG_PREEMPT_VOLUNTARY和CONFIG_PREEMPT_DESKTOP,分别表示没有,部分,和考虑降低最坏情况下的调度延迟。 如果没有补丁且在这些补丁完全合并到主线之前的内核还提供了额外的配置表项CONFIG_PREEMPT_RT,如果选择该表项,Linux会转变为正式的实时操作系统。FIFO和RR调度策略会用于运行具有实时优先级且最小调度延迟的线程。 TIPS:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 如何为每个新创建的Linux用户设置默认值?
- linux – Pycharm tensorflow ImportError但可以正常使用Te
- linux – 如何使用hdparm来修复挂起的扇区?
- linux – Jenkins可以根据代理操作系统有条件地执行shell或
- 有关Linux支持的最佳ThinkPad是什么?
- linux – RHEL / CentOS 6.x中的XFS文件系统坏了 – 我该怎
- 跟踪我花多少时间编程(在Linux中,特别是Emacs)
- linux – 为什么chmod在递归运行时会给出“没有这样的文件或
- Vi键在Xcode
- Operating.System.Concepts.10th.Edition中文翻译