Contents

Linux实时调度策略:SCHED_FIFO、SCHED_RR和SCHED_DEADLINE设置示例

一、前言

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, &param) != 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_test

SCHED_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, &param) != 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 任务根据定义的周期和运行时间进行严格调度。 如果运行时间超出预算,任务会被内核自动暂停直到下一个周期。