linux进程调度

linux进程调度

原文地址

进程优先级

linux采用两种不同的优先级范围.
第一种用nice值,范围为-20到19,越低优先级越高.
第二种是实时优先级,从0-99,越大优先级越高.

在系统调度中总会解决I/O密集型的和CPU密集型的进程的协调,I/O密集型要求有更好的响应性,而执行时间应该更少.CPU要求有更好的执行时间,而不是花费更多时间用来调度.

调度器类

linux调度器是以模块方式提供的,每个模块化结构成为调度器类,允许多种不同的可动态添加的调度算法并存.每个调度器都有一个优先级,会按照优先级顺序便利调度类,拥有一个可执行进程的最高优先级的调度器类胜出,选出下面要执行的一个程序.

公平调度

在linux中采用公平调度算法CFS,允许每个进程运行一段时间,循环轮转,选择运行最少的进程作为下一个运行进程,而不在采用分配给每个进程时间片.CFS在所有可运行进程总数基础上计算出一个进程应该运行多久.通过用nice值作为进程获得处理器运行比的权重,越低的优先级进程获得更低的处理器使用权重.在这里nice值并不是通过绝对值值来进行划分的,而是通过相对差值来分配权重的.避免了优先级差值不大的两个进程得到的处理器使用权重相差过大的情况.
在这里是由操作系统来确定进程应该使用多久,假设nice=0的进程分配时间片为100ms,则另一个nice=20的进程时间片为5ms.
如果按照绝对差值来分配时间片可能出现下列情况:
两个进程优先级分别为0和1,一个为100ms,则另一个为95ms,这时候基本没有问题.但是当两个优先级分别为18和19,那么一个为10ms,一个为5ms,这样前者比后者多出了一倍的处理器时间,是相对不合理的.

linux调度的实现

时间记账

CFS不再有时间片概念,维护每个进程运行的时间的记账,保存在进程描述符中.
每个进程都有一个虚拟运行时间,该运行时间的计算是所有可运行进程总数的标准化(是被加权的).虚拟时间以ns为单位.CFS使用vruntime变量来记录一个程序到底运行了多长时间以及还应该在运行多久.
vruntime运行时间计算如下:

  • 首先的到当前进程的执行时间,然后在根据当前可运行进程总数对运行时间进行加权计算,在将权重值与当前进程的vruntime相加.
  • vruntime准确的测量给定进程的运行时间,而且可知道谁应该是下一个被运行的进程,因为他是根据运行时间最小的进程优先调度的.
static const int prio_to_weight[40] = {
/* -20 */     88761,     71755,     56483,     46273,     36291,
/* -15 */     29154,     23254,     18705,     14949,     11916,
/* -10 */      9548,      7620,      6100,      4904,      3906,
/*  -5 */      3121,      2501,      1991,      1586,      1277,
/*   0 */      1024,       820,       655,       526,       423,
/*   5 */       335,       272,       215,       172,       137,
/*  10 */       110,        87,        70,        56,        45,
/*  15 */        36,        29,        23,        18,        15,
};

在linux中CPU nice值每下降1,则获得多10%的cpu时间,而这10%有一个相对的概念.就像上文所说的,如果用绝对的方式来说那么就会出现两倍的差距;
这里一张表表明了40个优先级的权重表示.比如有A,B两个进程nice都为0,那么每个的cpu占用时间都为1024/(1024+1024)=50%(这里1024代表上面0对应的权值),但是B要少出10的cpu时间的话,则将B的nice值加1,则应该有1024/(1024+B的权值) = 45%;算出来B的权值为837,与820相差不多,所以这里是按照相对值来计算获得的cpu时间的.
以上参考博文 https://blog.csdn.net/u010173306/article/details/46743491

进程选择

主要选择具有最小vruntime的任务;通过使用红黑树来保存这些进程

调度器入口

进程调度的时候首先是以调度器的优先级为顺序从高到低一次检查每个调度类,并且从最高优先级的调度类中选择最高优先级的进程.这样就找到最高优先级的进程,也就是vruntime最小的进程.

睡眠和唤醒

内核操作: 首先标记自己为休眠状态,从可执行红黑树中移除,放入等待队列.在选择一个可执行进程.唤醒相反.
等待队列: 维护一个等待队列,当要休眠的时候放入到等待队列.编码是一个while(true)循环中等待,在被唤醒后在此检查条件是否为真,为真就会退出循环,将自己移除出等待队列,加入可执行红黑树中.
唤醒:唤醒操作通过函数wake_up()进行,唤醒指定的等待队列上的所有进程.

抢占和上下文切换

内核中有一个参数为need_resched参数,表明是否需要重新执行一次调度,此过程称为抢占.

  • 用户抢占: 在系统调用返回用户控件或从中断处理程序返回用户空间是会发生用户抢占,当然need_resched参数要设置
  • 内核抢占: 除了need_resched参数还有一个preempt_count参数,表明是否持有锁,在preempt_count为0的时候说明在执行任务持有锁,此次抢占是不安全的.直到当前新进程持有的所有锁都释放了,才会重新执行调度.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值