1. 概述
sched_*
函数族是 Linux 系统中用于进程调度控制的一系列系统调用。可以把调度器想象成”CPU 时间片的分配管理员”——它决定哪个进程什么时候获得 CPU 时间,就像交通警察决定哪辆车什么时候可以通过路口一样。
这些函数提供了对进程调度策略、优先级、CPU 亲和性等方面的精细控制,是实现高性能、实时应用的重要工具。
2. sched_* 函数列表
2.1 基础调度函数
- sched_yield: 让出当前 CPU 时间片
- sched_getscheduler: 获取进程调度策略
- sched_setscheduler: 设置进程调度策略
- sched_getparam: 获取进程调度参数
- sched_setparam: 设置进程调度参数
2.2 CPU 亲和性函数
- sched_getaffinity: 获取进程 CPU 亲和性
- sched_setaffinity: 设置进程 CPU 亲和性
2.3 优先级函数
- sched_get_priority_min: 获取指定策略的最小优先级
- sched_get_priority_max: 获取指定策略的最大优先级
- sched_rr_get_interval: 获取轮转调度的时间片间隔
2.4 CPU 信息函数
- sched_getcpu: 获取当前 CPU 编号
3. 调度策略详解
3.1 调度策略类型
策略 | 值 | 说明 |
---|---|---|
SCHED_OTHER | 0 | 默认分时调度策略(CFS) |
SCHED_FIFO | 1 | 先进先出实时调度策略 |
SCHED_RR | 2 | 轮转实时调度策略 |
SCHED_BATCH | 3 | 批处理调度策略 |
SCHED_IDLE | 5 | 空闲调度策略 |
SCHED_DEADLINE | 6 | 截止时间调度策略 |
3.2 调度策略特点
#include <sched.h>
#include <stdio.h>
void show_scheduling_policies() {
printf("=== 调度策略特点 ===\n");
printf("SCHED_OTHER (默认):\n");
printf(" • 用于普通进程\n");
printf(" • 完全公平调度器 (CFS)\n");
printf(" • 动态优先级调整\n");
printf(" • 适合交互式应用\n\n");
printf("SCHED_FIFO (实时 FIFO):\n");
printf(" • 实时调度策略\n");
printf(" • 高优先级进程一直运行直到阻塞或主动让出\n");
printf(" • 不会时间片轮转\n");
printf(" • 需要 root 权限\n\n");
printf("SCHED_RR (实时轮转):\n");
printf(" • 实时调度策略\n");
printf(" • 时间片轮转调度\n");
printf(" • 相同优先级进程轮流执行\n");
printf(" • 需要 root 权限\n\n");
printf("SCHED_BATCH (批处理):\n");
printf(" • 用于批处理任务\n");
printf(" • 减少唤醒频率\n");
printf(" • 适合长时间运行的非交互任务\n\n");
printf("SCHED_IDLE (空闲):\n");
printf(" • 用于极低优先级任务\n");
printf(" • 只在系统空闲时运行\n");
printf(" • 不影响其他进程\n\n");
printf("SCHED_DEADLINE (截止时间):\n");
printf(" • 基于截止时间的调度\n");
printf(" • 确保任务按时完成\n");
printf(" • 需要特殊配置\n");
printf(" • Linux 3.14+\n\n");
}
4. 函数详细介绍
4.1 sched_yield – 让出 CPU 时间片
函数原型
#include <sched.h>
int sched_yield(void);
功能
让出当前进程的 CPU 时间片,允许其他同优先级的进程运行。
参数
无参数
返回值
- 成功: 返回 0
- 失败: 返回 -1(实际上很少失败)
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <time.h>
#include <errno.h>
// 消耗 CPU 的函数
void consume_cpu(int seconds) {
time_t start = time(NULL);
volatile long sum = 0;
while (time(NULL) - start < seconds) {
for (long i = 0; i < 1000000; i++) {
sum += i;
}
}
}
int main() {
printf("=== sched_yield 示例 ===\n\n");
// 获取当前进程 ID 和 CPU 信息
printf("进程 ID: %d\n", getpid());
printf("父进程 ID: %d\n", getppid());
// 获取当前 CPU 编号(如果有支持)
int current_cpu = sched_getcpu();
if (current_cpu != -1) {
printf("当前 CPU: %d\n", current_cpu);
} else {
printf("无法获取当前 CPU 信息\n");
}
printf("\n1. 不使用 sched_yield 的 CPU 消耗:\n");
printf(" 开始消耗 CPU 时间...\n");
time_t start_time = time(NULL);
consume_cpu(3); // 消耗 3 秒 CPU 时间
time_t end_time = time(NULL);
printf(" 消耗完成,用时 %ld 秒\n", end_time - start_time);
printf("\n2. 使用 sched_yield 的 CPU 消耗:\n");
printf(" 开始消耗 CPU 时间并让出时间片...\n");
start_time = time(NULL);
time_t yield_start = time(NULL);
while (time(NULL) - yield_start < 3) {
// 消耗一些 CPU 时间
volatile long sum = 0;
for (long i = 0; i < 500000; i++) {
sum += i;
}
// 让出 CPU 时间片
if (sched_yield() == -1) {
perror("sched_yield 失败");
}
}
end_time = time(NULL);
printf(" 消耗完成,用时 %ld 秒\n", end_time - start_time);
printf("\n3. sched_yield 的实际效果:\n");
printf(" • 允许其他同优先级进程运行\n");
printf(" • 改善系统响应性\n");
printf(" • 减少饥饿现象\n");
printf(" • 适合协作式多任务\n");
printf("\n=== sched_yield 使用场景 ===\n");
printf("1. 长时间运行的循环\n");
printf("2. 忙等待循环\n");
printf("3. 协作式多任务\n");
printf("4. 实时应用中的主动让出\n");
printf("5. 负载均衡\n");
printf("\n=== 注意事项 ===\n");
printf("1. 不保证立即切换到其他进程\n");
printf("2. 只影响同优先级进程\n");
printf("3. 过度使用可能影响性能\n");
printf("4. 不是强制调度切换\n");
printf("5. 应该谨慎使用\n");
return 0;
}
4.2 sched_getscheduler/sched_setscheduler – 调度策略控制
函数原型
#include <sched.h>
int sched_getscheduler(pid_t pid);
int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
sched_param 结构体
struct sched_param {
int sched_priority; // 调度优先级
// 对于 SCHED_DEADLINE,还有额外字段
};
功能
- sched_getscheduler: 获取指定进程的调度策略
- sched_setscheduler: 设置指定进程的调度策略和参数
参数
- pid: 进程 ID(0 表示当前进程)
- policy: 调度策略
- param: 指向调度参数的指针
返回值
- sched_getscheduler: 成功返回调度策略,失败返回 -1
- sched_setscheduler: 成功返回 0,失败返回 -1
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <errno.h>
#include <string.h>
#include <sys/resource.h>
// 将调度策略转换为字符串
const char* policy_to_string(int policy) {
switch (policy) {
case SCHED_OTHER: return "SCHED_OTHER (默认)";
case SCHED_FIFO: return "SCHED_FIFO (实时FIFO)";
case SCHED_RR: return "SCHED_RR (实时轮转)";
case SCHED_BATCH: return "SCHED_BATCH (批处理)";
case SCHED_IDLE: return "SCHED_IDLE (空闲)";
case SCHED_DEADLINE: return "SCHED_DEADLINE (截止时间)";
default: return "未知策略";
}
}
// 显示进程调度信息
void show_process_scheduling_info(pid_t pid, const char *description) {
printf("=== %s ===\n", description);
if (pid == 0) {
printf("进程: 当前进程 (PID: %d)\n", getpid());
} else {
printf("进程: PID %d\n", pid);
}
// 获取调度策略
int policy = sched_getscheduler(pid);
if (policy == -1) {
perror("获取调度策略失败");
return;
}
printf("调度策略: %s\n", policy_to_string(policy));
// 获取调度参数
struct sched_param param;
if (sched_getparam(pid, ¶m) == 0) {
printf("调度优先级: %d\n", param.sched_priority);
// 显示优先级范围
int min_priority = sched_get_priority_min(policy);
int max_priority = sched_get_priority_max(policy);
if (min_priority != -1 && max_priority != -1) {
printf("优先级范围: %d - %d\n", min_priority, max_priority);
if (param.sched_priority < min_priority || param.sched_priority > max_priority) {
printf("⚠ 当前优先级超出范围\n");
}
}
} else {
perror("获取调度参数失败");
}
// 获取进程优先级
errno = 0;
int nice_value = getpriority(PRIO_PROCESS, pid);
if (errno == 0) {
printf("Nice 值: %d\n", nice_value);
}
printf("\n");
}
// 设置调度策略
int set_process_scheduling_policy(pid_t pid, int policy, int priority) {
struct sched_param param;
param.sched_priority = priority;
printf("设置进程调度策略:\n");
printf(" 进程 ID: %d\n", pid ? pid : getpid());
printf(" 调度策略: %s\n", policy_to_string(policy));
printf(" 调度优先级: %d\n", priority);
if (sched_setscheduler(pid, policy, ¶m) == 0) {
printf("✓ 调度策略设置成功\n");
return 0;
} else {
switch (errno) {
case EPERM:
printf("✗ 权限不足: 需要 root 权限设置实时策略\n");
break;
case EINVAL:
printf("✗ 参数无效: 策略或优先级无效\n");
break;
case ESRCH:
printf("✗ 进程不存在\n");
break;
default:
printf("✗ 设置失败: %s\n", strerror(errno));
break;
}
return -1;
}
}
int main() {
printf("=== sched_getscheduler/sched_setscheduler 示例 ===\n\n");
// 显示当前用户信息
printf("用户信息:\n");
printf(" UID: %d\n", getuid());
printf(" EUID: %d\n", geteuid());
printf(" GID: %d\n", getgid());
printf(" EGID: %d\n", getegid());
printf("\n");
// 显示初始调度信息
show_process_scheduling_info(0, "初始调度信息");
// 显示各种调度策略的优先级范围
printf("=== 各种调度策略的优先级范围 ===\n");
int policies[] = {SCHED_OTHER, SCHED_FIFO, SCHED_RR, SCHED_BATCH, SCHED_IDLE};
int num_policies = sizeof(policies) / sizeof(policies[0]);
for (int i = 0; i < num_policies; i++) {
int min_priority = sched_get_priority_min(policies[i]);
int max_priority = sched_get_priority_max(policies[i]);
printf("%-20s: 最小优先级 %3d, 最大优先级 %3d\n",
policy_to_string(policies[i]), min_priority, max_priority);
}
printf("\n");
// 演示调度策略设置(需要 root 权限)
printf("=== 调度策略设置演示 ===\n");
// 1. 尝试设置 SCHED_FIFO(需要 root 权限)
printf("1. 尝试设置 SCHED_FIFO 策略:\n");
if (set_process_scheduling_policy(0, SCHED_FIFO, 10) == 0) {
show_process_scheduling_info(0, "设置 SCHED_FIFO 后");
} else {
printf(" 说明: SCHED_FIFO 需要 root 权限\n");
}
// 2. 尝试设置 SCHED_RR(需要 root 权限)
printf("\n2. 尝试设置 SCHED_RR 策略:\n");
if (set_process_scheduling_policy(0, SCHED_RR, 15) == 0) {
show_process_scheduling_info(0, "设置 SCHED_RR 后");
} else {
printf(" 说明: SCHED_RR 需要 root 权限\n");
}
// 3. 尝试设置 SCHED_BATCH
printf("\n3. 尝试设置 SCHED_BATCH 策略:\n");
if (set_process_scheduling_policy(0, SCHED_BATCH, 0) == 0) {
show_process_scheduling_info(0, "设置 SCHED_BATCH 后");
} else {
printf(" 说明: 可能需要适当权限\n");
}
// 4. 恢复默认策略
printf("\n4. 恢复默认 SCHED_OTHER 策略:\n");
struct sched_param default_param = {0};
if (sched_setscheduler(0, SCHED_OTHER, &default_param) == 0) {
printf("✓ 成功恢复默认调度策略\n");
show_process_scheduling_info(0, "恢复默认策略后");
} else {
printf("✗ 恢复默认策略失败: %s\n", strerror(errno));
}
printf("\n=== 调度策略使用建议 ===\n");
printf("选择原则:\n");
printf("1. 普通应用: 使用 SCHED_OTHER(默认)\n");
printf("2. 实时应用: 使用 SCHED_FIFO 或 SCHED_RR\n");
printf("3. 批处理任务: 使用 SCHED_BATCH\n");
printf("4. 后台任务: 使用 SCHED_IDLE\n");
printf("5. 截止时间任务: 使用 SCHED_DEADLINE\n");
printf("\n");
printf("权限要求:\n");
printf("1. SCHED_OTHER/SCHED_BATCH/SCHED_IDLE: 普通权限\n");
printf("2. SCHED_FIFO/SCHED_RR: 需要 root 权限\n");
printf("3. SCHED_DEADLINE: 需要特殊配置\n");
printf("\n");
printf("性能影响:\n");
printf("1. 实时策略: 更高优先级,更低延迟\n");
printf("2. 批处理策略: 更低唤醒频率,更好吞吐\n");
printf("3. 空闲策略: 不影响其他进程\n");
printf("4. 默认策略: 平衡性能和公平性\n");
return 0;
}
4.3 sched_getaffinity/sched_setaffinity – CPU 亲和性控制
函数原型
#define _GNU_SOURCE
#include <sched.h>
int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask);
CPU 集合操作宏
void CPU_ZERO(cpu_set_t *set); // 清空 CPU 集合
void CPU_SET(int cpu, cpu_set_t *set); // 设置 CPU
void CPU_CLR(int cpu, cpu_set_t *set); // 清除 CPU
int CPU_ISSET(int cpu, cpu_set_t *set); // 检查 CPU 是否设置
int CPU_COUNT(cpu_set_t *set); // 计算设置的 CPU 数量
功能
- sched_getaffinity: 获取进程的 CPU 亲和性掩码
- sched_setaffinity: 设置进程的 CPU 亲和性掩码
参数
- pid: 进程 ID(0 表示当前进程)
- cpusetsize: CPU 集合的大小
- mask: 指向 CPU 集合的指针
返回值
- 成功: 返回 0
- 失败: 返回 -1,并设置相应的 errno
示例代码
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <errno.h>
#include <string.h>
// 显示 CPU 集合信息
void show_cpu_set_info(const cpu_set_t *cpu_set, const char *description) {
printf("=== %s ===\n", description);
int cpu_count = CPU_COUNT((cpu_set_t*)cpu_set);
printf("CPU 数量: %d\n", cpu_count);
printf("CPU 列表: ");
int printed = 0;
for (int i = 0; i < CPU_SETSIZE; i++) {
if (CPU_ISSET(i, (cpu_set_t*)cpu_set)) {
if (printed > 0) printf(", ");
printf("%d", i);
printed++;
}
}
if (printed == 0) {
printf("无");
}
printf("\n\n");
}
// 获取系统 CPU 信息
void show_system_cpu_info() {
printf("=== 系统 CPU 信息 ===\n");
// 获取在线 CPU 数量
int online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
printf("在线 CPU 数量: %d\n", online_cpus);
// 获取配置的 CPU 数量
int conf_cpus = sysconf(_SC_NPROCESSORS_CONF);
printf("配置 CPU 数量: %d\n", conf_cpus);
// 显示当前进程的 CPU 亲和性
cpu_set_t current_set;
CPU_ZERO(¤t_set);
if (sched_getaffinity(0, sizeof(current_set), ¤t_set) == 0) {
show_cpu_set_info(¤t_set, "当前进程 CPU 亲和性");
} else {
perror("获取 CPU 亲和性失败");
}
}
// 设置 CPU 亲和性
int set_process_cpu_affinity(pid_t pid, const int *cpu_list, int cpu_count) {
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
printf("设置 CPU 亲和性:\n");
printf(" 进程 ID: %d\n", pid ? pid : getpid());
printf(" CPU 列表: ");
for (int i = 0; i < cpu_count; i++) {
if (i > 0) printf(", ");
printf("%d", cpu_list[i]);
CPU_SET(cpu_list[i], &cpu_set);
}
printf("\n");
if (sched_setaffinity(pid, sizeof(cpu_set), &cpu_set) == 0) {
printf("✓ CPU 亲和性设置成功\n");
return 0;
} else {
printf("✗ CPU 亲和性设置失败: %s\n", strerror(errno));
return -1;
}
}
// 创建 CPU 绑定的测试线程
void* cpu_bound_worker(void *arg) {
int worker_id = *(int*)arg;
printf("工作线程 %d 启动\n", worker_id);
// 获取线程的 CPU 信息
int current_cpu = sched_getcpu();
if (current_cpu != -1) {
printf(" 工作线程 %d 运行在 CPU %d 上\n", worker_id, current_cpu);
}
// 执行一些 CPU 密集型任务
volatile long sum = 0;
for (long i = 0; i < 10000000; i++) {
sum += i;
// 偶尔检查 CPU 变化
if (i % 1000000 == 0) {
int new_cpu = sched_getcpu();
if (new_cpu != current_cpu && new_cpu != -1) {
printf(" 工作线程 %d 从 CPU %d 切换到 CPU %d\n",
worker_id, current_cpu, new_cpu);
current_cpu = new_cpu;
}
}
}
printf("工作线程 %d 完成\n", worker_id);
return NULL;
}
int main() {
printf("=== sched_getaffinity/sched_setaffinity 示例 ===\n\n");
// 显示系统信息
show_system_cpu_info();
// 1. 获取当前进程的 CPU 亲和性
printf("1. 获取当前进程 CPU 亲和性:\n");
cpu_set_t initial_set;
CPU_ZERO(&initial_set);
if (sched_getaffinity(0, sizeof(initial_set), &initial_set) == 0) {
show_cpu_set_info(&initial_set, "初始 CPU 亲和性");
} else {
perror("获取初始 CPU 亲和性失败");
}
// 2. 设置 CPU 亲和性(绑定到特定 CPU)
printf("2. 设置 CPU 亲和性:\n");
// 获取系统 CPU 数量
int online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
printf("系统在线 CPU 数量: %d\n", online_cpus);
if (online_cpus > 1) {
// 绑定到第一个 CPU
int single_cpu[] = {0};
if (set_process_cpu_affinity(0, single_cpu, 1) == 0) {
cpu_set_t new_set;
CPU_ZERO(&new_set);
if (sched_getaffinity(0, sizeof(new_set), &new_set) == 0) {
show_cpu_set_info(&new_set, "设置后 CPU 亲和性");
}
}
// 绑定到前两个 CPU
printf("绑定到前两个 CPU:\n");
int two_cpus[] = {0, 1};
if (set_process_cpu_affinity(0, two_cpus, 2) == 0) {
cpu_set_t new_set;
CPU_ZERO(&new_set);
if (sched_getaffinity(0, sizeof(new_set), &new_set) == 0) {
show_cpu_set_info(&new_set, "绑定到前两个 CPU 后");
}
}
} else {
printf("系统只有一个 CPU,跳过 CPU 绑定测试\n");
}
// 3. 恢复初始 CPU 亲和性
printf("3. 恢复初始 CPU 亲和性:\n");
if (sched_setaffinity(0, sizeof(initial_set), &initial_set) == 0) {
printf("✓ 成功恢复初始 CPU 亲和性\n");
cpu_set_t restored_set;
CPU_ZERO(&restored_set);
if (sched_getaffinity(0, sizeof(restored_set), &restored_set) == 0) {
show_cpu_set_info(&restored_set, "恢复后 CPU 亲和性");
}
} else {
printf("✗ 恢复初始 CPU 亲和性失败: %s\n", strerror(errno));
}
// 4. 显示 CPU 亲和性的好处
printf("=== CPU 亲和性的好处 ===\n");
printf("性能优化:\n");
printf("1. 减少 CPU 缓存失效\n");
printf("2. 提高缓存命中率\n");
printf("3. 降低上下文切换开销\n");
printf("4. 改善 NUMA 访问模式\n");
printf("5. 提高多核应用性能\n");
printf("\n");
printf("应用场景:\n");
printf("1. 高性能计算应用\n");
printf("2. 实时系统\n");
printf("3. 数据库服务器\n");
printf("4. 游戏服务器\n");
printf("5. 科学计算\n");
printf("6. 音视频处理\n");
printf("\n");
printf("注意事项:\n");
printf("1. 过度限制可能影响负载均衡\n");
printf("2. NUMA 架构需要考虑内存亲和性\n");
printf("3. 应该根据应用特点合理设置\n");
printf("4. 避免与其他进程争抢 CPU\n");
printf("5. 监控系统整体性能\n");
return 0;
}
4.4 sched_get_priority_min/sched_get_priority_max – 优先级范围查询
函数原型
#include <sched.h>
int sched_get_priority_min(int policy);
int sched_get_priority_max(int policy);
功能
获取指定调度策略的最小和最大优先级值。
参数
- policy: 调度策略
返回值
- 成功: 返回对应的优先级值
- 失败: 返回 -1,并设置相应的 errno
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <errno.h>
#include <string.h>
// 显示调度策略优先级范围
void show_policy_priority_range(int policy, const char *policy_name) {
int min_priority = sched_get_priority_min(policy);
int max_priority = sched_get_priority_max(policy);
printf("%-20s: ", policy_name);
if (min_priority == -1 || max_priority == -1) {
printf("不支持 (%s)\n", strerror(errno));
} else {
printf("最小优先级 %3d, 最大优先级 %3d", min_priority, max_priority);
if (min_priority == max_priority) {
printf(" (固定优先级)");
} else if (min_priority < max_priority) {
printf(" (动态优先级范围)");
}
printf("\n");
}
}
// 显示所有调度策略的优先级范围
void show_all_policy_ranges() {
printf("=== 所有调度策略优先级范围 ===\n");
struct {
int policy;
const char *name;
} policies[] = {
{SCHED_OTHER, "SCHED_OTHER"},
{SCHED_FIFO, "SCHED_FIFO"},
{SCHED_RR, "SCHED_RR"},
{SCHED_BATCH, "SCHED_BATCH"},
{SCHED_IDLE, "SCHED_IDLE"},
{SCHED_DEADLINE, "SCHED_DEADLINE"},
{-1, NULL}
};
for (int i = 0; policies[i].name; i++) {
show_policy_priority_range(policies[i].policy, policies[i].name);
}
printf("\n");
}
// 优先级验证函数
int validate_priority_for_policy(int policy, int priority) {
int min_priority = sched_get_priority_min(policy);
int max_priority = sched_get_priority_max(policy);
if (min_priority == -1 || max_priority == -1) {
return -1; // 策略不支持
}
if (priority >= min_priority && priority <= max_priority) {
return 0; // 优先级有效
} else {
return 1; // 优先级无效
}
}
// 显示优先级验证结果
void show_priority_validation(int policy, int priority) {
const char *policy_name = NULL;
switch (policy) {
case SCHED_OTHER: policy_name = "SCHED_OTHER"; break;
case SCHED_FIFO: policy_name = "SCHED_FIFO"; break;
case SCHED_RR: policy_name = "SCHED_RR"; break;
case SCHED_BATCH: policy_name = "SCHED_BATCH"; break;
case SCHED_IDLE: policy_name = "SCHED_IDLE"; break;
case SCHED_DEADLINE: policy_name = "SCHED_DEADLINE"; break;
default: policy_name = "未知策略"; break;
}
printf("验证 %s 策略优先级 %d: ", policy_name, priority);
int result = validate_priority_for_policy(policy, priority);
switch (result) {
case -1:
printf("策略不支持\n");
break;
case 0:
printf("✓ 有效\n");
break;
case 1:
printf("✗ 无效\n");
break;
}
}
int main() {
printf("=== sched_get_priority_min/max 示例 ===\n\n");
// 显示所有策略的优先级范围
show_all_policy_ranges();
// 显示当前进程信息
printf("当前进程信息:\n");
printf(" 进程 ID: %d\n", getpid());
printf(" 父进程 ID: %d\n", getppid());
printf(" 用户 ID: %d\n", getuid());
printf(" 组 ID: %d\n", getgid());
// 获取当前进程调度策略
int current_policy = sched_getscheduler(0);
if (current_policy != -1) {
printf(" 当前调度策略: %d ", current_policy);
switch (current_policy) {
case SCHED_OTHER: printf("(SCHED_OTHER)\n"); break;
case SCHED_FIFO: printf("(SCHED_FIFO)\n"); break;
case SCHED_RR: printf("(SCHED_RR)\n"); break;
case SCHED_BATCH: printf("(SCHED_BATCH)\n"); break;
case SCHED_IDLE: printf("(SCHED_IDLE)\n"); break;
case SCHED_DEADLINE: printf("(SCHED_DEADLINE)\n"); break;
default: printf("(未知)\n"); break;
}
// 获取当前进程优先级
struct sched_param current_param;
if (sched_getparam(0, ¤t_param) == 0) {
printf(" 当前优先级: %d\n", current_param.sched_priority);
// 验证当前优先级
show_priority_validation(current_policy, current_param.sched_priority);
}
} else {
perror("获取当前调度策略失败");
}
printf("\n");
// 验证不同策略的优先级
printf("=== 优先级验证示例 ===\n");
// SCHED_OTHER 策略
printf("SCHED_OTHER 策略:\n");
show_priority_validation(SCHED_OTHER, 0); // 有效
show_priority_validation(SCHED_OTHER, -1); // 无效
show_priority_validation(SCHED_OTHER, 10); // 无效
// SCHED_FIFO 策略
printf("\nSCHED_FIFO 策略:\n");
show_priority_validation(SCHED_FIFO, 10); // 可能有效
show_priority_validation(SCHED_FIFO, 50); // 可能有效
show_priority_validation(SCHED_FIFO, 99); // 可能有效
show_priority_validation(SCHED_FIFO, 100); // 可能无效
// SCHED_RR 策略
printf("\nSCHED_RR 策略:\n");
show_priority_validation(SCHED_RR, 10); // 可能有效
show_priority_validation(SCHED_RR, 50); // 可能有效
show_priority_validation(SCHED_RR, 99); // 可能有效
show_priority_validation(SCHED_RR, 100); // 可能无效
// SCHED_BATCH 策略
printf("\nSCHED_BATCH 策略:\n");
show_priority_validation(SCHED_BATCH, 0); // 有效
show_priority_validation(SCHED_BATCH, -1); // 无效
show_priority_validation(SCHED_BATCH, 10); // 无效
// SCHED_IDLE 策略
printf("\nSCHED_IDLE 策略:\n");
show_priority_validation(SCHED_IDLE, 0); // 有效
show_priority_validation(SCHED_IDLE, -1); // 无效
show_priority_validation(SCHED_IDLE, 10); // 无效
printf("\n=== 优先级使用建议 ===\n");
printf("优先级设置原则:\n");
printf("1. 了解策略的优先级范围\n");
printf("2. 合理分配优先级值\n");
printf("3. 避免优先级反转\n");
printf("4. 考虑系统整体平衡\n");
printf("5. 验证优先级的有效性\n");
printf("\n");
printf("实时策略优先级:\n");
printf("1. SCHED_FIFO/SCHED_RR: 1-99 (通常)\n");
printf("2. 数值越大优先级越高\n");
printf("3. 需要 root 权限\n");
printf("4. 谨慎使用高优先级\n");
printf("5. 避免独占 CPU\n");
printf("\n");
printf("普通策略优先级:\n");
printf("1. SCHED_OTHER: 通常为 0\n");
printf("2. 通过 nice 值调整\n");
printf("3. 使用动态优先级\n");
printf("4. 平衡系统负载\n");
printf("5. 适合交互式应用\n");
return 0;
}
4.5 sched_rr_get_interval – 轮转调度时间片
函数原型
#include <sched.h>
int sched_rr_get_interval(pid_t pid, struct timespec *tp);
功能
获取 SCHED_RR 策略的时间片长度。
参数
- pid: 进程 ID(0 表示当前进程)
- tp: 指向 timespec 结构体的指针,用于存储时间片长度
返回值
- 成功: 返回 0
- 失败: 返回 -1,并设置相应的 errno
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <errno.h>
#include <string.h>
#include <time.h>
// 显示时间片信息
void show_timeslice_info(const struct timespec *interval, const char *description) {
printf("=== %s ===\n", description);
if (interval->tv_sec == 0 && interval->tv_nsec == 0) {
printf("时间片长度: 未设置\n");
} else {
printf("时间片长度: %ld.%09ld 秒\n",
(long)interval->tv_sec, (long)interval->tv_nsec);
printf("时间片长度: %.3f 毫秒\n",
(double)interval->tv_sec * 1000 + (double)interval->tv_nsec / 1000000);
printf("时间片长度: %.3f 微秒\n",
(double)interval->tv_sec * 1000000 + (double)interval->tv_nsec / 1000);
printf("时间片长度: %ld 纳秒\n",
(long)interval->tv_sec * 1000000000 + (long)interval->tv_nsec);
}
printf("\n");
}
// 获取 RR 调度时间片
int get_rr_timeslice(pid_t pid) {
struct timespec interval;
printf("获取 SCHED_RR 时间片长度:\n");
printf(" 进程 ID: %d\n", pid ? pid : getpid());
if (sched_rr_get_interval(pid, &interval) == 0) {
show_timeslice_info(&interval, "RR 调度时间片");
return 0;
} else {
switch (errno) {
case EINVAL:
printf("✗ 进程不是 SCHED_RR 策略\n");
break;
case ESRCH:
printf("✗ 进程不存在\n");
break;
default:
printf("✗ 获取时间片失败: %s\n", strerror(errno));
break;
}
return -1;
}
}
// 比较不同策略的时间片
void compare_policy_intervals() {
printf("=== 不同策略时间片比较 ===\n");
// 获取当前进程时间片(假设是 SCHED_OTHER)
struct timespec current_interval;
if (sched_rr_get_interval(0, ¤t_interval) == 0) {
printf("当前进程时间片: %ld.%09ld 秒\n",
(long)current_interval.tv_sec, (long)current_interval.tv_nsec);
} else {
printf("当前进程时间片: 无法获取 (%s)\n", strerror(errno));
}
// 显示系统时间片配置
printf("\n系统时间片配置:\n");
// 读取内核参数
FILE *fp = fopen("/proc/sys/kernel/sched_rr_timeslice_ms", "r");
if (fp) {
char buffer[64];
if (fgets(buffer, sizeof(buffer), fp)) {
printf(" RR 时间片 (ms): %s", buffer);
}
fclose(fp);
} else {
printf(" RR 时间片: 无法读取系统配置\n");
}
// 显示其他相关配置
printf("其他相关配置:\n");
system("cat /proc/sys/kernel/sched_child_runs_first 2>/dev/null || echo ' 无法读取 sched_child_runs_first'");
system("cat /proc/sys/kernel/sched_autogroup_enabled 2>/dev/null || echo ' 无法读取 sched_autogroup_enabled'");
printf("\n");
}
int main() {
printf("=== sched_rr_get_interval 示例 ===\n\n");
// 显示系统信息
printf("系统信息:\n");
printf(" 内核版本: ");
system("uname -r | tr -d '\\n'");
printf("\n");
printf(" CPU 架构: ");
system("uname -m | tr -d '\\n'");
printf("\n");
printf(" 进程 ID: %d\n", getpid());
printf(" 父进程 ID: %d\n", getppid());
printf("\n");
// 1. 获取当前进程时间片
printf("1. 获取当前进程时间片:\n");
get_rr_timeslice(0);
// 2. 尝试获取不存在进程的时间片
printf("2. 尝试获取不存在进程的时间片:\n");
if (sched_rr_get_interval(999999, &(struct timespec){0}) == -1) {
if (errno == ESRCH) {
printf("✓ 正确处理不存在进程: ESRCH\n");
} else {
printf("✗ 意外错误: %s\n", strerror(errno));
}
}
// 3. 尝试获取非 RR 策略进程的时间片
printf("3. 尝试获取非 RR 策略进程的时间片:\n");
if (sched_rr_get_interval(0, &(struct timespec){0}) == -1) {
if (errno == EINVAL) {
printf("✓ 正确处理非 RR 策略进程: EINVAL\n");
printf(" 说明: 当前进程使用默认 SCHED_OTHER 策略\n");
} else {
printf("✗ 其他错误: %s\n", strerror(errno));
}
}
// 4. 显示系统时间片配置
compare_policy_intervals();
// 5. 显示时间片对性能的影响
printf("=== 时间片对性能的影响 ===\n");
printf("时间片长度的影响:\n");
printf("1. 较短时间片:\n");
printf(" • 更好的响应性\n");
printf(" • 更多上下文切换\n");
printf(" • 更低吞吐量\n");
printf(" • 更高延迟\n");
printf("\n");
printf("2. 较长时间片:\n");
printf(" • 更低响应性\n");
printf(" • 更少上下文切换\n");
printf(" • 更高吞吐量\n");
printf(" • 更低延迟\n");
printf("\n");
printf("3. 默认时间片:\n");
printf(" • 平衡响应性和吞吐量\n");
printf(" • 通常为 10-100ms\n");
printf(" • 适应大多数应用\n");
printf(" • 可配置调整\n");
printf("\n");
printf("应用场景:\n");
printf("1. 实时系统: 需要短时间片保证响应性\n");
printf("2. 批处理系统: 需要长时间片提高吞吐量\n");
printf("3. 交互式应用: 需要适中时间片平衡各方面\n");
printf("4. 服务器应用: 根据负载动态调整\n");
printf("5. 嵌入式系统: 根据硬件特性优化\n");
printf("\n");
printf("配置建议:\n");
printf("1. 监控上下文切换频率\n");
printf("2. 调整时间片适应应用特点\n");
printf("3. 考虑系统整体负载\n");
printf("4. 测试不同配置的性能\n");
printf("5. 避免极端配置影响系统稳定性\n");
return 0;
}
4.6 sched_getcpu – 获取当前 CPU 编号
函数原型
#define _GNU_SOURCE
#include <sched.h>
int sched_getcpu(void);
功能
获取调用线程当前运行的 CPU 编号。
参数
无参数
返回值
- 成功: 返回 CPU 编号(从 0 开始)
- 失败: 返回 -1,并设置相应的 errno
示例代码
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <sys/syscall.h>
// 获取 CPU 信息的辅助函数
void show_cpu_info() {
printf("=== CPU 信息 ===\n");
// 获取当前 CPU 编号
int current_cpu = sched_getcpu();
if (current_cpu != -1) {
printf("当前 CPU 编号: %d\n", current_cpu);
} else {
printf("无法获取当前 CPU 编号: %s\n", strerror(errno));
}
// 获取系统 CPU 数量
long online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
long conf_cpus = sysconf(_SC_NPROCESSORS_CONF);
printf("在线 CPU 数量: %ld\n", online_cpus);
printf("配置 CPU 数量: %ld\n", conf_cpus);
// 显示 CPU 信息
printf("CPU 详细信息:\n");
system("lscpu | head -10 2>/dev/null || echo '无法获取 CPU 详细信息'");
printf("\n");
}
// 线程函数,显示线程的 CPU 信息
void* thread_cpu_info(void* arg) {
int thread_id = *(int*)arg;
int initial_cpu, current_cpu;
// 获取初始 CPU
initial_cpu = sched_getcpu();
printf("线程 %d:\n", thread_id);
printf(" 初始 CPU: %d\n", initial_cpu);
// 执行一些工作并检查 CPU 变化
volatile long sum = 0;
for (long i = 0; i < 10000000; i++) {
sum += i;
// 偶尔检查 CPU 变化
if (i % 1000000 == 0) {
current_cpu = sched_getcpu();
if (current_cpu != initial_cpu && current_cpu != -1) {
printf(" 线程 %d 从 CPU %d 切换到 CPU %d\n",
thread_id, initial_cpu, current_cpu);
initial_cpu = current_cpu;
}
}
}
// 最终 CPU
current_cpu = sched_getcpu();
printf(" 最终 CPU: %d\n", current_cpu);
printf(" 线程 %d 完成\n", thread_id);
return NULL;
}
// CPU 绑定测试
void test_cpu_binding() {
printf("=== CPU 绑定测试 ===\n");
// 获取系统 CPU 数量
long online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
if (online_cpus <= 1) {
printf("系统只有一个 CPU,跳过绑定测试\n");
return;
}
// 创建多个线程
pthread_t threads[4];
int thread_ids[4] = {1, 2, 3, 4};
printf("创建 4 个线程进行 CPU 绑定测试:\n");
for (int i = 0; i < 4; i++) {
if (pthread_create(&threads[i], NULL, thread_cpu_info, &thread_ids[i]) != 0) {
perror("创建线程失败");
return;
}
}
// 等待所有线程完成
for (int i = 0; i < 4; i++) {
pthread_join(threads[i], NULL);
}
printf("CPU 绑定测试完成\n\n");
}
int main() {
printf("=== sched_getcpu 示例 ===\n\n");
// 显示系统信息
show_cpu_info();
// 显示当前进程信息
printf("进程信息:\n");
printf(" 进程 ID: %d\n", getpid());
printf(" 父进程 ID: %d\n", getppid());
printf(" 线程 ID: %ld\n", syscall(SYS_gettid));
// 获取当前 CPU
int current_cpu = sched_getcpu();
if (current_cpu != -1) {
printf(" 当前运行 CPU: %d\n", current_cpu);
} else {
printf(" 无法获取 CPU 信息: %s\n", strerror(errno));
}
printf("\n");
// 连续获取 CPU 信息观察变化
printf("连续获取 CPU 信息 (执行密集计算):\n");
volatile long sum = 0;
int initial_cpu = sched_getcpu();
printf(" 初始 CPU: %d\n", initial_cpu);
for (long i = 0; i < 50000000; i++) {
sum += i;
// 每隔一定次数检查 CPU
if (i % 10000000 == 0) {
int current_cpu = sched_getcpu();
if (current_cpu != -1) {
printf(" 计算 %ld 次后 CPU: %d\n", i, current_cpu);
}
}
}
int final_cpu = sched_getcpu();
printf(" 最终 CPU: %d\n", final_cpu);
if (initial_cpu != final_cpu && initial_cpu != -1 && final_cpu != -1) {
printf(" ✓ CPU 在计算过程中发生了切换\n");
} else {
printf(" CPU 在计算过程中保持不变\n");
}
printf("\n");
// CPU 绑定测试
test_cpu_binding();
// 显示 CPU 调度信息
printf("=== CPU 调度信息 ===\n");
printf("CPU 调度相关概念:\n");
printf("1. CPU 亲和性: 进程可以运行的 CPU 集合\n");
printf("2. 负载均衡: 系统在 CPU 间分配负载\n");
printf("3. 上下文切换: 进程在 CPU 间的切换\n");
printf("4. 缓存局部性: 数据在 CPU 缓存中的位置\n");
printf("5. NUMA 拓扑: 非统一内存访问架构\n");
printf("\n");
printf("sched_getcpu 的用途:\n");
printf("1. 性能分析: 监控线程 CPU 使用情况\n");
printf("2. 负载均衡: 了解 CPU 分配情况\n");
printf("3. 调试工具: 分析程序执行行为\n");
printf("4. 实时系统: 监控实时性约束\n");
printf("5. 优化建议: 识别性能瓶颈\n");
printf("\n");
printf("使用建议:\n");
printf("1. 结合 CPU 亲和性使用\n");
printf("2. 监控 CPU 切换频率\n");
printf("3. 分析热点 CPU\n");
printf("4. 优化缓存局部性\n");
printf("5. 避免过度绑定 CPU\n");
return 0;
}
3. 编译和运行说明
# 编译所有示例程序
gcc -o pread_example pread_example.c
gcc -o affinity_example affinity_example.c
gcc -o priority_example priority_example.c
gcc -o rr_interval_example rr_interval_example.c
gcc -o getcpu_example getcpu_example.c -lpthread
# 运行示例程序
./pread_example
./affinity_example
./priority_example
./rr_interval_example
./getcpu_example
# 需要 root 权限的测试
sudo ./priority_example
sudo ./rr_interval_example
4. 系统要求检查
# 检查内核版本
uname -r
# 检查系统调用支持
grep -E "(pread|pwrite)" /usr/include/asm/unistd_64.h
# 检查 CPU 信息
lscpu
# 检查调度器信息
cat /proc/sched_debug 2>/dev/null || echo "无法读取调度器调试信息"
# 检查实时调度支持
grep -i realtime /boot/config-$(uname -r)
# 检查 NUMA 支持
numactl --hardware 2>/dev/null || echo "系统不支持 NUMA"
5. 重要注意事项
5.1 权限要求
- 普通用户: 可以使用
pread
/pwrite
等基本 I/O 操作 - root 用户: 需要设置实时调度策略 (
SCHED_FIFO
/SCHED_RR
) - CAP_SYS_NICE: 某些操作需要此能力
5.2 错误处理
// 安全的系统调用封装
int safe_pread(int fd, void *buf, size_t count, off_t offset) {
if (fd < 0 || !buf || count == 0) {
errno = EINVAL;
return -1;
}
ssize_t result;
do {
result = pread(fd, buf, count, offset);
} while (result == -1 && errno == EINTR);
return result;
}
// 安全的 CPU 亲和性设置
int safe_sched_setaffinity(pid_t pid, const cpu_set_t *mask) {
if (!mask) {
errno = EINVAL;
return -1;
}
return sched_setaffinity(pid, sizeof(cpu_set_t), mask);
}
5.3 性能考虑
// 性能优化建议
void performance_optimization_tips() {
printf("性能优化建议:\n");
printf("1. 批量操作: 使用 preadv/pwritev 减少系统调用次数\n");
printf("2. 缓冲区大小: 合理设置缓冲区大小避免频繁调用\n");
printf("3. CPU 亲和性: 合理绑定 CPU 提高缓存命中率\n");
printf("4. 调度策略: 根据应用特点选择合适的调度策略\n");
printf("5. 优先级设置: 避免过度使用高优先级影响系统稳定性\n");
printf("6. 时间片调整: 根据应用需求调整时间片长度\n");
printf("7. 资源限制: 合理设置进程资源限制\n");
printf("8. 内存管理: 避免内存碎片和频繁分配\n");
}
5.4 最佳实践
// 完整的 I/O 操作最佳实践
typedef struct {
int fd;
size_t buffer_size;
int use_positioned_io;
int use_scatter_gather;
cpu_set_t cpu_affinity;
int has_cpu_affinity;
} io_context_t;
// 初始化 I/O 上下文
int init_io_context(io_context_t *ctx, const char *filename) {
ctx->fd = open(filename, O_RDWR | O_CREAT, 0644);
if (ctx->fd == -1) {
return -1;
}
ctx->buffer_size = 4096;
ctx->use_positioned_io = 1;
ctx->use_scatter_gather = 0;
ctx->has_cpu_affinity = 0;
return 0;
}
// 清理 I/O 上下文
void cleanup_io_context(io_context_t *ctx) {
if (ctx->fd != -1) {
close(ctx->fd);
ctx->fd = -1;
}
}
6. 实际应用场景
6.1 数据库系统
// 数据库页 I/O 操作
int db_page_io(int fd, off_t page_offset, void *page_data, size_t page_size) {
// 使用 pread/pwrite 进行页级别的随机访问
ssize_t bytes_read = pread(fd, page_data, page_size, page_offset);
return (bytes_read == (ssize_t)page_size) ? 0 : -1;
}
6.2 实时系统
// 实时应用调度设置
int setup_realtime_scheduling(int priority) {
struct sched_param param;
param.sched_priority = priority;
// 设置实时调度策略
if (sched_setscheduler(0, SCHED_FIFO, ¶m) == -1) {
return -1;
}
// 设置 CPU 亲和性
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
CPU_SET(0, &cpu_set); // 绑定到 CPU 0
return sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
}
6.3 网络服务器
// 网络服务器 I/O 处理
int handle_network_io(int client_fd, struct iovec *iov, int iovcnt) {
// 使用 preadv/pwritev 处理网络数据包
return pwritev(client_fd, iov, iovcnt, 0);
}
7. 总结
7.1 核心概念回顾
Linux 调度器函数族为进程调度控制提供了精细化的管理能力:
- sched_yield: 让出当前 CPU 时间片,允许同优先级进程运行
- sched_getscheduler/sched_setscheduler: 获取和设置进程调度策略
- sched_getaffinity/sched_setaffinity: 获取和设置 CPU 亲和性
- sched_get_priority_min/sched_get_priority_max: 获取调度策略优先级范围
- sched_rr_get_interval: 获取轮转调度时间片长度
- sched_getcpu: 获取当前运行的 CPU 编号
- prlimit64: 获取和设置进程资源限制
7.2 调度策略详解
五种主要调度策略:
- SCHED_OTHER: 默认分时调度(CFS),适合普通应用
- SCHED_FIFO: 实时先进先出,高优先级进程持续运行
- SCHED_RR: 实时轮转调度,相同优先级进程时间片轮转
- SCHED_BATCH: 批处理优化,减少上下文切换
- SCHED_IDLE: 空闲任务,只在系统空闲时运行
7.3 性能优化要点
调度策略选择:
- 普通应用:使用 SCHED_OTHER(默认)
- 实时系统:使用 SCHED_FIFO 或 SCHED_RR
- 批处理任务:使用 SCHED_BATCH
- 后台任务:使用 SCHED_IDLE
CPU 亲和性优化:
- 减少 CPU 缓存失效
- 提高缓存命中率
- 降低上下文切换开销
- 改善 NUMA 访问模式
7.4 安全和权限管理
权限要求:
- 普通用户:可使用 SCHED_OTHER/SCHED_BATCH/SCHED_IDLE
- root 用户:可使用所有调度策略
- CAP_SYS_NICE:允许修改调度策略和优先级
- CAP_SYS_ADMIN:允许使用 prlimit64 设置资源限制
安全考虑:
// 权限检查示例
int check_scheduling_permissions() {
if (geteuid() == 0) {
return 1; // root 权限
}
// 检查 CAP_SYS_NICE 能力
// 使用 libcap-ng 库进行能力检查
return 0; // 普通权限
}
7.5 实际应用场景
适用场景:
- 实时系统:音视频处理、工业控制(SCHED_FIFO/SCHED_RR)
- 高性能计算:科学计算、数据分析(CPU 亲和性绑定)
- 服务器应用:Web 服务、数据库(合理的调度策略)
- 系统监控:性能分析、资源管理(sched_getcpu)
- 容器技术:资源限制、进程隔离(prlimit64)
7.6 最佳实践
调度策略设置:
// 安全的调度策略设置
int safe_set_scheduler(pid_t pid, int policy, int priority) {
struct sched_param param;
// 验证参数
if (priority < sched_get_priority_min(policy) ||
priority > sched_get_priority_max(policy)) {
errno = EINVAL;
return -1;
}
param.sched_priority = priority;
// 设置调度策略
int result = sched_setscheduler(pid, policy, ¶m);
if (result == -1) {
switch (errno) {
case EPERM:
fprintf(stderr, "权限不足,需要适当权限\n");
break;
case EINVAL:
fprintf(stderr, "无效的策略或优先级\n");
break;
case ESRCH:
fprintf(stderr, "进程不存在\n");
break;
}
}
return result;
}
CPU 亲和性管理:
// 智能 CPU 绑定
int smart_cpu_binding(pid_t pid, int cpu_count) {
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
// 根据系统 CPU 数量智能绑定
int available_cpus = sysconf(_SC_NPROCESSORS_ONLN);
int bind_count = (cpu_count < available_cpus) ? cpu_count : available_cpus;
for (int i = 0; i < bind_count; i++) {
CPU_SET(i, &cpu_set);
}
return sched_setaffinity(pid, sizeof(cpu_set), &cpu_set);
}
资源限制控制:
// 安全的资源限制设置
int safe_set_resource_limit(int resource, rlim_t soft_limit, rlim_t hard_limit) {
struct rlimit64 limit;
limit.rlim_cur = soft_limit;
limit.rlim_max = hard_limit;
int result = prlimit64(0, resource, &limit, NULL);
if (result == -1) {
switch (errno) {
case EPERM:
fprintf(stderr, "权限不足,需要 CAP_SYS_RESOURCE 能力\n");
break;
case EINVAL:
fprintf(stderr, "无效的资源类型或限制值\n");
break;
}
}
return result;
}
7.7 学习建议
掌握路径:
- 入门阶段:理解基本调度概念和 sched_yield 使用
- 进阶阶段:掌握调度策略和 CPU 亲和性
- 高级阶段:精通资源限制和性能优化
- 专家阶段:实现复杂的调度控制系统
实践要点:
- 从简单示例开始逐步复杂化
- 重点关注权限管理和错误处理
- 实际项目中验证调度效果
- 持续关注实时系统发展
这些调度器函数是 Linux 系统编程的重要组成部分,正确掌握和使用它们对于开发高性能、实时性要求高的应用程序至关重要。通过系统的学习和实践,开发者可以充分发挥 Linux 调度系统的强大功能。