通过之前的学习我知道了当前 Linux 系统下任务调度策略主要有三种:
1、SCHED_OTHER:普通任务调度策略。
2、SCHED_FIFO:实时任务调度策略,先到先服务。一旦占用cpu则一直运行,直到有更高优先级任务到达或自己放弃。
3、SCHED_RR:实时任务调度策略,时间片轮转。当任务的时间片用完,系统将重新分配时间片,并置于就绪队列尾。放在队列尾
保证了所有具有相同优先级的RR任务的调度公平。
Linux 提供的有关任务调度策略及优先级的接口函数:
1、
-
// 首先了解 sched_param 结构体
-
// In the current implementation, the structure contains only one field, sched_priority.
-
// The interpretation of param depends on the selected policy
-
-
struct sched_param
-
{
-
int sched_priority;
-
};
-
int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
-
-
int sched_getscheduler(pid_t pid);
The sched_setscheduler() system call sets both the scheduling policy and parameters for the thread whose ID is specified in pid.
If pid equals zero, the scheduling policy and parameters of the calling thread will be set.
The sched_getscheduler() returns the current scheduling policy of the thread identified by pid. If pid equals zero, the policy of the
calling thread will be retrieved.
与上面函数类似的还有:
-
int sched_setparam(pid_t pid, const struct sched_param *param);
-
-
int sched_getparam(pid_t pid, struct sched_param *param);
我们可以使用以下两个函数检测某个策略下优先级的取值范围。
-
int sched_get_priority_max(int policy);
-
-
int sched_get_priority_min(int policy);
对于 SCHED_OTHER 策略,sched_priority 只能为 0。对于 SCHED_FIFO,SCHED_RR 策略,sched_priority 从 1 到 99。
3、通过以下两个函数我们可以设置/查看线程的调度属性。
-
//调度属性结构体
-
struct sched_attr {
-
u32 size;
/* Size of this structure */
-
u32 sched_policy;
/* Policy (SCHED_*) */
-
u64 sched_flags;
/* Flags */
-
s32 sched_nice;
/* Nice value (SCHED_OTHER,
-
SCHED_BATCH) */
-
u32 sched_priority;
/* Static priority (SCHED_FIFO,
-
SCHED_RR) */
-
/* Remaining fields are for SCHED_DEADLINE */
-
u64 sched_runtime;
-
u64 sched_deadline;
-
u64 sched_period;
-
};
-
int sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags);
-
-
int sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags);
下面的 API 被更多使用:
4、初始化/销毁 struct pthread_attr_t
-
int pthread_attr_init(pthread_attr_t *attr);
-
-
int pthread_attr_destroy(pthread_attr_t *attr);
初始化后的 attr 默认使用 SCHED_OTHER 策略,优先级为 0。
5、设置/查看调度策略到 attr 里
-
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
-
-
int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
6、设置/查看调度优先级到 attr 里
-
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
-
-
int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);
7、继承调度属性 inheritsched。
-
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);
-
-
int pthread_attr_getinheritsched(pthread_attr_t *attr, int *inheritsched);
函数中inheritsched的取值为:PTHREAD_INHERIT_SCHED 或者 PTHREAD_EXPLICIT_SCHED。前者为继承创建线程的调度策
略和优先级,后者指定不继承调度策略和优先级,而是使用自己设置的调度策略和优先级。无论何时,当你需要控制一个线程的调
度策略或优先级时,必须将inheritsched属性设置为PTHREAD_EXPLICIT_SCHED。
8、动态设置/查看调度属性。
-
<span style=
"font-size:14px;">
int pthread_setschedparam(
pthread_t thread,
int policy,
const struct sched_param *param);
-
-
int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param);</span>
该方法下就不用调用函数来设置 inheritsched 属性了,因为
pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED) 函数设置的对象是pthread_attr_t !!!
注意使用 SCHED_RR 或 SCHED_FIFO 策略需要使用 sudo 权限运行程序才行。
注意:
1)调度策略和优先级是分开来描述的。前者使用预定义的SCHED_RR、SCHED_FIFO、SCHED_OTHER,后者是通过结果体
struct sched_param给出的。
2)这些设置调度策略和优先级的函数操作的对象是线程的属性pthread_attr_t(条款8除外),而不是直接来操作线程的调度策略和
优先级的。函数的第一个参数都是pthread_attr_t。
下面我们用代码检测下:
-
#include <pthread.h>
-
#include <unistd.h>
-
#include <stdio.h>
-
#include <assert.h>
-
-
void display()
-
{
-
sched_param param;
-
int policy;
-
-
pthread_getschedparam(pthread_self(), &policy, &m);
-
switch(policy)
-
{
-
case SCHED_RR:
-
printf(
"%X: policy:SCHED_RR priority:%d\n", pthread_self(), param.sched_priority);
-
break;
-
case SCHED_FIFO:
-
printf(
"%X: policy:SCHED_FIFO priority:%d\n", pthread_self(), param.sched_priority);
-
break;
-
case SCHED_OTHER:
-
printf(
"%X: policy:SCHED_OTHER priority:%d\n", pthread_self(), param.sched_priority);
-
break;
-
default:
-
printf(
"error\n");
-
}
-
}
-
-
void* fun(void *p)
-
{
-
display();
-
-
sched_param param;
-
param.sched_priority =
20;
-
//动态修改调度策略
-
pthread_setschedparam(pthread_self(), SCHED_FIFO, &m);
-
-
display();
-
}
-
-
int main()
-
{
-
pthread_t pid;
-
sched_param param;
-
int policy;
-
pthread_attr_t attr;
-
-
pthread_attr_init(&attr);
-
param.sched_priority =
10;
-
policy = SCHED_RR;
-
assert(pthread_attr_setschedpolicy(&attr, policy) ==
0);
-
assert(pthread_attr_setschedparam(&attr, &m) ==
0);
-
assert(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) ==
0);
-
-
assert(pthread_create(&pid, &attr, fun,
NULL) ==
0);
-
-
pthread_join(pid,
NULL);
-
pthread_attr_destroy(&attr);
-
-
return
0;
-
}
使用 sudo 运行后:
-
B75E8B40: policy:SCHED_RR priority:
10
-
B75E8B40: policy:SCHED_FIFO priority:
20
若我们不使用 sudo 运行,就会报错:
Assertion `pthread_create(&pid, &attr, fun, __null) == 0' failed.