菜单

Cobalt/Process scheduling

详细描述

Cobalt/POSIX 进程调度。

title: Cobalt/Process scheduling


函数文档

sched_get_priority_max()

int sched_get_priority_max (int policy)

获取指定调度策略的最大优先级。

该服务返回调度策略 policy 的最大优先级。

参数:

  • policy: 调度策略。

返回值:

  • 成功时返回 0
  • 出错时返回 -1 并设置 errno:
    • EINVAL: policy 无效。

标签:

  • thread-unrestrictedswitch-secondary

注意:
获取 SCHED_FIFOSCHED_RR 或任何 xkernel 特定策略的最大优先级级别不会导致模式切换。policy 的任何其他值可能会将调用者切换到次级模式。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <errno.h>

int main() {
    int policy = SCHED_FIFO; // 可以选择 SCHED_OTHER, SCHED_RR, SCHED_FIFO
    int max_priority;

    // 获取指定调度策略的最大优先级
    max_priority = sched_get_priority_max(policy);
    
    // 检查返回值
    if (max_priority == -1) {
        perror("sched_get_priority_max");
        exit(EXIT_FAILURE);
    }

    printf("The maximum priority for policy %d is: %d\n", policy, max_priority);
    
    return 0;
}

sched_get_priority_max_ex()

int sched_get_priority_max_ex (int policy)

获取指定调度策略的扩展最大优先级。

该服务返回调度策略 policy 的最大优先级,反映任何 Cobalt 对标准类的扩展。

参数:

  • policy: 调度策略。

返回值:

  • 成功时返回 0
  • 出错时返回 -1 并设置 errno:
    • EINVAL: policy 无效。

标签:

  • thread-unrestricted

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <errno.h>

int main() {
    int policy = SCHED_FIFO; // 可以选择 SCHED_OTHER, SCHED_RR, SCHED_FIFO
    int max_priority;

    // 获取指定调度策略的最大优先级
    max_priority = sched_get_priority_max_ex(policy);
    
    // 检查返回值
    if (max_priority == -1) {
        perror("sched_get_priority_max_ex");
        exit(EXIT_FAILURE);
    }

    printf("The maximum priority for policy %d is: %d\n", policy, max_priority);
    
    return 0;
}

sched_get_priority_min()

int sched_get_priority_min (int policy)

获取指定调度策略的最小优先级。

该服务返回调度策略 policy 的最小优先级。

参数:

  • policy: 调度策略。

返回值:

  • 成功时返回 0
  • 出错时返回 -1 并设置 errno:
    • EINVAL: policy 无效。

标签:

  • thread-unrestrictedswitch-secondary

注意:
获取 SCHED_FIFOSCHED_RR 或任何 xkernel 特定策略的最小优先级级别不会导致模式切换。policy 的任何其他值可能会将调用者切换到次级模式。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <errno.h>

int main() {
    int policy = SCHED_FIFO; // 可以选择 SCHED_OTHER, SCHED_RR, SCHED_FIFO
    int min_priority;

    // 获取指定调度策略的最大优先级
    min_priority = sched_get_priority_min(policy);
    
    // 检查返回值
    if (min_priority == -1) {
        perror("sched_get_priority_min");
        exit(EXIT_FAILURE);
    }

    printf("The minimum priority for policy %d is: %d\n", policy, min_priority);
    
    return 0;
}

sched_get_priority_min_ex()

int sched_get_priority_min_ex (int policy)

获取指定调度策略的扩展最小优先级。

该服务返回调度策略 policy 的最小优先级,反映任何 Cobalt 对标准类的扩展。

参数:

  • policy: 调度策略。

返回值:

  • 成功时返回 0
  • 出错时返回 -1 并设置 errno:
    • EINVAL: policy 无效。

标签:

  • thread-unrestricted

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <errno.h>

int main() {
    int policy = SCHED_FIFO; // 可以选择 SCHED_OTHER, SCHED_RR, SCHED_FIFO
    int min_priority;

    // 获取指定调度策略的最大优先级
    min_priority = sched_get_priority_min_ex(policy);
    
    // 检查返回值
    if (min_priority == -1) {
        perror("sched_get_priority_min_ex");
        exit(EXIT_FAILURE);
    }

    printf("The minimum priority for policy %d is: %d\n", policy, min_priority);
    
    return 0;
}

sched_getconfig_np()

ssize_t sched_getconfig_np (int cpu, int policy, union sched_config *config, size_t *len_r)

检索特定 CPU 的调度策略设置。

配置严格地局限于目标 cpu,并且可能与其他处理器不同。

参数:

  • cpu: 要检索配置的处理器。
  • policy: 配置数据适用的调度策略。目前,仅 SCHED_TPSCHED_QUOTA 是有效输入。
  • config: 一个指向内存区域的指针,该区域在调用成功时接收配置设置。

SCHED_TP 具体细节:
成功返回时,config->quota.tp 包含 cpu 上活动的 TP 调度。

SCHED_QUOTA 具体细节:
进入时,config->quota.get.tgid 必须包含要查询的线程组标识符。
成功退出时,config->quota.info 包含与 config->quota.get.tgid 引用的线程组相关的信息。

参数:

  • [in, out] len_r: 一个指向变量的指针,用于收集返回的配置数据的总长度(以字节为单位)。在请求发出时,该变量必须包含 config 中可用的空间量。

返回值:

  • 成功时返回复制到 config 的字节数;
  • 出错时返回负错误号:
    • EINVAL: cpu 无效,或 policy 不受当前内核配置支持,或 len 无法容纳检索到的配置数据。
    • ESRCH,当 policy 等于 SCHED_QUOTA 时,如果执行操作所需的组标识符无效(即 config->quota.get.tgid 无效)。
    • ENOMEM: 执行操作时内存不足。
    • ENOSPC: len 太短。

标签:

  • thread-unrestrictedswitch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <cobalt/sched.h>

void *thread_function(void *arg) {
    int cpu = 0;  // 目标 CPU
    union sched_config config;
    size_t len;

    // 设置 TP 调度窗口
    config.tp.op = sched_tp_install;
    config.tp.nr_windows = 1;
    
    // 配置1个时间窗口
    config.tp.windows[0].offset.tv_sec = 0;
    config.tp.windows[0].offset.tv_nsec = 10000000;
    config.tp.windows[0].duration.tv_sec = 0;
    config.tp.windows[0].duration.tv_nsec = 10000000;  // 10ms
    config.tp.windows[0].ptid = 2;

    len = sizeof(config.tp);

    // 设置 SCHED_TP 配置
    if (sched_setconfig_np(cpu, SCHED_TP, &config, len) < 0) {
        perror("sched_setconfig_np");
        exit(EXIT_FAILURE);
    }

     // 检索 SCHED_TP 配置
    len = sizeof(config);
    if (sched_getconfig_np(cpu, SCHED_TP, &config, &len) < 0) {
        perror("sched_getconfig_np");
        exit(EXIT_FAILURE);
    }

    printf("Successfully retrieved SCHED_TP configuration for CPU %d\n", cpu);
    printf("Number of windows: %d\n", config.tp.nr_windows);

    // 打印每个时间窗口的信息
    for (int i = 0; i < config.tp.nr_windows; i++) {
        printf("Window %d:\n", i);
        printf("  Offset: %ld.%09ld\n", 
               config.tp.windows[i].offset.tv_sec,
               config.tp.windows[i].offset.tv_nsec);
        printf("  Duration: %ld.%09ld\n", 
               config.tp.windows[i].duration.tv_sec,
               config.tp.windows[i].duration.tv_nsec);
        printf("  Partition ID: %d\n", config.tp.windows[i].ptid);
    }

    // 启动 TP 调度
    config.tp.op = sched_tp_start;
    if (sched_setconfig_np(cpu, SCHED_TP, &config, len) < 0) {
        perror("sched_setconfig_np (start)");
        exit(EXIT_FAILURE);
    }

    printf("Thread running with PID: %d\n", getpid());
    for (int i = 0; i < 3; i++) {
        printf("Thread: %d\n", i);
        sleep(1);
    }

    //停止TP调度并卸载
    config.tp.op = sched_tp_stop;
    if (sched_setconfig_np(cpu, SCHED_TP, &config, len) < 0) {
        perror("sched_setconfig_np (start)");
        exit(EXIT_FAILURE);
    }
    config.tp.op = sched_tp_uninstall;
    if (sched_setconfig_np(cpu, SCHED_TP, &config, len) < 0) {
        perror("sched_setconfig_np (start)");
        exit(EXIT_FAILURE);
    }
    pthread_exit(0);
}

int main() {
    pthread_t thread;

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

    // 等待线程结束
    pthread_join(thread, NULL);
    printf("Thread finished.\n");

    return EXIT_SUCCESS;
}

sched_setconfig_np()

int sched_setconfig_np (int cpu, int policy, const union sched_config *config, size_t len)

为特定 CPU 设置调度策略配置。

配置严格地局限于目标 cpu,并且可能与其他处理器不同。

参数:

  • cpu: 要加载配置的处理器。
  • policy: 配置数据适用的调度策略。目前,SCHED_TPSCHED_QUOTA 是有效的。
  • config: 一个指向要加载到 cpu 上的配置数据的指针,适用于 policy

适用于 SCHED_TP 的设置

此调用根据请求的操作控制 cpu 的时间分区。

  • config.tp.op 指定要执行的操作:
    • sched_tp_installcpu 上安装一个新的 TP 调度,由 config.tp.windows[] 定义。全局时间框架在此请求返回时尚未激活;必须发出 sched_tp_start 才能在 cpu 上激活时间调度。
    • sched_tp_uninstallcpu 上移除当前的 TP 调度,释放所有附加资源。如果 cpu 上不存在 TP 调度,则此请求无效。
    • sched_tp_start 启用 cpu 上的时间调度,启动全局时间框架。如果 cpu 上不存在 TP 调度,则此操作无效。
    • sched_tp_stop 禁用 cpu 上的时间调度。不过,当前的 TP 调度不会被卸载,可以通过 sched_tp_start 请求稍后重新启动。

注意:

  • 由于此请求的结果,分配给未调度分区的线程可能会被剥夺 CPU 时间。

适用于 SCHED_QUOTA 的设置

此调用管理在 cpu 上运行的线程组,定义每组的配额以限制其 CPU 消耗。

  • config.quota.op 应定义要执行的操作。有效操作包括:
    • sched_quota_addcpu 上创建一个新的线程组。新组标识符将在成功时写回到 info.tgid
    • sched_quota_remove 删除 cpu 上的线程组。组标识符应传递到 config.quota.remove.tgid
    • sched_quota_set 更新在 cpu 上定义的线程组的调度参数。

参数:

  • len: 配置数据的总长度(以字节为单位)。

返回值:

  • 成功时返回 0
  • 出错时返回错误号:
    • EINVAL: cpu 无效,或 policy 不受当前内核配置支持,或 len 无效,或 config 包含无效参数。
    • ENOMEM: 执行操作时内存不足。
    • EBUSY: 当 policy 等于 SCHED_QUOTA 时,如果尝试删除仍在管理线程的线程组。
    • ESRCH: 当 policy 等于 SCHED_QUOTA 时,如果执行操作所需的组标识符无效。

标签:

  • thread-unrestrictedswitch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <cobalt/sched.h>

void *thread_function(void *arg) {
    int cpu = 0;  // 目标 CPU
    union sched_config config;
    size_t len;

    // 设置 TP 调度窗口
    config.tp.op = sched_tp_install;
    config.tp.nr_windows = 1;
    
    // 配置1个时间窗口
    config.tp.windows[0].offset.tv_sec = 0;
    config.tp.windows[0].offset.tv_nsec = 0;
    config.tp.windows[0].duration.tv_sec = 0;
    config.tp.windows[0].duration.tv_nsec = 10000000;  // 10ms
    config.tp.windows[0].ptid = 1;

    len = sizeof(config.tp);

    // 设置 SCHED_TP 配置
    if (sched_setconfig_np(cpu, SCHED_TP, &config, len) < 0) {
        perror("sched_setconfig_np");
        exit(EXIT_FAILURE);
    }

    printf("Successfully set SCHED_TP configuration for CPU %d\n", cpu);

    // 启动 TP 调度
    config.tp.op = sched_tp_start;
    if (sched_setconfig_np(cpu, SCHED_TP, &config, len) < 0) {
        perror("sched_setconfig_np (start)");
        exit(EXIT_FAILURE);
    }

    printf("Started SCHED_TP scheduling on CPU %d\n", cpu);

    printf("Thread running with PID: %d\n", getpid());
    for (int i = 0; i < 3; i++) {
        printf("Thread: %d\n", i);
        sleep(1);
    }
    // 停止TP调度并卸载
    config.tp.op = sched_tp_stop;
    if (sched_setconfig_np(cpu, SCHED_TP, &config, len) < 0) {
        perror("sched_setconfig_np (start)");
        exit(EXIT_FAILURE);
    }
    config.tp.op = sched_tp_uninstall;
    if (sched_setconfig_np(cpu, SCHED_TP, &config, len) < 0) {
        perror("sched_setconfig_np (start)");
        exit(EXIT_FAILURE);
    }
    pthread_exit(0);
}

int main() {
    pthread_t thread;

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

    // 等待线程结束
    pthread_join(thread, NULL);
    printf("Thread finished.\n");

    return EXIT_SUCCESS;
}

sched_getscheduler()

int sched_getscheduler (pid_t pid)

获取指定进程的调度策略。

该服务检索由 pid 标识的 Cobalt 进程的调度策略。

如果 pid 未标识现有的 Cobalt 线程/进程,则该服务回退到常规的 sched_getscheduler() 服务。

参数:

  • pid: 目标进程/线程。

返回值:

  • 成功时返回 0
  • 出错时返回错误号:
    • ESRCH: 找不到 pid
    • EINVAL: pid 为负数;
    • EFAULT: param_ex 是无效地址。

标签:

  • thread-unrestricted

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <sched.h>
#include <stdlib.h>
#include <errno.h>

int main() {
    // 获取当前进程的调度策略
    int policy = sched_getscheduler(0);
    if (policy == -1) {
        perror("sched_getscheduler failed");
        exit(EXIT_FAILURE);
    }

    // 根据获取的策略打印对应的调度策略名称
    switch (policy) {
        case SCHED_OTHER:
            printf("Current policy: SCHED_OTHER\n");
            break;
        case SCHED_FIFO:
            printf("Current policy: SCHED_FIFO\n");
            break;
        case SCHED_RR:
            printf("Current policy: SCHED_RR\n");
            break;
        default:
            printf("Current policy: Unknown (%d)\n", policy);
            break;
    }

    return 0;
}

sched_getscheduler_ex()

int sched_getscheduler_ex (pid_t pid, int *policy_r, struct sched_param_ex *param_ex)

获取进程的扩展调度策略。

该服务是 sched_getscheduler() 服务的扩展版本,支持 Cobalt 特定和/或主机 Linux 环境不可用的附加调度策略。它检索由 pid 标识的 Cobalt 进程/线程的调度策略及相关的调度参数(例如优先级)。

参数:

  • pid: 查询的进程/线程。如果为零,则假定为当前线程。
  • policy_r: 一个指向变量的指针,用于接收 pid 的当前调度策略。
  • param_ex: 一个指向结构的指针,用于接收 pid 的当前调度参数。

返回值:

  • 成功时返回 0
  • 出错时返回错误号:
    • ESRCH: pid 不是 Cobalt 线程;
    • EINVAL: pid 为负数或 param_ex 为 NULL;
    • EFAULT: param_ex 是无效地址。

标签:

  • thread-unrestricted

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <sched.h>
#include <stdlib.h>
#include <errno.h>
#include <cobalt/sched.h>

int main() {
    struct sched_param_ex param;
    int policy;

    // 获取当前进程的调度策略和参数
    sched_getscheduler_ex(0,&policy,&param);
    if (policy == -1) {
        perror("sched_getscheduler failed");
        exit(EXIT_FAILURE);
    }

    // 根据获取的策略打印对应的调度策略名称
    switch (policy) {
        case SCHED_OTHER:
            printf("Current policy: SCHED_OTHER\n");
            break;
        case SCHED_FIFO:
            printf("Current policy: SCHED_FIFO\n");
            break;
        case SCHED_RR:
            printf("Current policy: SCHED_RR\n");
            break;
        default:
            printf("Current policy: Unknown (%d)\n", policy);
            break;
    }
    // 打印当前进程的调度优先级
    printf("Current priority: %d\n", param.sched_priority);

    return 0;
}

sched_setscheduler()

int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param)

设置指定进程的调度策略和参数。

该服务将由 pid 标识的 Cobalt 进程的调度策略设置为 policy,并将其调度参数(即优先级)设置为 param 指向的值。

如果传递当前的 Linux 线程 ID(参见 gettid(2)),该服务会将当前的常规 POSIX 线程转换为 Cobalt 线程。如果 pid 既不是当前线程的标识符,也不是现有 Cobalt 线程的标识符,则该服务回退到常规的 sched_setscheduler() 服务。

参数:

  • pid: 目标进程/线程;
  • policy: 调度策略,SCHED_FIFOSCHED_RRSCHED_OTHER 之一;
  • param: 调度参数地址。

返回值:

  • 成功时返回 0
  • 出错时返回错误号:
    • ESRCH: pid 无效;
    • EINVAL: policyparam->sched_priority 无效;
    • EAGAIN: 系统堆内存不足,请增加 CONFIG_XENO_OPT_SYS_HEAPSZ
    • EFAULT: param 是无效地址。

注意:

  • 参见 sched_setscheduler_ex()

标签:

  • thread-unrestrictedswitch-secondaryswitch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <sched.h>
#include <stdlib.h>
#include <errno.h>

int main() {
    // 获取当前进程的调度策略
    int policy = sched_getscheduler(0);
    if (policy == -1) {
        perror("sched_getscheduler failed");
        exit(EXIT_FAILURE);
    }
     // 获取当前进程的调度参数
    struct sched_param param;
    if (sched_getparam(0, &param) == -1) {
        perror("sched_getparam failed");
        exit(EXIT_FAILURE);
    }
    printf("Befor-Set : policy[%d] priority[%d]\n",policy, param.sched_priority);

    param.sched_priority = 15;
    if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
        perror("sched_getparam failed");
        exit(EXIT_FAILURE);
    }
    policy = sched_getscheduler(0);
    if (policy == -1) {
        perror("sched_getscheduler failed");
        exit(EXIT_FAILURE);
    }
     // 获取当前进程的调度参数
    if (sched_getparam(0, &param) == -1) {
        perror("sched_getparam failed");
        exit(EXIT_FAILURE);
    }
    printf("After-Set : policy[%d] priority[%d]\n",policy, param.sched_priority);

    return 0;
}

sched_setscheduler_ex()

int sched_setscheduler_ex (pid_t pid, int policy, const struct sched_param_ex *param_ex)

设置进程的扩展调度策略。

该服务是 sched_setscheduler() 服务的扩展版本,支持 Cobalt 特定和/或主机 Linux 环境不可用的附加调度策略。它将由 pid 标识的 Cobalt 进程/线程的调度策略设置为 policy 的值,并将其调度参数(例如优先级)设置为 param_ex 指向的值。

如果传递当前的 Linux 线程 ID 或零(参见 gettid(2)),该服务可能会将当前的常规 POSIX 线程转换为 Cobalt 线程。

参数:

  • pid: 目标进程/线程。如果为零,则假定为当前线程。
  • policy: 调度策略,SCHED_WEAKSCHED_FIFOSCHED_COBALTSCHED_RRSCHED_SPORADICSCHED_TPSCHED_QUOTASCHED_NORMAL 之一。
  • param_ex: 调度参数的地址。作为一个特殊例外,负的 sched_priority 值被解释为 policy 中给定的 SCHED_WEAK,使用该参数的绝对值作为弱优先级级别。

当启用 CONFIG_XENO_OPT_SCHED_WEAK 时,SCHED_WEAK 在 [0..99] 范围内(包括 0 和 99)展示优先级级别。否则,对于 SCHED_WEAK 策略,sched_priority 必须为零。

返回值:

  • 成功时返回 0
  • 出错时返回错误号:
    • ESRCH: 找不到 pid
    • EINVAL: pid 为负数,param_ex 为 NULL,policyparam_ex->sched_priority 无效;
    • EAGAIN: 系统堆内存不足,请增加 CONFIG_XENO_OPT_SYS_HEAPSZ
    • EFAULT: param_ex 是无效地址;

注意:

  • 参见 sched_setscheduler()

标签:

  • thread-unrestrictedswitch-secondaryswitch-primary

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <cobalt/sched.h>

int main() {
    struct sched_param param;
    int policy;
    // 获取当前进程的调度策略和参数
    sched_getscheduler_ex(0,&policy,&param);
    if (policy == -1) {
        perror("sched_getscheduler failed");
        exit(EXIT_FAILURE);
    }
    printf("Befor-Set : policy[%d] priority[%d]\n",policy, param.sched_priority);

    param.sched_priority = 15;
    if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
        perror("sched_getparam failed");
        exit(EXIT_FAILURE);
    }

    sched_getscheduler_ex(0,&policy,&param);
    if (policy == -1) {
        perror("sched_getscheduler failed");
        exit(EXIT_FAILURE);
    }
    printf("After-Set : policy[%d] priority[%d]\n",policy, param.sched_priority);

    return 0;
}

sched_yield()

int sched_yield (void)

让出处理器。

此函数将当前线程移动到其优先级组的末尾。

返回值:

  • 0

标签:

  • thread-unrestrictedswitch-primary

引用 XNRELAXXNWEAK

pthread_yield() 引用。

示例代码

c{filename="app.c"} 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sched.h>
#include <unistd.h>

#define NUM_THREADS 3

void* thread_function(void* arg) {
    int thread_id = *((int*)arg);
    for (int i = 0; i < 5; ++i) {
        printf("Thread %d: working...\n", thread_id);
        // 模拟工作
        usleep(100000); // 睡眠 100 毫秒
        
        // 调用 sched_yield() 放弃 CPU
        printf("Thread %d: yielding...\n", thread_id);
        sched_yield();
    }
    return NULL;
}

int main() {
    pthread_t threads[NUM_THREADS];
    int thread_ids[NUM_THREADS];

    // 创建多个线程
    for (int i = 0; i < NUM_THREADS; ++i) {
        thread_ids[i] = i + 1;
        if (pthread_create(&threads[i], NULL, thread_function, &thread_ids[i]) != 0) {
            perror("Failed to create thread");
            exit(EXIT_FAILURE);
        }
    }

    // 等待所有线程完成
    for (int i = 0; i < NUM_THREADS; ++i) {
        pthread_join(threads[i], NULL);
    }

    printf("All threads have finished.\n");
    return 0;
}

最近修改: 2025-09-30