Linux 调度SCHED_FIFO或SCHED_RR
- NORMAL(CFS - Completely Fair Scheduler)策略
- 基本原理:CFS 是 Linux 内核中默认的调度策略,用于普通进程的调度。它的设计目标是公平地分配 CPU 时间给各个进程。CFS 使用红黑树(Red - Black Tree)数据结构来维护所有可运行进程的调度队列。每个进程都有一个虚拟运行时间(virtual runtime),它是根据进程实际运行时间和进程优先级等因素计算得到的。CFS 会选择虚拟运行时间最小的进程来运行,这样可以保证每个进程都能相对公平地获取 CPU 资源。
- 应用场景和特点:适用于大多数的普通用户进程和系统进程,如文本编辑器、浏览器等应用程序对应的进程。它能够在多任务环境下,让各个进程都有机会运行,避免某个进程长时间独占 CPU 而导致其他进程饥饿。例如,在一个同时运行多个后台服务和前台应用的系统中,CFS 调度器会根据每个进程的虚拟运行时间,合理地分配 CPU 时间,使得系统整体运行流畅。
- FIFO(First - In - First - Out)策略
- 基本原理:FIFO 是一种简单的实时调度策略。按照进程进入可运行状态的先后顺序来分配 CPU 时间。一旦一个进程开始运行,它会一直运行下去,直到它主动放弃 CPU(例如通过等待 I/O 操作、调用阻塞式系统调用等)或者被更高优先级的实时进程抢占。
- 应用场景和特点:用于对实时性要求极高且任务执行时间相对可预测的场景。例如,一些工业控制中的实时数据采集任务,这些任务需要按照固定的顺序及时获取数据并且不能被打断,除非它们自己主动暂停。不过,FIFO 策略可能会导致低优先级进程长时间得不到 CPU 时间,出现 “饥饿” 现象,因为高优先级的 FIFO 进程会一直占用 CPU,直到完成或者阻塞。
- RR(Round - Robin)策略
- 基本原理:RR 策略也是一种实时调度策略。它类似于 FIFO,但为每个进程分配一个固定的时间片(time - slice)。当一个进程的时间片用完后,系统会将 CPU 切换到下一个就绪进程,即使当前进程还没有完成。所有就绪进程会按照顺序轮流使用 CPU,从而保证每个进程都能得到一定的 CPU 时间。
- 应用场景和特点:适用于对实时性有要求,并且需要多个任务公平共享 CPU 资源的场景。比如在一个实时多任务系统中,多个任务的优先级相同且都需要及时响应,像实时通信系统中的多个数据发送和接收任务,RR 调度策略可以确保每个任务都有机会在一定时间内使用 CPU,不会出现某个任务长时间等待的情况,相比 FIFO 策略可以更好地避免进程 “饥饿”。
- BATCH 策略
- 基本原理:BATCH 调度策略主要是为了处理那些不需要立即响应的批处理任务。这些任务通常对 CPU 时间的需求比较连续,但是对响应时间的要求不像实时任务那么高。BATCH 调度器会尽量让这些任务在系统负载较低的时候运行,以提高系统的整体效率。
- 应用场景和特点:应用于一些大规模的数据处理任务,如在数据中心中对大量数据进行离线分析、编译大型软件项目等场景。例如,在服务器上进行大数据集的统计分析工作,这些任务可以等待系统资源空闲时再集中处理,BATCH 调度策略能够有效地利用系统的空闲 CPU 资源,提高系统资源的利用率,同时不会对系统的实时响应性能产生太大影响。
- IDLE 策略
- 基本原理:IDLE 调度策略用于运行在系统空闲时的进程。这些进程只有在系统没有其他可运行的进程(即所有高优先级进程都处于等待状态)时才会被调度运行。IDLE 进程通常用于一些低优先级的后台任务,如系统监控工具在系统空闲时收集一些统计数据等。
- 应用场景和特点:适用于那些对系统资源占用不紧急、可以在系统空闲时间进行的任务。比如一些系统维护任务,像清理临时文件、更新系统日志等操作。这些任务不会影响系统的主要功能和性能,只会在系统真正空闲的时候利用剩余的 CPU 资源来完成自己的工作。
Linux内核怎么看时时线程和普通线程?
- 内核空间查看方式
- 通过
struct task_struct
结构体:在内核代码中,每个进程(线程)在内核中都有一个对应的struct task_struct
结构体来描述。这个结构体中有一个成员变量policy
用于存储调度策略。通过检查这个变量的值,可以判断进程是实时进程还是普通进程。例如,在内核模块或者内核调试过程中,可以使用如下代码片段(这是一个简化的示例,实际可能需要更多的头文件和错误处理等):
- 通过
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/kernel.h>
// 一个简单的内核模块函数,用于检查进程调度策略
static int __init check_schedule_policy(void)
{
struct task_struct *p;
for_each_process(p) {
if (p->policy == SCHED_FIFO || p->policy == SCHED_RR) {
printk(KERN_INFO "Process %s with PID %d is a real - time process\n", p->comm, p->pid);
} else if (p->policy == SCHED_OTHER) {
printk(KERN_INFO "Process %s with PID %d is a normal process\n", p->comm, p->pid);
}
}
return 0;
}
module_init(check_schedule_policy);
MODULE_LICENSE("GPL");
- 命令行方式(用户空间)
ps -eo pid,comm,policy
命令:在终端中使用ps -eo pid,comm,policy
可以查看系统中正在运行的进程(包括线程,因为 Linux 中线程在底层也是以轻量级进程的形式实现的)的进程标识符(pid
)、命令名称(comm
)和调度策略(policy
)。对于实时进程,调度策略会显示为SCHED_FIFO
(先进先出实时调度策略)或者SCHED_RR
(时间片轮转实时调度策略);而普通进程的调度策略通常是SCHED_OTHER
(对应于前面提到的 NORMAL/CFS 调度策略)。例如:
~$ ps -eo pid,comm,policy
PID COMMAND POL
1 systemd TS
2 kthreadd TS
3 rcu_gp TS
4 rcu_par_gp TS
5 slub_flushwq TS
6 netns TS
8 kworker/0:0H-ev TS
10 mm_percpu_wq TS
11 rcu_tasks_rude_ TS
12 rcu_tasks_trace TS
13 ksoftirqd/0 TS
14 rcu_sched TS
15 migration/0 FF
16 idle_inject/0 FF
18 cpuhp/0 TS
19 cpuhp/1 TS
20 idle_inject/1 FF
21 migration/1 FF
22 ksoftirqd/1 TS
kernel.sched_latency_ns 表示正在运行进程的所能运行的时间的最大值,即使只有一个处于running状态的进程,运行到这个时间也要重新调度一次(以纳秒为单位,在运行时会自动变化?)
同时这个值也是所有可运行进程都运行一次所需的时间,每个CPU的running进程数 = sched_latency_ns / sched_min_granularity_ns
kernel.sched_migration_cost_ns 该变量用来判断一个进程是否还是hot,如果进程的运行时间(now - p->se.exec_start)小于它,那么内核认为它的code还在cache里,所以该进程还是hot,那么在迁移的时候就不会考虑它
kernel.sched_min_granularity_ns 表示一个进程在CPU上运行的最小时间,在此时间内,内核是不会主动挑选其他进程进行调度(以纳秒为单位,在运行时会自动变化?)
kernel.sched_nr_migrate 在多CPU情况下进行负载均衡时,一次最多移动多少个进程到另一个CPU上
kernel.sched_rr_timeslice_ms 用来指示round robin调度进程的间隔,这个间隔默认是100ms。
kernel.sched_rt_period_us 该参数与sched_rt_runtime_us一起决定了实时进程在以sched_rt_period为周期的时间内,实时进程最多能够运行的总的时间不能超过sched_rt_runtime_us
kernel.sched_rt_runtime_us 该参数与sched_rt_period一起决定了实时进程在以sched_rt_period为周期的时间内,实时进程最多能够运行的总的时间不能超过sched_rt_runtime_us
参考:
linux内核参数详解_51CTO博客_linux内核源码详解
https://www.51cto.com/article/759102.html
https://zhuanlan.zhihu.com/p/381043183
Linux进程调度分析记录,进程优先级,隔离处理器,isolcpus,BCC、bpftrace工具_bcc 跟中cpu调度-CSDN博客
https://zhuanlan.zhihu.com/p/442788972
参考文献:
《Linux Kernel Development》
《Understanding the Linux Kernel》
《Professional Linux Kernel Architecture》
《Mastering Linux Kernel Development》
《Understanding the Linux Virtual Memory Manager》
《Linux内核深度解析》
《Linux操作系统原理与应用》
《深度探索Linux操作系统》
《ARM Linux内核源码剖析》
《奔跑吧Linux内核》
《Linux内核源代码情景分析》
《Linux内核设计的艺术》
《Linux内核完全注释》