> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs-staging.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 配置调度器

Qualcomm<sup>®</sup> Linux 内核支持标准的 Linux 调度器方案。内核使用调度器根据 CPU 能耗为任务放置选择合适的 CPU。

调度器决定进程的运行顺序。调度器从每个 CPU 的运行队列（runqueue）中运行进程。

内核基线支持标准的 Linux 调度器方案。内核使用[能耗感知调度（EAS）](https://docs.kernel.org/scheduler/sched-energy.html)根据 CPU 能耗为任务放置选择合适的 CPU。

EAS 覆盖了完全公平调度器（CFS）的任务唤醒均衡代码。在具有非对称 CPU 拓扑的系统中，它使用 CPU 的能耗模型（EM）和按实体负载跟踪（PELT）信号，在唤醒均衡期间选择节能的目标 CPU。

有关调度器的基本文档，请参阅 [Scheduler](https://docs.kernel.org/scheduler/index.html)。

## 了解 CPU 拓扑和 EAS

Qualcomm SoC 具有异构 CPU 拓扑，在 EAS 中通过 CPU 容量（capacity）指标加以区分。

EAS 使用\_容量\_的概念来区分具有不同计算能力的 CPU。CPU 的容量表示它以最高频率运行时完成的工作量，相对于系统中能力最强的 CPU 而言。容量值在 1024 的范围内归一化（最强大的 CPU/集群配置为 1024）。

EAS 根据 CPU 节点中指定的 Dhrystone 每秒百万指令数（DMIPS）值以及集群支持的最大频率来构建集群的容量。

以下是用于 CPU 拓扑和容量的 `sysfs` 节点：

**表：CPU 拓扑和容量**

|                           **命令**                           |         **用途**        |
| :--------------------------------------------------------: | :-------------------: |
|       cat /sys/devices/system/cpu/cpu\*/cpu\_capacity      |   获取系统中每个 CPU 关联的容量。  |
| cat /sys/devices/system/cpu/cpufreq/policy\*/related\_cpus | 获取系统中与每个集群关联的 CPU 列表。 |

有关调度器如何使用 CPU 容量的更多信息，请参阅 [Capacity Aware Scheduling](https://docs.kernel.org/scheduler/sched-capacity.html)。

## 更改默认的 CPU 频率调节器

CPU 频率调节器可以在运行时更改，也可以在构建编译期间静态设置。

1. Kconfig 配置：要设置 CPU 频率调节器，请在内核 defconfiguration 文件中启用相应的驱动。
   要将 `PERFORMANCE` 调节器设置为默认的 CPU 频率调节器，请在 defconfiguration 文件中设置 `CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y`。
2. 内核命令行：要覆盖内核配置选项，请在 SoC 专属 machine 包含文件中的 kas 基础配置文件 `ci/base.yml` 的 `KERNEL_CMDLINE_EXTRA` 中，向内核命令行添加 `cpufreq.default_governor=performance` 参数。
   例如，在 `meta-qcom/conf/machine/include/qcom-<SoC>.inc` 文件中设置合适的 CPU 频率调节器。

## 配置 SchedUtil 调节器

SchedUtil CPU 频率调节器是 Qualcomm Linux 内核中的默认调节器。SchedUtil 根据 CPU 利用率预测最优工作点（OPP），保持频率请求与能耗预测之间的一致性。

SchedUtil CPU 频率调节器与 EAS 绑定，它会尝试预测所有 CPU 下一步将在哪个 OPP 上运行，以估计其能耗。

有关更多信息，请参阅 [SchedUtil](https://docs.kernel.org/scheduler/schedutil.html)。

## 配置利用率钳制（UCLAMP）

利用率钳制是一项调度器特性，允许用户空间管理任务的性能需求。

要执行钳制，请配置以下参数：

* `UCLAMP_MIN`：如果设置为任何 `> 0` 的值，任务需求始终大于或等于此值。如果实际任务需求大于此值，则使用实际需求信号；但如果实际任务需求低于此值，则将 `UCLAMP_MIN` 作为任务需求上报。
* `UCLAMP_MAX`：如果设置为任何 `> 0` 的值，任务需求始终小于或等于此值。如果实际任务需求小于此值，则使用实际需求信号；但如果实际任务需求大于此值，则将 `UCLAMP_MAX` 作为任务需求上报。

<Note>
  `UCLAMP_MAX > UCLAMP_MIN`
</Note>

使用 UCLAMP 影响调度器的任务放置决策。

在异构系统上，调度器使用任务需求或利用率信号（PELT 信号）将任务分类为小任务或大任务。基于任务分类的输入，调度器选择小核（较低算力）或大核（较高算力）CPU 核心进行任务放置，这可能会影响功耗。

例如，将不重要的任务（琐碎/后台/内务任务）钳制到较低的值（`较低的 UCLAMP_MAX`），以促使调度器将这些任务放置在小核集群上。类似地，将重要/前台/活跃任务钳制到较高的值（`较高的 UCLAMP_MIN`），以促使调度器将这些任务放置在大核集群上。

UCLAMP 还允许调度器控制频率引导。

为了满足任务的快速频率提升需求，请将任务钳制到较高的需求（`UCLAMP_MIN`）值。较高的钳制有助于提升集群的频率，以满足任务的性能需求。

UCLAMP 操作允许从用户空间对任务/任务组进行性能管理。

UCLAMP 允许放置任务或任务组，并允许性能提示或约束。此机制用于影响调度器的放置决策或影响集群的频率引导。

有关更多信息，请参阅 [UCLAMP](https://docs.kernel.org/scheduler/sched-util-clamp.html)；有关接口和配置，请参阅 [Utilization Clamping](https://www.kernel.org/doc/html/v6.18/scheduler/sched-util-clamp.html)。

## 以实时优先级运行用户空间任务

必须先于所有 `SCHED_OTHER`（CFS）任务运行的任务使用 POSIX 实时策略之一。两种策略都以 `1`–`99` 范围内的固定优先级运行（`99` 为最高），并且都会抢占所有 CFS 任务：

**表：实时调度策略**

| **策略**       | **行为**                                          |
| :----------- | :---------------------------------------------- |
| `SCHED_FIFO` | 持续运行，直到阻塞、让出 CPU 或被更高优先级的 RT 任务抢占。没有时间片。        |
| `SCHED_RR`   | 与 `SCHED_FIFO` 相同，不同之处在于优先级相同的任务以轮转时间片方式共享 CPU。 |

<Note>
  标准 Qualcomm Linux 内核即支持实时策略。`PREEMPT_RT` 内核不会增加新的策略；它只是降低 RT 任务在变为可运行状态后被调度的延迟。有关更多信息，请参阅 [RT 内核基础](./rt-kernel-fundamentals)。
</Note>

### 从命令行设置策略

使用 `util-linux` 软件包中的 `chrt` 来启动新任务或更改正在运行的任务的策略。

1. 以优先级 80 的 `SCHED_FIFO` 策略启动一条命令：

   ```bash theme={null}
   chrt --fifo 80 /usr/bin/my_control_loop
   ```

2. 更改正在运行的线程的策略。当目标是多线程进程中的某个线程时，请使用线程 ID（TID），而不是进程 ID：

   ```bash theme={null}
   chrt --fifo --pid 80 <TID>
   ```

3. 确认已应用的策略和优先级：

   ```bash theme={null}
   chrt --pid <TID>
   # Expected output:
   # pid <TID>'s current scheduling policy: SCHED_FIFO
   # pid <TID>'s current scheduling priority: 80
   ```

若要在设置策略的同时将任务固定到专用 CPU，请将 `chrt` 与 `taskset` 结合使用：

```bash theme={null}
taskset --cpu-list 7 chrt --fifo 80 /usr/bin/my_control_loop
```

有关将 CPU 7 从通用调度器中保留出来的信息，请参阅[运行时性能调优](./runtime-performance-tuning)。

### 从应用程序设置策略

在调用线程上调用 `sched_setscheduler()`，以便在时间关键型工作开始之前应用优先级：

```c theme={null}
#include <sched.h>
#include <sys/mman.h>
#include <stdio.h>

int main(void)
{
    struct sched_param param = { .sched_priority = 80 };

    /* Raise the calling thread to SCHED_FIFO priority 80. */
    if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
        perror("sched_setscheduler");
        return 1;
    }

    /* Lock the address space in RAM so that a page fault cannot
     * introduce latency inside the real-time loop.
     */
    if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
        perror("mlockall");
        return 1;
    }

    /* Time-critical loop runs here. */
    return 0;
}
```

对于基于 `pthread` 的应用程序，请在创建线程之前设置属性，使线程以正确的优先级启动：

```c theme={null}
#include <pthread.h>
#include <sched.h>

pthread_attr_t attr;
struct sched_param param = { .sched_priority = 80 };

pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
pthread_attr_setschedparam(&attr, &param);
pthread_create(&thread, &attr, rt_thread_fn, NULL);
```

更改策略需要 `CAP_SYS_NICE` 能力。可以以 `root` 身份运行进程，或者向二进制文件授予该能力：

```bash theme={null}
setcap cap_sys_nice+ep /usr/bin/my_control_loop
```

### 配置实时限流

内核会对实时任务进行限流，以防失控的 RT 循环使系统饿死。默认情况下，RT 任务在每 1000 ms 周期内最多只能占用 950 ms：

```bash theme={null}
cat /proc/sys/kernel/sched_rt_period_us    # 1000000
cat /proc/sys/kernel/sched_rt_runtime_us   # 950000
```

若要让某个 RT 任务完全占用一个 CPU，请禁用限流：

```bash theme={null}
echo -1 > /proc/sys/kernel/sched_rt_runtime_us
```

<Warning>
  禁用 RT 限流后，不让出 CPU 的 `SCHED_FIFO` 任务可以无限期地占用一个 CPU。如果该任务运行在负责喂狗线程的 CPU 上，SoC 看门狗将会复位设备。请为 RT 任务保留一个专用 CPU，并将内务（housekeeping）工作保留在其余 CPU 上。有关更多信息，请参阅 [RT 验证和已知限制](./rt-validation-and-known-limitations)。
</Warning>

有关实时策略及其接口的更多信息，请参阅 [sched(7)](https://man7.org/linux/man-pages/man7/sched.7.html) 和 [Real-Time group scheduling](https://docs.kernel.org/scheduler/sched-rt-group.html)。
