为什么会发生调度?
 
因为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. hibernate_sequence.nextval 序列不存在

    1: 使用oracle数据库时,hibernate配置bean文件时,在*.hbm.xml中配置主键生成策略为sequence,却没有指定sequence 2: <param name=&quo ...

  2. 高性能 Socket 组件 HP-Socket v3.2.1-RC1 公布

    HP-Socket 是一套通用的高性能 TCP/UDP Socket 组件.包括服务端组件.client组件和 Agent 组件.广泛适用于各种不同应用场景的 TCP/UDP 通信系统.提供 C/C+ ...

  3. nginx语法之location详解

    Location语法优先级排列 匹配符 匹配规则 优先级 = 精确匹配 ^~ 以某个字符串开头 ~ 区分大小写的正则匹配 ~* 不区分大小写的正则匹配 !~ 区分大小写不匹配的正则 !~* 不区分大小 ...

  4. swift实现AES解密

    原来的加密解密是用java写的,用在安卓系统上.现在要用在iOS系统上,所以从服务器上下载过来的加密文件要用swift来实现其的解密方法. 具体过程如下: 给NSData增加一个类目,NSData+A ...

  5. zabbix haproxy 监控

    摘自: http://www.tuicool.com/articles/JrYNNrm 写的非常好,步步紧逼,环环相扣.直到成功! 文章首发站点:OpensGalaxy 这是一个HAProxy的zab ...

  6. DropDownList(For)

    1.绑定数据源 方法一 Controllers:var users = GetUsers(); var selectList = new SelectList(users, "Value&q ...

  7. IDEAL葵花宝典:java代码开发规范插件 Rainbow Brackets 插件

    前言: 最近在Jetbrains IDEA插件网站逛发现了 Rainbow Brackets这款插件,非常棒,推荐给大家. 可以实现配对括号相同颜色,并且实现选中区域代码高亮的功能. 对增强写代码的有 ...

  8. linux 下文件恢复工具extundelete介绍

        下载 http://extundelete.sourceforge.net/ bunzip2 extundelete-0.2.0.tar.bz2 tar xvf extundelete-0.2 ...

  9. POJ3237 Tree(树剖+线段树+lazy标记)

    You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbe ...

  10. k8s-集群状态及部署一个实例

    [root@k8s-master ~]# kubectl get csNAME STATUS MESSAGE ERRORcontroller-manager Healthy ok scheduler ...