TwinCAT3 实时内核调度算法

ops/2024/9/23 4:27:50/

前言

TwinCAT3 支持多核心CPU并行运行实时任务,根据官方网站的帮助信息“实时”定义取自DIN44300,而且实时任务的调度算法默认是 RMS算法(速率单调调度算法

RMS算法

来看一下百度百科的解释:
RMS(单调速率调度算法)是一种静态优先级调度算法,是经典的周期性任务调度算法。 RMS的基本思路是任务的优先级与它的周期表现为单调函数的关系,任务的周期越短,优先级越高;任务的周期越长,优先级越低。如果存在一种基于静态优先级的调度顺序,使得每个任务都能在其期限时间内完成,那么RMS算法总能找到这样的一种可行的统调度方案。
理论证明过程可以参看百度百科上的论述,这里不细说,直接给结论:
1)单核心处理器处理周期性任务时,RMS算法是最优的;
2)RMS算法是抢占式算法,周期越短的任务,优先级越高。
针对第二点,例如对于处理器来说,假定有2个任务,周期分别是 任务A:10 ms,任务B:50ms,那么CPU每50ms就会“中断”一次去执行任务A,A必须确保在10ms内执行完,假如A实际执行仅用2ms,那么剩下的8ms就可以给任务B执行,如果任务B实际执行需要35ms,那么执行完8ms以后,又到了10ms的中断时机,这时候CPU就把任务B挂起,把它的当前状态保存起来,以备后续接着执行任务B,转头去第二次执行任务A,任务A又用了2ms,这时候又空出来8ms来执行任务B,任务B再次执行8ms,CPU被迫中断,到目前为止,任务B总共运行了16ms,任务A运行了4ms,CPU运行了20ms。第三轮抢占再次开始,CPU第三次运行时,任务A占去2ms,任务B占去8ms,10ms时间又到了,CPU再次被中断,此时任务A运行了23=6ms,任务B总共运行了83=24ms,CPU总共运行了103=30ms;第四次抢占开始,任务A运行2ms,任务B运行8ms,CPU运行10ms,然后再次中断,到目前为止,任务A运行了24=8ms,任务B运行了 84=32ms,CPU运行了 104=40ms;第五次抢占开始,任务A运行2ms,任务B运行8ms,CPU运行10ms,任务A总共运行了25=10ms,这10ms是真正被任务A利用的CPU时间,CPU没有空转浪费。任务B运行3ms,这时,任务B总共运行了 32+3=35ms,才算是跑完了完整的“一圈”,期间被任务A多次打断。这时候CPU还剩 10-2-3=5ms空余时间,但是!!!!因为任务B的周期是50ms,所以CPU前四次总共执行了104=40ms,第五次实际跑任务A和任务B又花费了5ms,下一个10ms计时到,任务A的10ms中断和任务B的50ms周期中断一起触发,所以CPU空余时间实际上只有50-45=5ms,第六轮开始…
可以发现,在CPU运行的50ms时间内,任务A的代码被跑了5遍,任务B的代码只跑了1遍。

中断机制

Double-Tick中断

由于TwinCAT3支持多核心运行,衍生出两种核心分配机制即共享核心和独占核心,共享核心由TwinCAT实时调度器(下称 TwinCAT kernel)分配实时任务和Windows系统的占比,默认是 80%,即CPU在预设的实时周期中,其确保80%的CPU运算时间分配给实时任务,Windows系统只使用剩下的20%运算时间,这个值是可调的,如果接触过FreeRTOS这类tiny real-time kernel的人可能会注意到,在FreeRTOS中task的切换需要保存当前正在运行task的上下文,如果没有运行完,下一次排到它的时候,它就可以恢复当时的上下文环境(本质是寄存器中的值)接续运行。在TwinCAT的调度机制中,共享核心也需要在实时任务和非实时任务之前切换,若当前周期内实时任务没有运行完,那么就需要保存实时任务的上下文环境,以备下一周期恢复来接续执行。80%的设定就是保证在共享核心中,Windows系统总能获得20%的时间来执行,这个“切换点”就是中断来控制的,TwinCAT中称之为Double Tick。
下图中,第一个周期内,Double-Tick到来时实时任务还没有运行完,这时就需要保存实时任务的上下文环境,第二个Base Time到来的时候,上一次没有执行完的任务又获得了一段执行时间(绿色和红色的部分),然后才轮到了本次的“读输入-执行代码-写输出”的实时任务。
在这里插入图片描述

Tick中断

Tick中断是用来规划CPU时间片的,例如有两个核心的CPU,其中一个核心运行了PLC Task,该PLC Task的运行周期是10ms,那么每10ms中断一次就是Tick中断在负责。注意这里的Base Time就是10ms,如果在TwinCAT中把 Base Time设为100us,但是PLC Task设为 10ms,那么下图中的Base Time还是10ms,这个是要注意区分的。
在这里插入图片描述
在独占核心的情况下,Double-Tick中断没有存在的价值,因为整个核心被用来跑实时任务,也就是说TwinCAT Real-Time Kernel独占这个核心,Windows操作系统不能使用这个核心来运行了,那么实时任务的调度就变得简单了,如下图所示,这样用户的PLC程序获得了更过的CPU时间,用来跑一些计算量大的程序或者对jitter要求严苛的程序适合使用独占核心的这种配置方法,jitter会在Double-Tick的时候产生,由于和用户程序相关这个jitter存在“抖动”。
在这里插入图片描述

超时机制

对于用户而言,预测自己程序的执行时间非常困难,尤其是目前多核心的CPU,结合不同的核心分配机制,这个时间是不确定的,那么一旦用户程序写的非常复杂,在一个周期内并不能运行完毕该怎么办,TwinCAT的处理方法是放到下一个周期中继续运行,这样实际上挤压了下一个周期中程序的执行时间,导致后面每个周期都不能来运行本属于自己这个周期的程序,反而得腾挪时间来跑上一次积压下来的程序,这样的话,实际上几轮周期下来,对应关系就乱起来了,而且程序实际跑了几圈并不能通过周期运行圈数来一一对应,这种情况其实是不允许的。
如下图所示,CPU跑了4圈,但程序实际上只执行了3次,这种情况就会导致超时计数器累加。
在这里插入图片描述
一个正常运行的程序,超时计数器不应累计,应当始终为零,如下图所示
在这里插入图片描述


http://www.ppmy.cn/ops/33801.html

相关文章

解决Uncaught TypeError: Cannot read properties of null (reading ‘getAttribute‘)

问题: 用了element ui 的echart ,初始化时候找不到指定id的元素,导致的问题,如下 浏览器控制台输出的错误信息如下 Echars echarts.min.js:22 Uncaught TypeError: Cannot read properties of null (reading getAttribute)at echarts.min.…

Android使用kts发布aar到JitPack仓库

Android使用kts发布aar到JitPack 之前做过sdk开发,需要将仓库上传到maven、JitPack或JCenter,但是JCenter已停止维护,本文是讲解上传到JitPack的方式,使用KTS语法,记录使用过程中遇到的一些坑.相信Groovy的方式是大家经常使用的,…

结构体介绍(2)

结构体介绍(2) 前言一、结构体的内存对齐之深入理解为什么存在内存对齐?修改默认对齐数 二、结构体传参2.1:该怎么传参呢? 三、结构体实现位段3.1什么是位段位段的内存分配位段的跨平台问题 总结 前言 根据之前讲了结…

【八股】AQS,ReentrantLock实现原理

AQS 概念 AQS 的全称是 AbstractQueuedSynchronized (抽象队列同步器),在java.util.concurrent.locks包下面。 AQS是一个抽象类,主要用来构建锁和同步器,比如ReentrantLock, Semaphore, CountDownLatch,里…

使用python和pyqt开发的抽签小程序v1.0

使用python和pyqt开发的抽签小程序v1.0 作用效果代码 作用 对输入框中的文本进行随机抽取,抽取数量为3行。 效果 代码 import sys import random from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QTextEdit, QPushButton, QMessageBoxclass Ra…

Android Studio学习笔记——数据库存储

Android Studio学习笔记——数据库存储 6.1持久化技术简介6.2 文件存储将数据存储到文件中从文件中读取数据 6.3 SharedPreferences存储6.3.1 将数据存储到是SharedPreferences中6.3.2 从SharedPreferences中读取数据6.3.3 实现记住密码功能 6.4 SQLite数据库存储6.4.1 创建数据…

急速入门Prompt开发之跨国婚姻小助手

文章目录 前言MoonShot编写提示词对接模型WebUI编写完整代码 前言 整个活,同时分享技术~至于是啥活,懂得都懂,男孩子自强自尊自爱!!! 先看看实现效果吧: 那么这里的话,我们使用到的…

Linux内核深入学习 - 内核同步

目录 内核抢占 同步原语 per-CPU变量 API Per CPU 变量的应用 per CPU 变量在多文件下的用法 原子操作 API 优化和内存屏障 自旋锁 自旋锁 API 函数 读写锁 API RCU 信号量 API 1. 信号量的结构: 2. 初始化函数sema_init 3. 可中断获取信号量函数…