sched_setscheduler() - Unix, Linux系统调用
广告
名称sched_setscheduler, sched_getscheduler - 设置和获取调度算法/参数概要
#include <sched.h>
int sched_setscheduler(pid_t pid, int policy,
const struct sched_param *param);
int sched_getscheduler(pid_t pid);
struct sched_param {
...
int sched_priority;
...
};
|
描述
sched_setscheduler() 设置进程(由pid标识)的调度策略和相关参数。如果pid等于零,则设置调用进程的调度程序。参数param的解释取决于所选策略。目前,Linux支持以下三种调度策略:SCHED_FIFO、SCHED_RR、SCHED_OTHER和SCHED_BATCH;它们的语义如下所述。
sched_getscheduler() 查询当前应用于进程(由pid标识)的调度策略。如果pid等于零,则检索调用进程的策略。 调度策略调度程序是内核的一部分,它决定哪个可运行进程将由CPU接下来执行。Linux调度程序提供三种不同的调度策略,一种用于普通进程,两种用于实时应用程序。一个静态优先级值sched_priority分配给每个进程,此值只能通过系统调用更改。从概念上讲,调度程序为每个可能的sched_priority值维护一个可运行进程列表,并且sched_priority的值范围为0到99。为了确定接下来运行的进程,Linux调度程序查找具有最高静态优先级的非空列表,并采用该列表开头的进程。调度策略决定每个进程在其具有相同静态优先级的进程列表中的插入位置以及在该列表中的移动方式。
SCHED_OTHER是大多数进程使用的默认通用时间共享调度策略。SCHED_BATCH适用于进程的“批处理”式执行。SCHED_FIFO和SCHED_RR适用于需要精确控制可运行进程执行选择方式的特殊时间关键型应用程序。 使用SCHED_OTHER或SCHED_BATCH调度的进程必须分配静态优先级0。在SCHED_FIFO或SCHED_RR下调度的进程可以具有1到99范围内的静态优先级。系统调用sched_get_priority_min()和sched_get_priority_max()可以用来以一种可移植的方式在所有符合POSIX.1-2001的系统上找出调度策略的有效优先级范围。 所有调度都是抢占式的:如果具有更高静态优先级的进程准备运行,则当前进程将被抢占并返回到其等待列表。调度策略仅决定具有相同静态优先级的可运行进程列表中的顺序。 SCHED_FIFO:先进先出调度
SCHED_FIFO只能与高于0的静态优先级一起使用,这意味着当SCHED_FIFO进程变为可运行时,它将始终立即抢占任何当前运行的SCHED_OTHER或SCHED_BATCH进程。SCHED_FIFO是一种简单的调度算法,没有时间切片。对于在SCHED_FIFO策略下调度的进程,将应用以下规则:被更高优先级的进程抢占的SCHED_FIFO进程将保留在其优先级的列表开头,并在所有更高优先级的进程再次阻塞后恢复执行。当SCHED_FIFO进程变为可运行时,它将插入到其优先级的列表末尾。调用sched_setscheduler()或sched_setparam()将把由pid标识的SCHED_FIFO(或SCHED_RR)进程放在列表的开头(如果它是可运行的)。因此,如果它具有相同的优先级,它可能会抢占当前正在运行的进程。(POSIX.1-2001规定进程应移到列表的末尾。)调用sched_yield()的进程将被放在列表的末尾。没有其他事件会移动在具有相同静态优先级的可运行进程的等待列表中按SCHED_FIFO策略调度的进程。SCHED_FIFO进程运行直到它被I/O请求阻塞,被更高优先级的进程抢占,或者它调用sched_yield()。SCHED_RR:循环轮询调度
SCHED_RR是对SCHED_FIFO的简单增强。上面对SCHED_FIFO的描述也适用于SCHED_RR,除了每个进程只允许运行最大时间量。如果SCHED_RR进程已经运行的时间段等于或长于时间量,它将被放在其优先级的列表末尾。被更高优先级的进程抢占并随后作为运行进程恢复执行的SCHED_RR进程将完成其循环轮询时间量的未到期部分。可以使用sched_rr_get_interval(2)检索时间量的长度。SCHED_OTHER:默认Linux时间共享调度
SCHED_OTHER只能在静态优先级0下使用。SCHED_OTHER是标准的Linux时间共享调度程序,它适用于所有不需要特殊静态优先级实时机制的进程。要运行的进程是从静态优先级0列表中选择的,该列表基于仅在此列表内确定的动态优先级。动态优先级基于优先级级别(由nice(2)或setpriority(2)设置),并且对于进程准备运行但被调度程序拒绝运行的每个时间量都会增加。这确保了所有SCHED_OTHER进程的公平进展。SCHED_BATCH:调度批处理进程(自Linux 2.6.16起。)SCHED_BATCH只能在静态优先级0下使用。此策略类似于SCHED_OTHER,但此策略将导致调度程序始终假设该进程是CPU密集型的。因此,调度程序将应用一个小调度惩罚,以便在调度决策中稍微不利于此进程。此策略对于非交互式的工作负载很有用,但不想降低其优先级值,以及对于想要确定性调度策略而无需交互导致额外抢占(工作负载的任务之间)的工作负载也很有用。权限和资源限制在2.6.12之前的Linux内核中,只有特权(CAP_SYS_NICE)进程才能设置非零静态优先级。非特权进程可以进行的唯一更改是设置SCHED_OTHER策略,这只有在sched_setscheduler()的调用者的有效用户ID与目标进程(即由pid指定的进程)的实际或有效用户ID匹配时才能进行,目标进程的策略正在更改。自Linux 2.6.12起,RLIMIT_RTPRIO资源限制定义了非特权进程对于SCHED_RR和SCHED_FIFO策略的优先级上限。如果非特权进程具有非零RLIMIT_RTPRIO软限制,则它可以更改其调度策略和优先级,但前提是优先级不能设置为高于RLIMIT_RTPRIO软限制的值。如果RLIMIT_RTPRIO软限制为0,则唯一允许的更改是降低优先级。在相同的规则下,另一个非特权进程也可以进行这些更改,只要进行更改的进程的有效用户ID与目标进程的实际或有效用户ID匹配即可。有关RLIMIT_RTPRIO的更多信息,请参见getrlimit(2)。特权(CAP_SYS_NICE)进程忽略此限制;与旧内核一样,它们可以对调度策略和优先级进行任意更改。 响应时间等待I/O的被阻塞的高优先级进程在再次调度之前有一定的响应时间。设备驱动程序编写者可以通过使用“慢中断”中断处理程序来大大减少此响应时间。其他子进程继承fork()中的调度算法和参数。调度算法和参数在execve(2)中保留。实时进程通常需要内存锁定以避免分页延迟,这可以使用mlock()或mlockall()来完成。 由于在SCHED_FIFO或SCHED_RR下调度的进程中的非阻塞无限循环将永远阻塞所有具有较低优先级的进程,因此软件开发人员应始终在控制台上保留一个在比被测应用程序更高的静态优先级下调度的shell。这将允许紧急终止未按预期阻塞或终止的被测实时应用程序。 在sched_setscheduler()和sched_getscheduler()可用的POSIX系统上,在<unistd.h>中定义了_POSIX_PRIORITY_SCHEDULING。 返回值成功时,sched_setscheduler()返回零。成功时,sched_getscheduler()返回进程的策略(一个非负整数)。出错时,返回-1,并适当地设置errno。错误
标签 | 描述 |
EINVAL | 调度策略不是已识别的策略之一,或者参数param对于策略没有意义。 |
EPERM | 调用进程没有相应的权限。 |
ESRCH | 找不到ID为pid的进程。 |
符合标准POSIX.1-2001。SCHED_BATCH策略是Linux特有的。注释标准Linux是一个通用的操作系统,可以处理后台进程、交互式应用程序和软实时应用程序(通常需要满足时限的应用程序)。本手册页针对的是这些类型的应用程序。标准Linux并非设计用于支持硬实时应用程序,即必须保证时限(通常远小于一秒)的应用程序,否则系统将灾难性地失败。与所有通用操作系统一样,Linux的设计目标是最大化平均性能而不是最差性能。Linux在中断处理方面的最差性能远低于其平均性能,其各种内核锁(例如用于SMP)会产生很长的最大等待时间,并且其许多性能改进技术通过增加最坏情况时间来减少平均时间。对于大多数情况,这就是您想要的,但是如果您确实正在开发硬实时应用程序,请考虑使用Linux的硬实时扩展,例如RTLinux(http://www.rtlinux.org)或RTAI(http://www.rtai.org),或者使用专门为硬实时应用程序设计的其他操作系统。 另请参见
Bill O. Gallmeister著,《面向现实世界的编程 - POSIX.4》,O’Reilly & Associates, Inc. 出版,ISBN 1-56592-074-0
广告
|