第1章 RTL线程优先级基础

1.1 实时线程库概念

实时线程库(Real-Time Thread Library,RTL)是一组封装了Linux内核实时调度策略的API集合,专门用于提供可预测、低延迟的线程响应能力。在Android SystemUI场景下,RTL用于确保用户交互线程(如触摸响应、动画更新)能够优先于后台任务获得CPU时间,避免因争抢调度导致界面卡顿。

与普通线程相比,RTL线程具有以下核心特性:

  • 确定的调度顺序:依赖优先级抢占机制,高优先级线程可直接抢占低优先级线程,无需等待时间片轮转。
  • 有限优先级范围:Linux实时优先级范围为0~99,数值越大优先级越高,普通线程的nice优先级范围100~139。
  • 系统调用支持:通过pthread_setschedparam、sched_setscheduler等接口设置实时调度策略和优先级。
关键概念:RTL线程必须与实时调度策略配合使用,仅设置高优先级而不指定SCHED_FIFO/SCHED_RR策略不会获得实时行为。

1.2 优先级范围与系统调用

Linux内核将线程优先级分为两大区域:实时区与普通区。SystemUI中的关键渲染、输入分发线程常运行在实时区。

Linux线程优先级划分(基于内核5.x)
区域 优先级范围 调度策略 典型用途
实时(RT) 0 ~ 99 SCHED_FIFO, SCHED_RR SystemUI输入事件线程、vsync信号处理
普通(NORMAL) 100 ~ 139 SCHED_OTHER, SCHED_BATCH 后台GC、日志压缩、非关键动画
空闲(IDLE) —— SCHED_IDLE 低优先级后台扫描任务

设置实时优先级的核心系统调用及参数:

  • sched_setscheduler(pid, policy, param) – 设置调度策略与优先级结构体。
  • pthread_setschedparam(thread, policy, param) – POSIX线程接口,适用于多线程编程。
  • sched_get_priority_min/max(policy) – 查询指定策略下可用优先级范围。
权限限制:设置实时优先级需要CAP_SYS_NICE权限或进程具有root/ system身份。SystemUI进程通常以system用户运行,允许在99范围内调整,但部分低端设备可能受SELinux策略约束。
RTL线程优先级调度架构 Android应用层 SystemUI 关键线程 RTL API 封装 pthread_setschedparam / sched_setscheduler Linux CFS 调度器 + RT 调度器 SCHED_FIFO / SCHED_RR / SCHED_OTHER 混合运行 RT优先级0~49 RT优先级50~99 普通优先级100~139 优先级数值↑ 抢占能力↑ 实时线程不可被普通线程抢占

1.3 线程创建与属性设置

在Native代码中创建RTL线程时,必须通过线程属性对象(pthread_attr_t)或创建后动态设置。推荐在创建前设置调度策略和优先级,以避免线程运行在错误优先级下的风险。

标准实现流程:

  1. 初始化线程属性 pthread_attr_init(&attr)
  2. 设置继承调度属性为显式设置 pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)
  3. 设置调度策略 pthread_attr_setschedpolicy(&attr, SCHED_FIFO)
  4. 设置优先级(例如90)pthread_attr_setschedparam(&attr, &param)
  5. 创建线程 pthread_create(&thread, &attr, thread_func, arg)
  6. 销毁属性 pthread_attr_destroy(&attr)
// 示例:创建一个SCHED_FIFO策略、优先级90的线程
#include <pthread.h>
#include <sched.h>
#include <stdio.h>

void* rt_worker(void* arg) {
    // 实时线程工作循环
    while (1) {
        // 处理SystemUI关键任务
    }
    return NULL;
}

int create_rt_thread(pthread_t* thread_id) {
    pthread_attr_t attr;
    struct sched_param param;
    int ret;

    ret = pthread_attr_init(&attr);
    if (ret != 0) return ret;

    // 不继承调用线程的调度属性
    ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
    if (ret != 0) goto err;

    ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
    if (ret != 0) goto err;

    param.sched_priority = 90;
    ret = pthread_attr_setschedparam(&attr, &param);
    if (ret != 0) goto err;

    ret = pthread_create(thread_id, &attr, rt_worker, NULL);
err:
    pthread_attr_destroy(&attr);
    return ret;
}
调试检查:创建后可通过 /proc/[pid]/task/[tid]/stat 查看策略字段(第42字段,'F'表示SCHED_FIFO,'R'表示SCHED_RR,'O'表示SCHED_OTHER),确认策略生效。
常见错误:
  • 忘记设置 PTHREAD_EXPLICIT_SCHED,导致线程继承父进程的普通调度策略,优先级设置被忽略。
  • 优先级设置超出1~99范围(或超出sched_get_priority_max返回值),导致pthread_attr_setschedparam返回EINVAL。
  • 在未获取CAP_SYS_NICE权限的进程中调用上述接口,导致EPERM错误。