抢断调度,是调度机制对实时系统需要的支持,是一种快速响应的重调度机制。既然与重调度有关,那么就先回顾一下调度和重调度。

调度分两种情况,
1. 一种是自愿调度,由代码主动调用schedule来让度cpu,例如sleep,mutex,sema等阻塞等待。另外,当一个进程(或线程)走到尽头(do_exit)时,也会调用schedule,但是却永远不再恢复执行了,否则就是BUG了。
2. 另一种是重调度,非自愿的。当前线程被设置重调度后,当有中断发生或系统调用时,在entry.S的返回路径上就会被动调用schedule。而抢断调度,也是重调度,却不必等待到中断发生或系统调用,在处理结束后离开entry.S才进行调度。而是在离开抢断临界区就马上进行调度。

一般地,在自愿调度之前,当前线程都会将自身的task_struct挂接在某一等待队列上,如wait_queue_t。并且将自身的state设置为INTERRPUTABLE或UNINTERRUTABLE(允许信号唤醒或不允许),最后才调用schedule。在这种情况下,schedule的执行会将当前的task_struct移除出它所在的运行队列。
而重调度或都抢断的重调度,schedule是不会将当前的task_struct移除出它所在运行队列。

重调度分两步:
1. 将当前运行线程的设置为TIF_NEED_RESCHED,当前线程可能在抢断保护的临界区中。通常wakeup的目标线程在当前cpu上,则设置可以直接设置重调度。
2. a. 当离开抢断保护的临界区,马上检查是否需要重调度,是否立即进行调度。
    b. 中断处理结束,软中断处理结束,或系统调用结束,恢复到原来的代码之前,进行重调度。

简单地说:
先在某处调用resched_curr对当前线程所在的调度策略的队列进行重调度的评判,可以则标记需要重调度,但并不进行实质的调用。
当要切换上下文,如中断处理结束,系统调用结束时,再调用schedule进行实质的调度工作 。
或者直接在离开抢断保护的临界区就马上调用preempt_schedule进行调度。

我们熟知的wakeup以及时间片轮转调度实际就是调用resched_curr。

resched_curr 重调度当前cpu的某一调度策略的运行队列
有三步工作:
1. 当前线程是否已经设为重调度
2. 重调度的目标的运行队列所属cpu是否也当前运行的cpu?
    如果是则进行下面两步:
      a. 设置重调度标记 TIF_NEED_RESCHED
      b. 向当前CPU的preempt_count设置重调度 PREEMPT_NEED_RESCHED。
3. 向远端CPU发送重调度IPI(Inter-processor interrupt)。

抢断保护“锁”,是一个保护临界区内不被重调度需求而抢断进行调度。这个锁独立保护每一个cpu(当前运行的线程),而不是保护线程并发临界区。它是可递归,没有竞争状态,不会阻塞,不存在竞态条件。每一个cpu都有一个抢断保护锁。这个锁只是一个32位名为__preempt_count整形变量。它为中断,软中断,普通抢断保护提供嵌套深度,同时也用作为软中断锁,保护软中断处理不递归进入。中断处理,软中断处理同样是抢断保护的临界区,不允许被重调度抢断。

抢断保护"锁",除了保护了临界区不被重调度推断外,同时也为快速响应重调度提供了响应的时机,那就是抢断临界区离开的时候。因为entry.S上对重调度的响应,往往是被动的,必须等待有中断发生或系统调用等不确定的事件,使内核经过entry.S并离开时才会响应重调度。而抢断调度则是代码在离开临界区的时候主动去响应重调度。如果没有了抢断保护锁__preempt_count,代码就不清楚什么时候才合适去响应重调度。只好被动延后到经过entry.S,从而不能及时最快地去响应重调度。

抢断调度,由函数preempt_schedule进行,必须主动调用。这个函数嵌入到了每一处离开抢断临界区的代码中,比如内核无处不在的同步锁释放,spin_unlock, rwlock_unlock, rcu_read_unlock, spin_trylock, 以及pagefault_enable等。这些函数都会嵌入preempt_enable。

在抢占调度中,CPU的__preempt_count被设置PREEMPT_ACTIVE 用来提示 __schedule() ,我们是从preempt path 进来的。PREEMPT_ACTIVE 用来保护重调度不嵌套抢断。当前被抢断的线程在恢复运行之前,运行在当前cpu的其它线程不可以再进行抢断。

这里必须要清楚这样一个事实,软件中断保护锁也是在使用抢断保护锁,当离开软中断处理的同时,也等同于离开一层抢断临界区,这时只要不存在嵌套临界区的话,就可以进行抢断调试。__local_bh_enable_ip嵌入了preempt_check_enable。

linux内核的preempt抢占调度,preempt_count抢占保护“锁”的更多相关文章

  1. Linux内核——进程管理与调度

    进程的管理与调度 进程管理 进程描写叙述符及任务结构 进程存放在叫做任务队列(tasklist)的双向循环链表中.链表中的每一项包括一个详细进程的全部信息,类型为task_struct,称为进程描写叙 ...

  2. 分析Linux内核中进程的调度(时间片轮转)-《Linux内核分析》Week2作业

    1.环境的搭建: 这个可以参考孟宁老师的github:mykernel,这里不再进行赘述.主要是就是下载Linux3.9的代码,然后安装孟宁老师编写的patch,最后进行编译. 2.代码的解读 课上的 ...

  3. 《linux 内核全然剖析》 chapter 4 80x86 保护模式极其编程

    80x86 保护模式极其编程       首先我不得不说.看这章真的非常纠结...看了半天.不知道这个东西能干嘛.我感觉唯一有点用的就是对于内存映射的理解...我假设不在底层给80x86写汇编的话.我 ...

  4. Linux用户抢占和内核抢占详解(概念, 实现和触发时机)--Linux进程的管理与调度(二十)

    1 非抢占式和可抢占式内核 为了简化问题,我使用嵌入式实时系统uC/OS作为例子 首先要指出的是,uC/OS只有内核态,没有用户态,这和Linux不一样 多任务系统中, 内核负责管理各个任务, 或者说 ...

  5. Linux内核抢占实现机制分析【转】

    Linux内核抢占实现机制分析 转自:http://blog.chinaunix.net/uid-24227137-id-3050754.html [摘要]本文详解了Linux内核抢占实现机制.首先介 ...

  6. Linux内核态抢占机制分析

    http://blog.sina.com.cn/s/blog_502c8cc401012pxj.html [摘要]本文首先介绍非抢占式内核(Non-Preemptive Kernel)和可抢占式内核( ...

  7. Linux内核态抢占机制分析(转)

    Linux内核态抢占机制分析  http://blog.sina.com.cn/s/blog_502c8cc401012pxj.html 摘 要]本文首先介绍非抢占式内核(Non-Preemptive ...

  8. Linux内核态抢占机制分析【转】

    转自:http://blog.csdn.net/yiyeguzhou100/article/details/53097665 目录(?)[-] 1非抢占式和可抢占式内核的区别 21 用户态抢占User ...

  9. 深入Linux内核架构——进程管理和调度(上)

    如果系统只有一个处理器,那么给定时刻只有一个程序可以运行.在多处理器系统中,真正并行运行的进程数目取决于物理CPU的数目.内核和处理器建立了多任务的错觉,是通过以很短的间隔在系统运行的应用程序之间不停 ...

随机推荐

  1. C# Halcon混合编程中遇到的问题(一)

    目标平台 安装64位的halcon的情况下,目标平台必须使用x64而不能使用x86 目标框架 不能使用.Net Framework Client版本,有一些必须的程序集会缺失,测试使用.Net Fra ...

  2. Spring Boot 2.X(十一):全局异常处理

    前言 在 Java Web 系统开发中,不管是 Controller 层.Service 层还是 Dao 层,都有可能抛出异常.如果在每个方法中加上各种 try catch 的异常处理代码,那样会使代 ...

  3. 张高兴的 .NET Core IoT 入门指南:(五)PWM 信号输出

    什么是 PWM 在解释 PWM 之前首先来了解一下电路中信号的概念,其中包括模拟信号和数字信号.模拟信号是一种连续的信号,与连续函数类似,在图形上表现为一条不间断的连续曲线.数字信号为只能取有限个数值 ...

  4. Intellij IDEA 常用的插件 建议全装

    介绍几个常用的插件 Alibaba Java Coding Guidelines https://plugins.jetbrains.com/plugin/10046-alibaba-java-cod ...

  5. 小白学微信小程序

    奔着实用性的目的-测试孩子的认字量,开发了一个微信小程序-测字大王.上下班路上看书看了一个星期,代码前后共写一个星期.现在小程序已经对外开放,share下我的开发过程吧. 一 工具准备 首先先过一篇 ...

  6. Mysql UTF-8mb4字符集的问题

    官方Mysql手册链接 https://dev.mysql.com/doc/connectors/en/connector-j-reference-charsets.html Notes For Co ...

  7. MySQL开发篇(5)索引、视图、触发器、SQL中的安全问题、SQL Mode、

    一.索引 所有MySQL列类型都可以被索引,对相关列使用索引是提高SELECT操作性能的最佳途径.每种存储引擎(MyISAM.InnoDB.BDB.MEMORY等)对每个表至少支持16个索引,总索引长 ...

  8. .Net Core实现健康检查

    ASP.NET Core 提供运行状况检查中间件和库,以用于报告应用基础结构组件的运行状况. 运行状况检查由应用程序作为 HTTP 终结点公开. 可以为各种实时监视方案配置运行状况检查终结点: 运行状 ...

  9. Rest_Framework之频率组件部分

    一.RestFramework之频率组件源码部分 频率组件的源码部分和权限组件流程一模一样的,这里就不多说了,直接上源码的主要逻辑部分: def check_throttles(self, reque ...

  10. 在VMware下的Linux中的RAID10校验位算法下的磁盘管理

    988年由加利福尼亚大学伯克利分校发表的文章首次提到并定义了RAID,当今CPU性能每年可提升30%-50%但硬盘仅提升7%,渐渐的已经成为计算机整体性能的瓶颈,并且为了避免硬盘的突然损坏导致数据丢失 ...