为什么会发生调度?
 
因为cpu是有限的,而操作系统上的进程很多,所以操作系统需要平衡各个进程的运行时间
比如说有的进程运行时间已经很长了,已经占用了cpu很长时间了,这个时候操作系统要公平
就会换下一个需要运行的进程。
 
举个例子
 
公司只有一个饮水机用来接水,有很多人排队,某个人接完了一杯水,又接下一杯水,一连接了好多杯水,这个时候公司的人事就要过来把这个人赶走
换下一个人接水,然而这个时候老板过来接水了,这个时候下一个人就是老板来接水,而不是后面排队的人,因为什么呢?因为他是老板,就这么强悍
 
这里面的饮水机就是cpu
人事就是操作系统
等接水的一个个员工就是进程
 
老板就对应操作系统里的实时进程
普通员工就对应操作系统的普通进程
 
在操作系统里面实时进程的优先级比普通进程的优先级要高,
所以操作系统在选择下个进程的时候会优先选择实时进程队列里面的进程
除非实时进程里面的进程没有了,这个时候才轮到普通进程
 
 
操作系统就像人事一样,需要公平的调度和分配资源,当然公司里面有很多老板啊,总经理啊,领导啊
这些人拥有特权,所有分配资源的时候要优先考虑这些老板领导们,这也很正常,谁让人家是老板呢
 
 
 
下面来说说抢占式调度
 
什么情况下会发生抢占式调度呢?
最常见的现象是你这个进程运行时间太长了,是时候切换到另一个进程了
 
然而操作系统怎么去统计运行时间呢?
 
计算机有个时钟的概念,每过一段时间,计算机会通知操作系统,告诉操作系统,又过去了一段时间,你去看看,当前运行的进程运行时间是不是过长了,这个时候操作系统就会去搞这个进程了。
 
在操作系统中对于每个进程有一个理想运行时间的变量,然后对应还有一个虚拟运行时间和实际运行时间和权重(优先级)。
 
这三者有什么关系呢?
 
虚拟运行时间 vruntime += 实际运行时间 delta_exec * NICE_0_LOAD/ 权重(优先级)
 
通过这个公式可以看出来,给高优先级的进程的虚拟运行时间算少了,给低优先级的进程的虚拟运行时间算多了,但是当操作系统选择下一个进程的时候还是选择虚拟运行时间最少的进程,所以说优先级在这里面就体现出来了。
 
当某个进程在运行的时候,这个进程的虚拟运行时间会增加,当进程不运行的时候,虚拟时间不增加
其实这里又会涉及到调度器的概念。
 
这里我们就只说针对普通进程的绝对公平调度策略
 
这种策略在选取下个进程的时候,是怎么选取的呢?
他是选取当前所有普通进程中运行时间最少的进程,这个应该很好理解吧,因为你在cpu上占用的时间最少,所以为了公平,就要选取你这个进程在cpu上运行。
 
在操作系统中维护了一个红黑树,红黑树就是一颗平衡二叉树,也就是说红黑树上面挂了好多进程,最左边的进程就是运行时间最少的进程,所有操作系统在,选取下一个进程就会选取这个红黑树上最左侧的进程。
 
static void
check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
{
unsigned long ideal_runtime, delta_exec;
struct sched_entity *se;
s64 delta;
 
 
ideal_runtime = sched_slice(cfs_rq, curr);
delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime;
if (delta_exec > ideal_runtime) {
resched_curr(rq_of(cfs_rq));
return;
}
......
se = __pick_first_entity(cfs_rq);
delta = curr->vruntime - se->vruntime;
if (delta < 0)
return;
if (delta > ideal_runtime)
resched_curr(rq_of(cfs_rq));
}
 
上面代码是Linux源码
 
在操作系统中还有个时间的概念,就是在一个调度周期中,这个进程应该运行的实际时间(ideal_runtime)
sum_exec_runtime指进程总共执行的实际时间, prev_sum_exec_runtime指上次该进程被调度时已经占用的实际时间。
 
每次在调度一个新的进程时都会把它的se->prev_sum_exec_runtime=se->sum_exec_runtime,所以sum_exec_runtime-prev_sum_exec_runtime
就是这次调度占用实际时间。如果这个时间大于ideal_runtime,则应该被抢占了。
 
除了这个条件外,还会通过_pick_first_entity取出红黑树中最小的进程。如果当前进程的vruntime(虚拟运行时间)大于红黑树中最小的进程的vruntime,且差值大于ideal_time,也应该
被抢占了
 
当发现这个进程应该被抢占了,不能直接把他踢下去,而是在这个进程上打一个标签TIF_NEED_RESCHED,标示这个进程可以被抢占了
 
还有一个可能发生抢占的场景,就是当一个休眠的进程被唤醒的时候
这个时候如果这个被唤醒的进程比当前运行的进程的优先级高,则也应该被抢占了,也是在当前运行的进程上打一个标签TIF_NEED_RESCHED
 
抢占的时机
 
1.用户态的抢占时机
当该进程进行系统调用从内核态返回到用户态的时候,判断如果该进程有TIF_NEED_RESCHED标签,则进行抢占。
 
2.内核态的抢占时机
对内核态的执行中,被抢占的时机一般发生在preempt_enable()中。
preempt_disable()关闭抢占
在内核态的执行中,有的操作是不能被中断的,所有在进行这些操作之前,总是先调用preempt_disable()关闭抢占,当再次打开的时候,也就是调用preempt_enable()的时候
就是一次内核态代码被抢占的机会。
 
在内核态也会遇到中断的情况,当中断返回的时候,返回的仍然是内核态度。这个时候也是一个执行抢占的时机。
 
大家可以看看这张图理解

linux抢占式调度的更多相关文章

  1. 从源码剖析Go语言基于信号抢占式调度

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/485 本文使用的go的源码15.7 这一次来讲讲基于信号式抢占式调度 ...

  2. RTX——第10章 任务调度-抢占式、时间片和合作式

    以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章教程为大家将介绍 RTX 操作系统支持的任务调度方式,抢占式,时间片和合作式,这部分算是RTX 操作 ...

  3. FreeRTOS——任务调度—抢占式,时间片和合作式

    以下转载自安富莱电子: http://forum.armfly.com/forum.php 本章教程为大家将介绍 FreeRTOS 操作系统支持的任务调度方式:抢占式,时间片和合作式,这部分算是 Fr ...

  4. ASM:《X86汇编语言-从实模式到保护模式》第17章:保护模式下中断和异常的处理与抢占式多任务

    ★PART1:中断和异常概述 1. 中断(Interrupt) 中断包括硬件中断和软中断.硬件中断是由外围设备发出的中断信号引发的,以请求处理器提供服务.当I/O接口发出中断请求的时候,会被像8259 ...

  5. Linux 2.4调度系统分析--转

    http://www.ibm.com/developerworks/cn/linux/kernel/l-k24sch/index.html 杨沙洲 (pubb@163.net)国防科技大学计算机学院 ...

  6. 24小时学通Linux内核之调度和内核同步

    心情大好,昨晚我们实验室老大和我们聊了好久,作为已经在实验室待了快两年的大三工科男来说,老师让我们不要成为那种技术狗,代码工,说多了都是泪啊,,不过我们的激情依旧不变,老师帮我们组好了队伍,着手参加明 ...

  7. chapter9_4 非抢占式的多线程

    协同程序与常规的多线程不同之处:协同程序是非抢占式的. 当一个协同程序运行时,是无法从外部停止它的.只有当协同程序显式地调用yield时,它才会停止. 当不存在抢先时,编程会变得简单很多,无须为同步的 ...

  8. 转: 调整 Linux I/O 调度器优化系统性能

    转自:https://www.ibm.com/developerworks/cn/linux/l-lo-io-scheduler-optimize-performance/index.html 调整 ...

  9. (转)Linux I/O 调度方法

    Linux I/O 调度方法 转自https://blog.csdn.net/theorytree/article/details/6259104 操作系统的调度有 CPU调度    CPU sche ...

随机推荐

  1. lvs虚拟服务器

    NAT模式 1.模拟环境: LVS服务器有两块网卡,连接外网(用户端)和内网(服务器),充当"交警"角色. 优点: 节省ip开销 缺点: LVS服务器负载过高,数据吞吐量降低 三台 ...

  2. 一起来学linux:ACL

    传统的 权限设置只有user,group,other三种,并没有办法针对某一个用户或者某一个组来设定权限.ACL就是用于这个目的的 那 ACL 主要可以针对哪些方面来控制权限呢?他主要可以针对几个项目 ...

  3. Django 初始化数据库

    django 初始化数据库 刷新数据库guoguos-MacBook-Pro:mysite guoguo$ python manage.py sqlflushBEGIN;SET FOREIGN_KEY ...

  4. C++三种继承方式

    一.三种继承方式 继承方式不同,第一个不同是的是派生类继承基类后,各成员属性发生变化.第二个不同是派生类的对象能访问基类中哪些成员发生变化.表格中红色标注.

  5. render 的执行流程

    流程 :  render 只能识别 字符串,对于其他的css,html,js,jquery样式是不能识别的,它会将文件中的内容解析称为字符串拿到前端页面,浏览器进行渲染. 例如 : # 视图函数 de ...

  6. 安装wampserver 计算机丢失msvcr100.dll

    刚刚重新安装了Windows 7 64位系统,再安装Wampserver 2时却提示系统错误,如下图所示: 在网上下载了MSVCR100.dll放到system32文件夹下依然没有用. 百度搜索了一下 ...

  7. LightOJ - 1079 Just another Robbery —— 概率、背包

    题目链接:https://vjudge.net/problem/LightOJ-1079 1079 - Just another Robbery    PDF (English) Statistics ...

  8. BZOJ_5338_ [TJOI2018]xor_可持久化trie

    BZOJ_5338_ [TJOI2018]xor_可持久化trie Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 ...

  9. 【Matlab】常用函数

    1.取整函数 ceil(x)返回不小于x的最小整数值.floor(x)返回不大于x的最大整数值.round(x)返回x的四舍五入整数值.

  10. JVM(一)虚拟机内存划分

    Java内存区域 线程私有数据区域:虚拟机栈,本地方法栈,程序计数器 线程共享数据区域:方法区,堆 程序计数器:当前线程所执行的字节码的行号指示器,JVM通过这个字节码解释器改变计数器的值,以选择下一 ...