linux进程分为应用层和,Linux调度机制以及应用层的优化

本文简要介绍Linux调度机制以及如何在应用层进行调度优化。

进程分类

根据进程工作场景,可将进程分为

交互时进程:这类进程大部分时间都在等待输入,CPU占用不高,要求响应迅速。例如:编辑器

批处理进程:进行大量密集计算以及IO,关心最终输出结果,对响应时间以及资源要求较低

实时进程:硬实时,严格要求在指定时间内完成指定任务。软件实时,尽可能快的完成任务。。

上述三类进程,从实时性视角上,分为实时进程和普通进程,具体取决于进程优先级数值。

调度器对这两类进程有不同的调度方式:

实时进程,基于优先级队列进行调度,优先级定义从0到99,0表示最高,99最低,共100个优先级。高优先级优于低优先级进程调度,相同优先级下,根据调度策略来调度。

普通进程,使用CFS调度器。在一个调度周期内,所有进程都有机会被调度,区别在于运行时间,与进程的nice相关。

调度策略

调度策略有:

SCHED_FIFO: 同等优先级,先入先出,调度触发时机:

进程主动调用sched_yield,让出CPU资源

进程被更高优先级进程抢占

进程停止或者被杀死

进程在等待锁、睡眠(把调度实体从优先级队列中删掉,等待被唤醒后,再添加到优先级队列中)

SCHED_RR: 同等优先级的进程,按时间片轮转,调度时间片为100ms,调度时机:

包含SCHED_FIFO的4种情况

当前进程耗尽时间片(将调度实体移动到优先级队列尾部)

问题:那如果一直存在实时进程,会不会导致普通进程始终获取不到CPU资源?

解答:Linux针对这种情况,提出组调度策略,限制实时进程的总运行时间,可通过以下两个参数进行控制:

在 sched_rt_period_us 时间内,所有实时进程运行时间之和不得超过 sched_rt_runtime_us的时间,如上图所示,在1秒内,所有实时进程最多运行0.95秒,剩下的0.05秒留给普通进程。

针对普通进程,采用CFS调度器,其核心思想是完全公平,调度策略为SCHED_OTHER,新创建的线程,默认都是普通进程。

实践前的准备

linux中,应用层和内核层对优先级的定义不同。

优先级区分

实时进程

普通进程

应用层优先级

[1,99] 1最低,99最高

内核优先级

[0,99],0最高,99最低

[100,139],100最高,139最低

应用层可通过如下两种方式设置进程优先级:

nice函数设置普通进程优先级,取值范围为-20~19,设置值越大,优先级越低。

pthread_setschedparam设置实时进程优先级,设置的值越大,优先级越高。

默认情况下,创建的进程都是普通进程,通过top命令查看进程状态,与优先级相关的字段有PR和NI。

PR列:给内核调度使用的优先级,如果该域显示为rt,则表明该进程为实时进程

NI列:进程的nice值,默认为0,取值范围为[-20,19], 负值意味着更高的优先级

控制接口

多线程在内核看来是轻量级进程,以下都以进程来标识说明。调度机制由调度策略以及调度参数来控制,目前有两套接口可供使用:

以sched_开头的系统调用,例如, sched_setparam、sched_setscheduler,

对进程标识采用__pid_t,使用getpid()接口获取,以应用层进程级别来控制。

以pthread_XX开头的接口,由线程库提供,例如,pthread_setschedparam等,对进程标识采用pthread_t,使用pthread_self接口获取,以应用层线程级别来控制。

以下采用pthread_XX系列接口。

实践

测试思路, 主线程创建两个子线程1和2,每个子线程中循环执行耗时代码,直到主线程通知它们退出,留给子线程的运行时间设置为5秒,测试代码见文末链接。

场景1:两个线程都是默认属性

测试结果:两个线程执行次数相差无几,表明线程1和2平均得到了CPU资源。

场景2:通过nice增加线程1优先级,线程2保持不变。

测试结果:增加线程1的优先级,线程1的执行次数多余线程2的执行次数

场景3:通过nice降低线程1优先级,线程2保持不变。

![场景2_降低A线程的优先级.jpg](https://i.loli.net/2021/01/21/

G8zwgouAs4JM52e.jpg)

测试结果:降低线程1的优先级,线程1的执行次数少于线程2的执行次数

场景3:设置线程1调度模式为FIFO,线程2为默认属性。

测试结果:线程1和线程2都有机会运行,但线程1运行次数多余2。通过查看运行时的绑定CPU,发现两个线程在运行过程中会切换CPU,如果线程1和线程2绑定在同一个CPU上,FIFO调度策略线程会一直占用CPU,直到它退出。

场景4:线程A和线程B绑定在同一个CPU上,线程A为FIFO模式,线程B保持默认。

测试结果:绑定在同一个CPU上后,线程A始终占据CPU资源,一直在运行,线程B得不到资源。FIFO这种模式会一直占用CPU,直到进程主动退出,即使有相同FIFO和相同优先级的进程,也不会抢占。

场景5:线程A和线程B绑定在同一个CPU上,线程A为RR模式,线程B也认为RR模式。两种优先级一样。

测试结果:先抢占到CPU的线程,始终占有CPU资源。测试结果和RR模式下时间片轮转,相同优先级会均匀调度的结论不一样。不知道什么原因?后来在线程中加入适当延时,主动让出调度机会,得到的结果就符合预期。

场景6:线程中加入适当延时后的

优先级不同的两个RR进程,高优先级的RR进程1始终占用CPU,直到进程1退出,进程2才获取了1次执行机会。

如果两个线程优先级设置为一致,则平均获得CPU资源,结果如下图:

小结

在多线程程序中,要在应用层提高线程优先级,可通过nice函数提高线程静态优先级,或者采用SCHED_RR调度模式,同时,采用绑定CPU的方式来独占某个核,降低cache失效概率,提高线程运行效率。

参考文档:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值