欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux内核之进程调度3:进程调度

程序员文章站 2024-02-27 20:44:39
...

1. 吞吐率和响应

吞吐:单位时间内做的有用功;

响应:低延迟。

吞吐追求的整个系统CPU做有用功,响应追求的是某个特定任务的延迟低;

1GHZ的CPU切换线程保存恢复现场约几个微妙级别,看似消耗不了太多时间,但是由于系统的局部性原理,会保存当前线程数据的缓存,切换线程会打乱局部性引起cache
miss,而CPU访问cache速度远大于内存访问,这样综合看来上下文切换花销还是很大的。无用功占用较多CPU;

所以追求吞吐量和低延迟,这两个目标是矛盾的

Linux内核之进程调度3:进程调度

编译内核选项有如下

Linux内核之进程调度3:进程调度

服务器版追求吞吐量,配置为不抢占;桌面版或手机更追求响应,配置为低延迟;

调度器一般讲的是最后一种,低延迟抢占;

2. Linux任务类型

问题2: 一个典型的系统内任务分两种:CPU消耗型和IO消耗型

Linux内核之进程调度3:进程调度

CPU型的任务,通常要求高性能,但是不追求低延迟,优先级较低;

IO型的任务,通常优先级更高,追求低延迟,对CPU性能不敏感;

如下图,一个读IO循环过程,占用CPU时间极短(1ms),IO占用100ms
,若CPU性能降一倍,执行CPU占用2ms对整体时间影响不大(总时间102ms);但是如果CPU不能及时响应,一个读写周期响应延迟100ms,那整体时间变为约200ms,整体性能降低一半;

Linux内核之进程调度3:进程调度

所以,IO型任务只关注响应速度,对CPU性能不敏感;

基于此原理ARM公司设计了big.LITTLE架构,比如在手机上有8个核,设计为四大核,四小核;大小核指令集完全兼容,调度器调配IO型的任务跑在小核上(对CPU弱不敏感),CPU型任务放在大核上跑。这样用4+1(四小核等效)核的功耗实现了8核的性能;

调度器要在吞吐和延迟之间找到某个均衡;

3 任务调度

1调度原理:

涉及两个概念,策略优先级

内核所有进程优先级为0~139之间;

0~99:采用RT策略,常用的有SCHED_FIFO, SCHED_RR;

SCHED_FIFO, 属于霸占型的,高优先级执行完,才会执行低优先级;

SCHED_RR, 不同优先级与CHED_FIFO相同,属于霸占型,同等优先级轮转;

比如有4个进程:P1_FIFO_3, P2_CHED_RR_2, P3_CHED_RR_2, P4_FIFO_4

执行过程,P2/P3轮转执行完之后,执行P1, 最后执行P4。

100~139:普通线程,采用非RT策略,对应nice(-20, 19).

这里所有优先级都是可以抢占的,但nice 值越低,分配CPU资源越多。

2.所有调度,SCHER_FIFO/SCHER_RR或设置nice都是针对task_struct;

3.将进程设置为FIFO策略:

修改进程25020的策略为FIFO, 优先级50

sudo chrt –f –a –p 50 25020

这样进程是按FIFO策略调度,占有CPU最高为80%(普通进程可以接近100%),CPU占有率降低(但不可抢占),此时IO延迟反而变大,鼠标操作变慢;

设置FIFO线程api

Linux内核之进程调度3:进程调度

内核里优先级=99-50=49

内核态数字越低,优先级越高;用户态相反;

4.每个task_struct的nice都可以单独设置(所有普通线程);

Nice值设置都是指普通线程,RT策略不支持nice;

Linux内核之进程调度3:进程调度

nice()默认是0

调度,在不同nice值进程间轮转,

2.6早期内核对进程采取奖励和惩罚算法,越睡眠越奖励,越消耗CPU,越惩罚,动态调整nice值,实现极其复杂,后来升级两个补丁;

补丁1:RT熔断机制,设置rt门限值

Linux内核之进程调度3:进程调度

默认runtime 0.95s,period 1s,1s内RT最多跑了0.95s自动熔断;

$cd /proc/sys/kernel

sudo sh -c ‘echo 800000 > sched_rt_runtime_us’

设置RR/FIFO策略熔断最高位800ms,RR/FIFO策略进程最多占用CPU 80%。(默认是95%)

补丁2:普通进程调度算法CFS(complete fare schedule)

Linux内核之进程调度3:进程调度

虚拟运行时间,vtime = ptime * 1024/weight

ptime:物理时间

weight:权重参数

Linux内核之进程调度3:进程调度

nice=0,虚拟时间等于物理时间;

nice值越小,对应weight分母越大,vtime增长越慢,实际对应ptime占用越多;

vtime机制很好的平衡了I/O型,CPU型任务;

I/O型喜欢睡眠,ptime比较小,所以vtime自然较小,会偏向于挂在树左边;

同理,优先级越高的CPU型,其weight值越大,vtime也会越小,亦偏向挂载树左边;

即CFS用很简单的方式实现了历史上复杂的睡眠补偿,消耗惩罚,动态调整等功能;

修改进程的nice值:

sudo renice -n -5 -g 24856 //24856进程的所有线程nice都设置为-5

综上,linux调度算法过程:

1.首先执行SCHECH_RR/SCHECH_FIFO进程,待他们执行到睡眠或者熔断,CPU切换到普通线程;

2.普通线程按CFS算法调度,在普通线程间轮转;

线程调度优先与线程是否在内核态无关,只由优先级和策略决定。用户态内核态只涉及权限问题;