Linux 内核中的进程调度:从 CFS 到实时调度
引言
作为一名深耕操作系统和嵌入式开发的工程师,我深知资源调度的重要性。在系统开发中,合理的资源调度可以提高系统的效率,确保任务的顺利进行。在 Linux 内核中,进程调度是一个核心组件,它负责分配 CPU 时间给不同的进程和线程。今天,我们就来深入探讨 Linux 内核中的进程调度,从技术原理到实战应用。
技术原理
进程调度的核心概念
Linux 内核的进程调度主要包括:
进程调度的实现原理
// 调度器类结构体
struct sched_class {
const struct sched_class *next;
void (*enqueue_task)(struct rq *rq, struct task_struct *p, int flags);
void (*dequeue_task)(struct rq *rq, struct task_struct *p, int flags);
void (*yield_task)(struct rq *rq);
bool (*yield_to_task)(struct rq *rq, struct task_struct *p, bool preempt);
void (*check_preempt_curr)(struct rq *rq, struct task_struct *p, int flags);
struct task_struct *(*pick_next_task)(struct rq *rq, struct task_struct *prev, struct rq_flags *rf);
void (*put_prev_task)(struct rq *rq, struct task_struct *p);
void (*set_curr_task)(struct rq *rq);
void (*task_tick)(struct rq *rq, struct task_struct *p, int queued);
void (*task_fork)(struct task_struct *p);
void (*task_dead)(struct task_struct *p);
};
// CFS 调度器结构体
struct cfs_rq {
struct load_weight load;
unsigned long nr_running;
u64 exec_clock;
u64 min_vruntime;
struct rb_root_cached tasks_timeline;
struct rb_node *rb_leftmost;
unsigned int nr_spread_over;
};
// 调度实体
struct sched_entity {
struct load_weight load;
struct rb_node run_node;
struct list_head group_node;
unsigned int on_rq;
u64 exec_start;
u64 sum_exec_runtime;
u64 vruntime;
u64 prev_sum_exec_runtime;
u64 nr_migrations;
struct sched_statistics statistics;
};
// 进程结构体中的调度相关字段
struct task_struct {
int prio, static_prio, normal_prio;
unsigned int rt_priority;
const struct sched_class *sched_class;
struct sched_entity se;
struct sched_rt_entity rt;
unsigned int policy;
cpumask_t cpus_allowed;
unsigned int time_slice;
};
// 调度策略
#define SCHED_NORMAL 0
#define SCHED_FIFO 1
#define SCHED_RR 2
#define SCHED_BATCH 3
#define SCHED_IDLE 5
#define SCHED_DEADLINE 6
创业视角分析
从创业者的角度来看,进程调度的设计思路与企业管理中的任务管理有着密切的联系:
实用技巧
进程调度的使用场景
进程调度的最佳实践
代码示例
设置进程调度策略
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
int main(void)
{
struct sched_param param;
int policy;
// 获取当前调度策略
policy = sched_getscheduler(0);
switch (policy) {
case SCHED_NORMAL:
printf("Current policy: SCHED_NORMAL\\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: %d\\n", policy);
break;
}
// 设置实时调度策略
param.sched_priority = 99; // 最高实时优先级
if (sched_setscheduler(0, SCHED_FIFO, ¶m) < 0) {
perror("sched_setscheduler failed");
return 1;
}
printf("Set policy to SCHED_FIFO with priority %d\\n", param.sched_priority);
// 执行实时任务
for (int i = 0; i < 5; i++) {
printf("Real-time task iteration %d\\n", i);
usleep(100000); // 100ms
}
// 恢复默认调度策略
param.sched_priority = 0;
sched_setscheduler(0, SCHED_NORMAL, ¶m);
printf("Restored policy to SCHED_NORMAL\\n");
return 0;
}
调整进程优先级
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int nice_value;
// 获取当前 nice 值
nice_value = nice(0);
printf("Current nice value: %d\\n", nice_value);
// 降低优先级(增加 nice 值)
nice_value = nice(10);
printf("After increasing nice: %d\\n", nice_value);
// 提高优先级(减少 nice 值)
nice_value = nice(-5);
printf("After decreasing nice: %d\\n", nice_value);
return 0;
}
调度管理命令
# 查看进程调度策略和优先级
ps -eo pid,comm,policy,ni,pri,rtprio
# 调整进程优先级
sudo nice -n 10 ./my_program
sudo renice -n 5 -p <pid>
# 设置实时调度策略
sudo chrt –fifo 99 ./my_program
sudo chrt –rr 50 ./my_program
# 查看 CPU 亲和性
taskset -p <pid>
# 设置 CPU 亲和性
taskset -cp 0,1 <pid>
# 查看调度统计信息
cat /proc/schedstat
# 查看 CFS 调度器参数
sysctl -a | grep sched
# 调整 CFS 调度器参数
sysctl kernel.sched_latency_ns=20000000
sysctl kernel.sched_min_granularity_ns=1000000
总结
Linux 内核中的进程调度是一个核心组件,它负责分配 CPU 时间给不同的进程和线程。进程调度通过调度器类、调度策略、优先级等机制,实现了 CPU 资源的合理分配。
工作也要流程化,进程调度就像是系统中的任务管理工具,它确保了 CPU 资源的合理分配和系统的高效运行。在实际应用中,我们需要选择合适的调度策略,合理设置优先级,避免长时间占用 CPU,使用 nice 值,以及监控调度行为,以实现系统的最佳性能和可靠性。
这就是生机所在,通过深入理解和应用进程调度技术,我们不仅可以构建更高效、更可靠的系统,也可以从中汲取企业管理的智慧,为创业之路增添一份技术的力量。





