跳转至

实时线程优先级

实时线程优先级决定了线程在系统中的执行顺序,确保高优先级的线程在就绪时能够立即抢占低优先级线程的执行,从而保证关键路径的确定性延迟。

  • 设置方法:在Linux系统中,可以使用pthread_setschedparam函数来设置线程的调度策略和优先级。

Linux内核的三种调度策略:

  • SCHED_OTHER:分时调度策略,系统默认
  • SCHED_FIFO:实时调度策略,先到先服务
  • SCHED_RR:实时调度策略,时间片轮转
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>

void* thread_function(void* arg) {
  // 线程执行的代码
  return NULL;
}

int main() {
  pthread_t thread;
  struct sched_param param;
  int policy;

  // 创建线程
  if (pthread_create(&thread, NULL, thread_function, NULL) != 0) {
    perror("pthread_create");
    return EXIT_FAILURE;
  }

  // 获取当前线程的调度策略和参数
  if (pthread_getschedparam(pthread_self(), &policy, &param) != 0) {
    perror("pthread_getschedparam");
    return EXIT_FAILURE;
  }

  // 设置调度策略为SCHED_FIFO
  policy = SCHED_FIFO;
  // 设置线程优先级,取值范围为0到sched_get_priority_max(policy)
  param.sched_priority = sched_get_priority_max(policy);

  // 设置线程的调度策略和优先级
  if (pthread_setschedparam(thread, policy, &param) != 0) {
    perror("pthread_setschedparam");
    return EXIT_FAILURE;
  }

  // 等待线程结束
  if (pthread_join(thread, NULL) != 0) {
    perror("pthread_join");
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}

// sched_setscheduler(pid_t pid, int policy, const struct sched_param *param)
// 这是对应调整进程优先级的函数

优先级反转及解决办法

在实时系统中,当高优先级线程因等待低优先级线程持有的资源(如互斥锁)而阻塞时,若中优先级线程抢占CPU,会导致:

  • 低优先级线程无法及时释放资源
  • 高优先级线程被“间接”延迟(本应最高优先级却最晚执行) L(持锁)→ H(等待锁)→ M(抢占L)→ H持续阻塞

优先级继承(PTHREAD_PRIO_INHERIT)

  1. 高优先级线程H等待锁时,持有锁的低优先级线程L的优先级临时提升至H的优先级
  2. 提升后的L可立即抢占中优先级线程M,快速执行并释放锁
  3. L释放锁后,其优先级自动恢复原值
  4. 若存在多层等待(如L等待另一锁),系统会递归提升所有相关线程优先级

2.优先级天花板(PTHREAD_PRIO_PROTECT)

锁创建时预设天花板优先级,适用于已知资源依赖场景

命令: 使用 chrt (change real-time attributes) 命令,只针对进程调整优先级

# 将PID为 <pid> 的进程设置为 SCHED_FIFO 实时调度策略,优先级为最高的99
sudo chrt -f -p 99 <pid>

chrt 命令的基本语法是:
chrt [选项] <优先级> <命令> [命令参数...]
chrt [选项] -p <优先级> <PID>
<优先级>: 这是一个整数,表示调度优先级。其范围和含义取决于使用的调度策略。
<命令>: 你想要运行并设置其调度策略的命令及其参数。
<PID>: 你想要修改调度策略的现有进程的进程 ID。

chrt 支持多种实时调度策略,其中最常用的是:

--fifo (SCHED_FIFO):先到先服务 (First-In, First-Out)。具有相同优先级的进程会按照它们就绪的顺序执行。一旦一个 FIFO 进程开始运行,它会一直运行,直到它自己主动放弃 CPU、被阻塞(例如等待 I/O),或者被一个具有更高优先级的进程抢占。

--rr (SCHED_RR):轮转 (Round-Robin)。与 SCHED_FIFO 类似,但有一个时间片。当一个 RR 进程的时间片用完时,它会被移到就绪队列的末尾,让同等优先级的其他进程有机会运行。

--other (SCHED_OTHER):普通调度策略。这是系统的默认调度策略,使用 CFS (Completely Fair Scheduler)。

--batch (SCHED_BATCH):批处理调度策略。适用于不需要交互的批处理任务。

--idle (SCHED_IDLE):空闲调度策略。只在系统空闲时运行,优先级最低。

常用选项:

-p: 操作指定的 PID(进程 ID),而不是启动新命令。

-o: 设置 OTHER 调度策略(SCHED_OTHER)。

-f: 设置 FIFO 调度策略(SCHED_FIFO)。

-r: 设置 RR 调度策略(SCHED_RR)。

-b: 设置 BATCH 调度策略(SCHED_BATCH)。

-i: 设置 IDLE 调度策略(SCHED_IDLE)。

-g: 设置 GROUP 调度策略(SCHED_GROUP,不常用)。

-h: 设置 HIGH 调度策略(SCHED_HIGH,不常用)。

-a: 设置 AFR 调度策略(SCHED_AFR,不常用)。

-e: 设置 EDF 调度策略(SCHED_EDF,不常用)。

-d: 设置 DEADLINE 调度策略(SCHED_DEADLINE,不常用)。

-v: 显示 当前进程(或指定 PID)的调度策略和优先级。

--help: 显示帮助信息。

--version: 显示版本信息。