Linux实时调度策略:SCHED_FIFO、SCHED_RR和SCHED_DEADLINE设置示例
Contents
一、前言
Linux 支持多种任务调度策略(Scheduling Policy),其中:
- 普通任务(SCHED_NORMAL) 是普通分时调度;
- 实时任务(SCHED_FIFO、SCHED_RR、SCHED_DEADLINE) 适用于对响应延迟、执行周期有严格要求的系统(如工业控制、音视频处理等)。
二、实时调度策略简介
| 调度策略 | 类型 | 优先级范围 | 时间片机制 | 特点 | 典型应用 |
|---|---|---|---|---|---|
| SCHED_FIFO | 实时调度 | 1–99 | 无时间片 | 高优先级任务永不主动让出 CPU,直到阻塞或结束 | 电机控制、传感器采样 |
| SCHED_RR | 实时调度 | 1–99 | 有时间片(默认 100ms) | 多个相同优先级任务轮流执行 | 多任务实时控制 |
| SCHED_DEADLINE | 实时调度 | 无优先级 | 通过 runtime/deadline/period 控制执行预算 | 最严格的周期性任务调度 | 视频渲染、实时信号处理 |
三、三种调度策略设置代码示例
SCHED_FIFO 测试程序
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <sys/prctl.h>
#include <pthread.h>
#include <sched.h>
int main() {
cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(0, &mask);
if (sched_setaffinity(0, sizeof(mask), &mask) != 0)
perror("sched_setaffinity");
// 设置实时调度
struct sched_param param = { .sched_priority = 80 };
if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0)
perror("sched_setscheduler");
printf("Running under SCHED_FIFO with priority %d on CPU 0\n", param.sched_priority);
while (1) {
for (volatile int i = 0; i < 100000000; i++);
printf(".");
fflush(stdout);
usleep(500000); // 防止完全占满CPU
}
}编译与运行:
gcc sched_fifo_test.c -o sched_fifo_test
sudo ./sched_fifo_testSCHED_RR 测试程序
// sched_rr_test.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <errno.h>
#include <string.h>
int main() {
cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(0, &mask);
if (sched_setaffinity(0, sizeof(mask), &mask) != 0)
perror("sched_setaffinity");
// 设置实时调度
struct sched_param param = { .sched_priority = 80 };
if (sched_setscheduler(0, SCHED_RR, ¶m) != 0)
perror("sched_setscheduler");
printf("Running under SCHED_FIFO with priority %d on CPU 0\n", param.sched_priority);
while (1) {
for (volatile int i = 0; i < 100000000; i++);
printf(".");
fflush(stdout);
usleep(500000); // 防止完全占满CPU
}
}编译与运行:
gcc sched_rr_test.c -o sched_rr_test
sudo ./sched_rr_test观察: 若你同时运行多个 RR 任务(相同优先级),会发现 CPU 在不同任务间周期性切换。 时间片长度可通过:
cat /proc/sys/kernel/sched_rr_timeslice_ms查看(默认 100ms)。
SCHED_DEADLINE 测试程序
// sched_deadline_test.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/sched.h>
#include <sys/syscall.h>
#include <errno.h>
#include <stdint.h>
#include <sched.h>
struct sched_attr {
uint32_t size;
uint32_t sched_policy;
uint64_t sched_flags;
int32_t sched_nice;
uint32_t sched_priority;
/* Deadline scheduling specific fields */
uint64_t sched_runtime;
uint64_t sched_deadline;
uint64_t sched_period;
};
int sched_setattr(pid_t pid, const struct sched_attr *attr, unsigned int flags) {
return syscall(SYS_sched_setattr, pid, attr, flags);
}
int main() {
cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(0, &mask);
if (sched_setaffinity(0, sizeof(mask), &mask) != 0)
perror("sched_setaffinity");
struct sched_attr attr = {0};
attr.size = sizeof(attr);
attr.sched_policy = SCHED_DEADLINE;
attr.sched_runtime = 5 * 1000 * 1000; // 运行时间 5ms
attr.sched_deadline = 10 * 1000 * 1000; // 截止时间 10ms
attr.sched_period = 10 * 1000 * 1000; // 周期 10ms
if (sched_setattr(0, &attr, 0) < 0) {
perror("sched_setattr");
return -1;
}
printf("SCHED_DEADLINE 设置成功\n");
// 模拟工作负载
while (1) {
usleep(10000);
}
return 0;
}编译与运行:
gcc sched_deadline_test.c -o sched_deadline_test
sudo ./sched_deadline_test观察:
SCHED_DEADLINE任务根据定义的周期和运行时间进行严格调度。 如果运行时间超出预算,任务会被内核自动暂停直到下一个周期。