【原创】linux为什么不是实时操作系统

文章目录

    • 一、什么是实时操作系统(RTOS)?
    • 二、linux为什么不是实时操作系统?
      • 中断响应时间
      • 中断处理时间
      • 任务调度时间
        • 1、No Forced Preemption(Server)
        • 2、Voluntary Kernel Preemption(Desktop)
        • 3、Preemptible Kernel(Low-Latency Desktop)
        • 4、Full Real Time Preemption(PREEMPT-RT)
      • 上下文切换时间
    • 参考链接

一、什么是实时操作系统(RTOS)?

可参见本博客之前的文章:

什么是实时
实时分类
常见的RTOS
latency和jitter

总结一下,实时其实说的是系统响应事件需要的时间的确定性,时间必须确定,打死都不能超过这个时间。

二、linux为什么不是实时操作系统?

为了确保系统的实时性,即事件响应产生结果的时间准确性,可以将整个事件响应过程的延迟拆解为若干个组成部分如下。只有各个部分的响应时间都具有确定性,整体的响应时间才能得到保证。

而操作系统仅能保证系统层面时延,也就是完成实时任务的调度执行,至于你的实时任务执行时间确不确定,还取决于你的软件算法设计,然后输出计算或控制结果,即最后结果输出的确定性。

img

对操作系统延时进行分解,可分解为**系统延时=中断响应延时+中断处理延时+调度延时+进程切换延时,**所以我们一一来看,linux为什么不实时?

中断响应时间

中断响应时间是指从接收到中断信号到操作系统做出响应,并完成进入中断服务例程所需要的时间。

实时操作系统的意义就在于能够在确定的时间内处理各种突发的事件,而中断是这些事件、系统抢占调度的触发点,中断何时得到处理反应了系统的基本实时性能,因而衡量嵌入式实时操作系统的最主要、最具有代表性的性能指标参数无疑是中断响应时间。

中断延迟时间=**最大关中断时间+硬件开始处理中断到开始执行中断服务例程第一条指令之间的时间。**通俗地说:**中断产生到内核执行中断处理程序第一条指令的时间。**影响该指标的最大因素是中断屏蔽时间。

那么任何条件下,linux中断响应时间确定吗(也就是最大中断屏蔽时间确定吗)?全球这么多开发者一起开发,linux支持这么多外设驱动,谁的驱动屏蔽中断执行多久谁知道呢?

中断处理时间

响应中断后,开始执行中断处理函数,不同的中断处理所需要的时间不同,那linux的中断处理延时确定吗?Linux由于不支持中断嵌套,执行中断处理时关中断,所以,该时间同样未知!不同的板子,不同的外设,不同的驱动程序设计,中断处理需要的时间均不一样。

任务调度时间

那一个事件产生,完成中断处理,下一步唤醒与该事件相关的任务。现在要找到下一个使用cpu的任务,如果系统中有成千上万个任务,linux从中选择运行的任务的时间要多少,这个调度过程的时间确定吗? 这就是为什么要有不同调度类和调度算法,不同调度类之间还要有不同的优先级,EDF调度类>RT调度类>完全公平调度调度类>idle调度类。Linux不同调度类的调度算法时间复杂度为O(1),选择下一个运行的任务很快,所以linux的实时问题不是出在这,而是什么时候能调度的问题!!!

任何操作系统的调度追求2个目标:**吞吐率大和延迟低,但这个目标是相互矛盾的。**调度和上下文切换过程本身也是要CPU时间的,频繁的上下文切换会导致CPU时间的浪费,降低系统的吞吐量,

Linux是通用操作系统(GPOS), 其定位是尽量缩短系统的平均响应时间,提高吞吐量,注重操作系统的整体功能需求,达到更好的平均性能。(过度追求响应时,过多的上下文切换把 CPU 时间消耗在寄存器、内核栈以及虚拟内存等数据的保存和恢复上,从而缩短进程真正运行的时间,导致系统的整体性能大幅下降),所以规定在哪可以调度很重要,也就是我们说的调度点或者抢占点。

说白了,调度也是一段代码,一个函数,什么时候可以调用这个函数呢?不同的抢占模型抢占点不同,目前linux主线提供了3种抢占模型。

1、No Forced Preemption(Server)

img

img

早期linux为追求最大吞吐量,只能在内核态返回用户态时中断处理返回用户态时进行调度,也就是整个内核态执行的过程中都不能抢占,那外部事件产生到p3任务执行,这时间就可大了去了,完全没有确定性可言。

这是传统的抢占模型,目标是使吞吐量最大化。大多数时候提供良好的延迟,但是没有保证,可能偶尔出现长的延迟。这种模型主要用于服务器和科学计算系统。如果希望使内核的处理能力最大化,不考虑调度延迟,那么应该选择这种模型。

2、Voluntary Kernel Preemption(Desktop)

img

img

后来呢,为降低系统整体的响应时间,加入了自愿调度,也就是我是内核开发者,我在开发这个驱动或者子系统的时候,我觉得这里我占用CPU太久了,我主动加一行代码调用might_resched()增加抢占点,让别的任务执行一下,相比No Forced Preemption P3事件响应时间明显减少了,这种方式对吞吐量几乎没影响。

img

3、Preemptible Kernel(Low-Latency Desktop)

img

img

可抢占内核,就是内核态执行过程中,除了临界区以外的所有内核代码可抢占,也就是在上面的基础上增加了**中断处理返回内核态(内核态抢占)**的抢占点。

提供了很低的响应延迟,最坏情况的延迟时间是几毫秒,代价是稍微降低吞吐量和稍微增加运行时开销。相比Voluntary Kernel Preemption,从事件发生到高优先级的p3到得到运行之间的时间更少了。

这种模型主要用于有毫秒级别延迟需求的桌面系统和嵌入式系统(linux 2.6 以上),比如音视频处理。

img

那为什么到这linux还不是一个硬实时操作系统呢?因为增加了中断处理返回内核态的抢占点,内核态中,只要不是关中断的地方,都可能发生抢占,这时候内核开发就变复杂了,任何内核代码都要考虑不同的上下文会不会有重入/死锁问题,多核下死锁的问题,进而增加了更多的临界区,这些临界区是不能抢占的。

所以就算linux启用可抢占内核,还有很多临界区和机制是默认不能抢占的,spinlock默认禁止抢占(整个内核态有10万+地方使用),同时硬中断的执行时间不确定,软中断总是抢占应用上下文等等影响任务调度时间的地方。

4、Full Real Time Preemption(PREEMPT-RT)

也就是我们说的实时补丁,linux实时化的方案之一。

img

使能RT补丁,得到硬实时kernel,几乎任何地方都可以发生抢占,这种模型主要用于延迟要求为100微秒或稍低(几十微秒)的实时系统。 降低吞吐量、增加更多运行时开销。

PREEMPT-RT包含了hrtimer、优先级翻转、可抢占RCU、中断线程化、Full Tickless、EDF调度等等这些机制来保证系统的整体实时性。其中的90%多已经进入主线内核。

(1)仓库http://git.kernel.org/cgit/linux/kernel/git/rt/linux-rt-devel.git

(2)仓库http://git.kernel.org/cgit/linux/kernel/git/rt/linux-stable-rt.git

img

上下文切换时间

那下一个运行的任务选出来了,linux完成上下文切换需要多久?得益于现在的CPU针对性优化设计,linux上下文切换时间是很短的,与处理器架构相关。

下篇文章介绍Linux实时方案,详见实时linux方案概述

参考链接

Real-Time Linux Wiki

https://blog.csdn.net/fightingskyer/article/details/118877564

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/644607.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 中的注解(Annotation)

Java 中的注解(Annotation) 一、元注解1.Java 中的元注解 二、Java 中内置的三大注解三、自定义注解1.语法格式 四、反射注解五、注解的作用六、总结 所有的注解类型都继承自 java.lang.annotation.Annotation 接口。注解(Annotation)是一种引用数据类型…

正则表达式 格式化excel表格数据

一、从excel表格复制一列数据 二、形成数据格式 ‘4013197767140’,‘5776879019003’, 三、操作 打开编辑器,使用正则匹配

k8s---helm

Helm是什么? 在没有helm之前。部署一个服务,需要deployment、service、ingress、挂在卷等等相关配置都需要人工来配置。 helm的作用就是通过打包的方式,把需要人工编写的配置集成在一起。是一键式的部署服务。类似于yum功能。 由官方提供的…

C++笔记(二)

函数的默认参数 如果我们自己传入数据,就用自己的数据,如果没有,就用默认值 语法: 返回值类型 函数名(形参默认值){} int func(int a,int b20,int c30){} …

pytorch实战-6手写数字加法机-迁移学习

1 概述 迁移学习概念:将已经训练好的识别某些信息的网络拿去经过训练识别另外不同类别的信息 优越性:提高了训练模型利用率,解决了数据缺失的问题(对于新的预测场景,不需要大量的数据,只需要少量数据即可…

2012-2022年全国各省数字经济相关指标数据合集(18个指标)

2012-2022年全国各省数字经济相关指标数据合集(18个指标) 1、时间:2012-2022年 2、指标:地区、year、互联网接入端口数、互联网宽带接入用户数、互联网域名数、移动电话普及率、长途光缆线路长度(万公里)…

java开发——《并发编程》

目录 一.jmm 二.并发了什么 1.只有一个核(单核)并发还有没有意义 2.单核,还有什么可见性问题 3.并发和并行 三.volitaile 1.变量的可见性问题 2.原因是什么 3.本次修改的变量直接刷到主内存 4.声明其他内存对于这个地址的缓存无效 …

highcharts.css文件的样式覆盖了options的series里面的color问题解决

文章目录 一、问题背景二、解决问题 一、问题背景 原本的charts我们的每个数据是有对应的color显示的,如下图: 后面我们系统做了黑白模式,引入了highcharts的css文件,结果highcharts的css文件中class的颜色样式覆盖了我们数据中的…

ChatGPT与文心一言:应用示例与体验比较

ChatGPT 和文心一言哪个更好用? 为了更好地感受ChatGPT和文心一言这两款AI助手如何在实际运用中竞相辉映,我将提供一些典型的应用示例。这些示例都取自真实的用户体验,以帮助解释这两种工具如何让日常生活或工作变得更加轻松。 ChatGPT Ch…

【云原生】Docker的端口映射、数据卷、数据卷容器、容器互联

目录 一、端口映射(相当于添加iptables的DANT) 二、数据卷创建(宿主机目录或文件挂载到容器中) 三、数据卷容器(多个容器通过同一个数据卷容器为基点,实现所有容器数据共享) 四、容器互联&am…

Java 设计者模式以及与Spring关系(六) 装饰和模版方法模式

简介: 本文是个系列一次会出两个设计者模式作用,如果有关联就三个,除此外还会讲解在spring中作用。 23设计者模式以及重点模式 我们都知道设计者模式有3类23种设计模式,标红是特别重要的设计者模式建议都会,而且熟读于心&#…

Deployment介绍

1、Deployment介绍 Deployment一般用于部署公司的无状态服务。 格式: apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metada…

菜鸟导入导出assetbundle

因为菜鸟不会用unity c#什么的,所以最后参考贴吧的方法用的是UABE(Unity Assets Bundle Extractor)和UABEA(Unity Assets Bundle Extractor Avalonia) 可以去github上下载 对于txt、xml什么的可以直接改,但是byte文件里还是会有一些类似乱码的东西&…

Qt5项目拆解第一集解决:中文乱码| 全局字体|注册表|QSS/CSS

# 一、乱码解决代码片段 QTextCodec是Qt中用于处理文本编码和字符集转换的类。它提供了一系列静态函数来实现不同编码的文本转换,包括编码转换、字符集检测和转换、以及数据流中的文本编码处理。QTextCodec类使得Qt可以在不同的编码和字符集之间进行无缝转换,从而方便地处理…

Switch用法以及新特性-最全总结版

本篇文章参考了大佬文章,感谢大佬无私分享: http://t.csdnimg.cn/MjZnX http://t.csdnimg.cn/QFg0x 目录 一、Switch用法:JDK7及以前 1.1、举例一: 1.2、举例二: 二、Switch穿透: 2.1、举例&#xf…

【Linux】常见指令(二)

前言 常见指令第二部分。 文章目录 一、指令&#xff08;下&#xff09;重定向>&#xff1a;输出重定向>>&#xff1a;追加输出<&#xff1a;输入重定向 10. more—显示文本文件内容11.less—逐屏浏览文本文件内容12. head13. tail管道 |14. date—时间指令在这里插…

rust for循环步长-1,反向逆序遍历

fn main() {for i in (0..3).rev().step_by(1) {print!("{}", i);} } // 打印结果&#xff1a;210Trait std::iter::Iterator fn rev(self) -> Rev where Self: Sized DoubleEndedIteratorfn step_by(self, step: usize) -> StepBy where Self: Sized

DI和IOC

依赖注入&#xff08;Dependency Injection, DI&#xff09;和控制反转&#xff08;Inversion of Control, IoC&#xff09;是面向对象编程中的两个重要概念&#xff0c;它们紧密相关并在现代软件开发中经常结合使用。 依赖注入&#xff1a; 依赖注入是一种设计模式&#xff0…

2024年可能会用到的几个地图可视化模板

前言 在数字化的过程中&#xff0c;数据可视化变得越来越重要。用户喜欢通过酷炫的视觉效果和直观的数据展示来理解数据。可视化地图组件是数据可视化的重要组成部分。这些地图组件提供多样化的效果&#xff0c;能够更好地展示数据的关系和地理分布&#xff0c;直观地将数据与…

高高兴兴过春节

一年一度的春节到了&#xff0c;到处洋溢着节日的气氛&#xff0c;到处彩灯高照&#xff0c;鞭炮齐鸣。   早上&#xff0c;我早早地起来和姐姐一起给爷爷奶奶拜年&#xff0c;爷爷很开心给了我一个大大的红包。吃完早饭&#xff0c;妈妈贴春联&#xff0c;爸爸挂灯笼&#x…