验证Linux“__schedule“调用条件,关中断和关调度是必须的嘛?

2024-04-26 04:08

本文主要是介绍验证Linux“__schedule“调用条件,关中断和关调度是必须的嘛?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

"__schedule"函数是linux操作系统中的核心函数,就是它实现了操作系统最基本的多任务切换功能,使系统可以称之为操作系统,"__schedule"函数功不可没!

看下图,所有的引起任务切换的调用路径最终都会调用到__schedule函数,可见它在系统实现中的核心作用。

上图已经搜罗了系统里面所有所有会调用到__schedule函数的接口的父函数,只有六个地方,看起来扇入不是太多,不太像一个核心接口,实际上,从函数的双下划线标志就能大概猜到,它是一个内部接口,只供核心内部调用,所以当然它的扇入不会太大,但是他的父函数就不一样了,例如schedule接口在内核中被广泛调用,遍布整个内核,所以实际上__schedule的扇入是通过夫函数体现出来的,本身作为一个内部公共实现只供有限的几个点调用。

通过上图可以看到,在调用__schedule之前,每个父函数都会直接或者间接的调用"preeempt_diable"来设置抢占标志,禁止当前CPU上的抢占发生(schedule_idle是个例外,并非是因为他不会调用preempt_disable, 而是因为 linux的ilde任务在出生时就已经关闭了调度,具体可以看另一篇文章).

从另一个地方也可以看出来,__schedule函数在入口会直接调用schedule_debug函数

而schedule_debug会检查抢占是否已关,没关的话就会调用__schedule_bug给出内核警告,看起来还是一个比较严重的事件的!

所以可以基本确定:

规则1:环境在调用__schedule前, 必须主动关闭抢占

现在看另一条规则,先看一下__schedule的执行细节:

可以看到,__schedule函数内部,在入口处必定会调用 local_irq_disable执行关闭CPU本地中断的操作,而退出的时候,两条路径都会执行 local_irq_enable的操作,并且不是通常的"riqsave"以及"irqrestore"的禁止/恢复形式,而是关闭/打开这种方式,这和一般的驱动或者中间层的调用方式不大一样,或许这就是最核心接口的特权:).

一般来讲,一个函数应该要保证,它的入口处的状态和出口处的状态,必须要一致的。按照这样的原则,考虑到__schedule退出的时候会无条件打开中断,为了满足对称的要求,我们只能猜测,就像关闭抢占一样,环境在调用__schedule之前,必须要打开中断响应能力,以便__schedule函数返回后,状态能够一致!

事实是这样吗?

很遗憾,搭建qemu环境实测了一下,大部分场景下都是符合要求的,但是在一个点上,出现了不满足。

在schedule_debug中增加检测中断使能的逻辑

 zui

最终发现,在do_work_pending函数中,出现了在中断关闭的情况下调用schedule的情况

do_work_pending里面,一处比较没有意义的区分,如果在调用schedule之前,调用local_irq_enable也无大碍,而且最后无条件执行local_irq_disable也符合schedule之后,中断响应打开,建立临界区的语义。

也就是在这里 __schedule函数入口处和出口处的中断状态不在对称.

在这一点上,MIPS port的执行逻辑和arm 是类似的,124行,执行 jal schedule的时候,中断也是关闭的退出时就打开了,所以126行迅速执行关闭,再次检测调度条件,这一点和上面的 do_work_pending如出一辙。

如果抛去对称性的讨论,单纯看流程倒是可以理解为,保证thread_flags的获取和判断是原子的,而从内部__schedule 出来再到 678行关闭中断,这段时间中断是打开的,可以发生抢占,只是牺牲了对称性,可能linux开发者觉得,这没什么问题!看下图!

irq_disable();

.............

do {

      ....................

        schedule();----->__schedule { ............. irq_enable()};

        .................   //interrupt preempt happend!

        irq_disabe();

       ...................

}

还是i不用纠结了,软件就是折衷,凑合的过程,不要过度追求完美,甚至linux也是一样。

这篇关于验证Linux“__schedule“调用条件,关中断和关调度是必须的嘛?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/936676

相关文章

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

opencv图像处理之指纹验证的实现

《opencv图像处理之指纹验证的实现》本文主要介绍了opencv图像处理之指纹验证的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、简介二、具体案例实现1. 图像显示函数2. 指纹验证函数3. 主函数4、运行结果三、总结一、

SpringIntegration消息路由之Router的条件路由与过滤功能

《SpringIntegration消息路由之Router的条件路由与过滤功能》本文详细介绍了Router的基础概念、条件路由实现、基于消息头的路由、动态路由与路由表、消息过滤与选择性路由以及错误处理... 目录引言一、Router基础概念二、条件路由实现三、基于消息头的路由四、动态路由与路由表五、消息过滤

Linux samba共享慢的原因及解决方案

《Linuxsamba共享慢的原因及解决方案》:本文主要介绍Linuxsamba共享慢的原因及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux samba共享慢原因及解决问题表现原因解决办法总结Linandroidux samba共享慢原因及解决

新特性抢先看! Ubuntu 25.04 Beta 发布:Linux 6.14 内核

《新特性抢先看!Ubuntu25.04Beta发布:Linux6.14内核》Canonical公司近日发布了Ubuntu25.04Beta版,这一版本被赋予了一个活泼的代号——“Plu... Canonical 昨日(3 月 27 日)放出了 Beta 版 Ubuntu 25.04 系统镜像,代号“Pluc

在C#中调用Python代码的两种实现方式

《在C#中调用Python代码的两种实现方式》:本文主要介绍在C#中调用Python代码的两种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#调用python代码的方式1. 使用 Python.NET2. 使用外部进程调用 Python 脚本总结C#调

Linux安装MySQL的教程

《Linux安装MySQL的教程》:本文主要介绍Linux安装MySQL的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux安装mysql1.Mysql官网2.我的存放路径3.解压mysql文件到当前目录4.重命名一下5.创建mysql用户组和用户并修

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

Linux上设置Ollama服务配置(常用环境变量)

《Linux上设置Ollama服务配置(常用环境变量)》本文主要介绍了Linux上设置Ollama服务配置(常用环境变量),Ollama提供了多种环境变量供配置,如调试模式、模型目录等,下面就来介绍一... 目录在 linux 上设置环境变量配置 OllamPOgxSRJfa手动安装安装特定版本查看日志在