Linux任务调度策略与调整进程优先级

前言

Linux 内核支持多种调度策略,根据不同的任务需求和实时性要求,可分为 普通调度策略 和 实时调度策略。观复君本次讲解以Linux系统为例,希望能给大家的工作带来一些启发。

Linux任务调度策略

普通调度策略(非实时任务)

SCHED_OTHER(完全公平调度器,CFS)

  • 类型:默认策略,面向普通优先级任务。

  • 特点

    • 基于时间片轮转,动态分配 CPU 时间,确保任务间的公平性。

    • 使用 虚拟运行时间(vruntime) 决定任务调度顺序。

    • 支持 优先级(nice值)(范围:-20(最高)到 19(最低))。

  • 适用场景:大多数普通进程(如用户应用程序、后台服务)。

SCHED_BATCH

  • 类型:优化批处理任务。

  • 特点

    • 类似 SCHED_OTHER,但减少交互式任务的优先级,适合长时间运行的批处理作业。

    • 任务倾向于一次性占用较长 CPU 时间片,减少上下文切换开销。

  • 适用场景:非交互式计算密集型任务(如编译、数据分析)。

SCHED_IDLE

  • 类型:最低优先级任务。

  • 特点

    • 仅在系统空闲时运行,优先级低于所有其他策略。

    • 不占用公平调度的时间配额。

  • 适用场景:极低优先级的后台任务(如系统监控探针)。

实时调度策略

SCHED_FIFO(先进先出)

  • 类型:严格实时策略。

  • 特点

    • 任务一旦获得 CPU,会一直运行直到主动释放(如阻塞、调用 sched_yield)或被更高优先级的实时任务抢占。

    • 无时间片限制,除非被抢占。

    • 优先级范围:1(最低)到 99(最高)(数值越大优先级越高)。

  • 适用场景:需要确定性和低延迟的实时任务(如硬件控制)。

SCHED_RR(轮转调度)

  • 类型:实时策略,带时间片轮转。

  • 特点

    • 类似 SCHED_FIFO,但每个任务有固定时间片(默认 100ms,可通过 sched_rr_timeslice_ms 调整)。

    • 时间片耗尽后,任务被移到同优先级队列末尾,允许其他同优先级任务运行。

    • 优先级范围:1 到 99

  • 适用场景:需要共享 CPU 的同优先级实时任务(如音视频处理)。

SCHED_DEADLINE(截止时间优先)

  • 类型:基于截止时间的实时策略(Linux 3.14+ 引入)。

  • 特点

    • 任务需声明三个参数:运行时间(runtime)、截止时间(deadline)、周期(period)。

    • 调度器确保任务在截止时间前完成指定运行时间,否则视为超时。

    • 优先级动态计算,截止时间越近的任务优先级越高。

  • 适用场景:严格周期性实时任务(如机器人控制、传感器采样)。

调度策略对比

策略类型时间片抢占规则优先级范围典型场景
SCHED_OTHER普通动态调整公平调度-20 到 19普通应用程序
SCHED_BATCH普通较长低交互性优化同 SCHED_OTHER批处理任务
SCHED_IDLE普通无限制仅空闲时运行最低后台监控
SCHED_FIFO实时高优先级抢占1 到 99硬件中断处理
SCHED_RR实时固定同优先级轮转1 到 99多任务实时协作
SCHED_DEADLINE实时动态截止时间驱动动态计算周期性实时任务

nice值与优先级的异同

心细的朋友可能已经关注到SCHED_OTHER的调度策略是通过nice值来表示的,它的含义与其他调度策略(如实时策略)不同。以下是对 SCHED_OTHER 优先级(nice值)的详细解释。

1. SCHED_OTHER 优先级的特点

  • 优先级范围nice 值的范围是 -20 到 19(数值越小,优先级越高)。

  • 默认值:新进程默认的 nice 值为 0

  • 作用方式

    • nice 值不直接决定绝对优先级,而是影响进程在 完全公平调度器(CFS) 中的 CPU 时间权重

    • 值越小(如 -20),进程的权重越高,分配的 CPU 时间比例越大。

    • 值越大(如 19),权重越低,分配的 CPU 时间比例越小。


2. 关键规则

nice 值含义
-20最高优先级(进程将获得比其他进程更多的 CPU 时间)
0默认优先级(与其他 nice=0 的进程平等竞争 CPU 时间)
19最低优先级(进程仅在其他高优先级进程不需要 CPU 时才运行)

示例

  • 如果进程 A 的 nice=-10,进程 B 的 nice=10,则 A 的 CPU 时间权重远高于 B。

  • 这种差异在系统负载较高时更明显,但在空闲系统中可能表现相似。


3. nice 值与实时优先级的区别

  • SCHED_OTHER(普通进程)

    • 优先级通过 nice 值调整(范围:-20 到 19)。

    • 数值越小,优先级越高

  • 实时策略(SCHED_FIFO/SCHED_RR

    • 优先级通过 sched_priority 调整(范围:1 到 99)。

    • 数值越大,优先级越高

⚠️ 注意:实时策略的进程优先级(1-99)永远高于普通策略(SCHED_OTHER),即使普通进程的 nice=-20

进程优先级调整

系统支持调度策略查看

chrt 是 Linux 中用于操作调度策略的工具,直接运行 chrt 命令会显示支持的策略列表:

chrt -h

输出示例(J3):

如果输出中没有某个策略(如 SCHED_DEADLINE),则内核可能未启用该策略支持。

调整普通进程的nice值

查看进程的nice值

ps -eo pid,ni,comm | grep <进程名>

指令方式

修改已运行进程的 nice 值

# 语法:renice -n <目标值> -p <PID>
# 示例:将 PID=1234 的进程的 nice 值设为 -5
sudo renice -n -5 -p 1234       # 需要 root 权限

# 示例:将 PID=5678 的进程的 nice 值设为 10
renice -n 10 -p 5678            # 普通用户可运行(仅能降低优先级)

启动新进程时指定 nice 值

# 语法:nice -n <增量> <命令>
# 示例:启动一个高优先级进程(nice=-10)
sudo nice -n -10 ./my_program    # 需要 root 权限(降低 nice 值)

# 示例:启动一个低优先级进程(nice=15)
nice -n 15 ./my_program          # 普通用户可直接运行(增大 nice 值)

  • 规则

    • -n 后的数值是相对于默认值(0)的增量。例如:

      • nice -n -10 → 最终 nice=-10(更高优先级)。

      • nice -n 5 → 最终 nice=5(更低优先级)。

    • 普通用户只能降低优先级(增大 nice 值),提高优先级(减小 nice 值)需要 root 权限

代码方式

使用 setpriority 函数动态调整优先级。

#include <stdio.h>
#include <sys/resource.h>

int main() {
    int new_nice = -10;  // 设置更高的优先级(需要 root 权限)

    // 设置当前进程的 nice 值
    if (setpriority(PRIO_PROCESS, 0, new_nice) == -1) {
        perror("setpriority failed");
        return 1;
    }

    printf("当前进程的 nice 值已设置为: %d\n", new_nice);
    return 0;
}

编译运行:

gcc set_nice.c -o set_nice
sudo ./set_nice  # 需要 root 权限(因为降低 nice 值)

调整实时进程的优先级

查看进程的调度策略和优先级

not0397@DZ-NOT-0397:~$ chrt -p 2643077
pid 2643077 当前的调度策略︰ SCHED_OTHER
pid 2643077 的当前调度优先级:0

指令方式

1. 启动新进程时指定调度策略和优先级
# 语法:chrt [选项] <优先级> <命令>
# 示例:以 SCHED_FIFO 策略、优先级 90 启动进程
sudo chrt -f 90 ./my_realtime_task    # -f 表示 SCHED_FIFO

# 示例:以 SCHED_RR 策略、优先级 50 启动进程
sudo chrt -r 50 ./my_realtime_task    # -r 表示 SCHED_RR

# 示例:以 SCHED_DEADLINE 策略启动(需额外参数)
sudo chrt -d --sched-runtime 10000000 --sched-deadline 20000000 --sched-period 20000000 0 ./my_deadline_task
  • 选项

    • -fSCHED_FIFO(严格实时)。

    • -rSCHED_RR(带时间片轮转的实时)。

    • -dSCHED_DEADLINE(需指定运行时间、截止时间和周期,单位:纳秒)。

2. 修改已运行进程的调度策略和优先级
# 语法:chrt -p [选项] <优先级> <PID>
# 示例:将 PID=1234 的进程设为 SCHED_FIFO,优先级 80
sudo chrt -f -p 80 1234

# 示例:将 PID=5678 的进程设为 SCHED_RR,优先级 60
sudo chrt -r -p 60 5678

代码方式

实时策略的优先级通过 sched_priority 字段设置(范围:1(最低)到 99(最高))。
代码示例:使用 sched_setscheduler 函数设置策略和优先级。

#include <stdio.h>
#include <sched.h>
#include <stdlib.h>

int main() {
    struct sched_param param;
    int policy = SCHED_FIFO;  // 调度策略
    int priority = 80;        // 实时优先级(1-99)

    // 设置优先级参数
    param.sched_priority = priority;

    // 设置调度策略和优先级
    if (sched_setscheduler(0, policy, &param) == -1) {
        perror("sched_setscheduler failed");
        exit(EXIT_FAILURE);
    }

    printf("当前进程已设置为 SCHED_FIFO,优先级: %d\n", priority);
    return 0;
}

注意事项

1. 权限要求
操作所需权限
提高 nice 值(降低优先级)普通用户可直接操作
降低 nice 值(提高优先级)需要 root 权限
设置实时策略(SCHED_FIFO 等)需要 root 权限或 CAP_SYS_NICE 能力
2. 实时策略的风险
  • CPU 独占:高优先级 SCHED_FIFO 任务可能长时间占用 CPU,导致系统无响应。
    解决方案:合理分配优先级,或结合 SCHED_RR 使用时间片轮转。

3. 调度策略的兼容性
  • SCHED_DEADLINE:需内核 ≥3.14 并启用 CONFIG_SCHED_DEADLINE,且需指定 runtimedeadlineperiod 参数。

  • 实时内核优化:在 PREEMPT RT 补丁的内核(如地平线 J3 系统)中,实时任务响应更快。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值