linux 中高精度timer的实现

相关结构体

每个cpu上绑定一个hrtimer_cpu_base结构体,它的active_bases用位记录了有哪些种类的timer,对应每种类型的计时器红黑树(hrtimer_clock_base)在hrtimer_cpu_base->clock_base[]上。

软硬超时调试时机

软超时处理线程的调度时机有两个,一个是在硬中断中顺带触发,另一个是在每个时间片调度时通过run_local_timers来触发。

硬超时处理线程的调度时机是在hrtimer_reprogram和hrtimer_force_reprogram中设置到硬件上的,具体实现是通过tick_program_event设置到硬件上,计时器的触发有一次触发(CLOCK_EVT_STATE_ONESHOT)与周期性触发(CLOCK_EVT_STATE_PERIODIC)两种模式,一般是单次触发,再底层调用clockevents_program_event来配置硬件(dev->set_next_ktime,设置是时间还是时长由dev->features上有没有CLOCK_EVT_FEAT_KTIME来决定)。

软超时的处理

软超时处理的入口是hrtimer_run_softirq,这个线程中会找到达到了软超时的task(__hrtimer_run_queues),判断它没有disable(tasklet_struct->count==0)且处于TASKLET_STATE_SCHED的task(软超时的任务,__run_hrtimer),执行它的func或callback,并更新下一个即将到达的软超时时间。

硬超时的处理

硬超时是在超时hrtimer_interrupt到来时就直接在中断中处理的。

当时间到达时,触发hrtimer_interrupt,如果超过了软中断时间,将唤醒软中断处理线程,然后调用__hrtimer_run_queues找到硬超时的active 的 clock红黑树中所有硬超时的计时器,执行__run_hrtimer,它实际会从对应红黑树移除timer,触发绑定的函数:timer->function(timer),这个绑定函数的返回值表示是否需要将计时器更新后重加回红黑树中(红黑树操作函数为timerqueue_add和timerqueue_del)。调用hrtimer_update_next_event更新距离下次最早的软硬中断的等待时长,如果下一个时间点已经过了(虚拟机中运行或是callback过长将有可能导致硬中断处理太久),则尝试设置一个最小延时时长,并设置hang_detected标记,以防不断触发hrtimer_interrupt,最多尝试三次。

超时时间的设置

用户可以设置到期时间和宽限期(schedule_hrtimeout_range_clock),记录在timer->_softexpires和timer->node.expires上,在达到_softexpires时会在软超时处理线程中专门处理。如果达到expires,这个线程还没有处理,就在此时触发的硬超时里直接处理了。

注册定时器的接口是hrtimer_start_range_ns,如果是一个已经注册过的timer,会先把它从红黑树里取出来,并重新计算下一个触发的timer(可能是软计时也可能硬计时),更新到计时器硬件上(remove_hrtimer)。当没有下一个计时器时,超时时间是KTIME_MAX。更新timer的时长后再插入回计时队列(enqueue_hrtimer),如果发现它还是第一个计时器,则重新计算下一个触发的timer来将它的时间更新在计时器硬件上。

这里发现如果它真得是第一个计时器,则移除队列与加入队列后都有一个更新计时器硬件的过程,这两个过程是可以合并的,在remove_hrtimer上有一个reprogram参数把它置为false就可以了。但有个例外情况,就是计时器在其它cpu上。

另外,实时任务的软硬超时时间是一样的。

纳秒睡眠的实现

系统调用nanosleep(struct old_timespec32 __user *, rqtp, struct old_timespec32 __user *, rmtp) 中rqtp表示请求睡眠时间,rmtp表示剩余睡眠时间,当在指定的睡眠时间内被信号中断,则rmtp指向一个__kernel_timespec结构体,该结构体包含睡眠剩余时间的信息,以便调用者可以知道剩余的睡眠时间。如果不关心剩余的睡眠时间,可以将rmtp设置为NULL。

实现中调用hrtimer_nanosleep,核心在do_nanosleep,在hrtimer_sleeper_start_expires中将timer设置上,注册的回调是hrtimer_wakeup。然后调用schedule,提交当前线程(如果是内核中任务的话)并调度下一task。当调度回来时,删除timer(hrtimer_cancel),如果是超时唤醒的,则在hrtimer_wakeup中已将t->task为空,正常返回。如果是中断唤醒的,则do_nanosleep返回ERESTART_RESTARTBLOCK,它会使current->restart_block->fn 设置为hrtimer_nanosleep_restart,并更新超时时间,这样如果是用户调用的nanosleep,则在返回用户空间前,会自动重新调nanosleep。

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

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

相关文章

相册里的视频怎么提取音频?帮你整理了几个必备的!

有的时候视频中的音频包含重要信息,如对话、旁白、音乐等。提取音频不仅可以节省存储空间,还方便对这些信息进行单独处理和利用。那么如何提取音频呢?下面介绍了3种方法~ 方法一:直接使用手机相册自带功能 1、打开手机相册&#…

PAT 乙级1090危险品装箱

题目: 集装箱运输货物时,我们必须特别小心,不能把不相容的货物装在一只箱子里。比如氧化剂绝对不能跟易燃液体同箱,否则很容易造成爆炸。 本题给定一张不相容物品的清单,需要你检查每一张集装箱货品清单,…

C++(20):explicit(true/false)

explicit通常用于声明是否运行隐式转换: struct A {explicit A(int) { } };int main() {A a1 10; //编译报错,不运行隐式的通过int构造AA a2(10); //可以显示的构造return 0; } C20扩展了explicit,可以通过explicit(false)来禁用&a…

selenium自动升级115以上版本谷歌游览器驱动方案

原本selenium4已经更新了自动获取驱动的方案,但目前最大只能获取到115版本,而115版本还能够使用也只是因为114版本能够驱动谷歌游览器。 如今,我的谷歌游览器已经到了119版本,以前编写的自动更新驱动的方案全部报废。 自动更新Sel…

C语言重点突破(五) 动态内存管理

前言 动态内存管理是指在一个程序运行期间动态地分配、释放和管理内存空间的过程。在应用程序中,当程序需要使用变量或对象时,需要在内存中分配一段空间,并在使用完毕后释放该空间,以提高程序的效率和性能。本文意在介绍常用动态…

PostGreSQL:JSON|JSONB数据类型

JSON JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)JSON 是轻量级的文本数据交换格式JSON 独立于语言:JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许…

Android WMS——WMS窗口添加(十)

Android 的 WMS(Window Manager Service)是一个关键组件,负责管理窗口的创建、显示、布局和交互等。Window 的操作有两大部分,一部分是 WindowManager 来处理,一部分是 WMS 来处理,如下图所示: …

Android渲染流程

目录 缓冲区的不同生命周期代表当前缓冲区的状态: 多个源 ViewRootImpl: Android4.0: Android5.0: Android应用程序调用SurfaceFliger将测量,布局,绘制好的Surface借助GPU渲染显示到屏幕上。 一个Acti…

Python中字符串前“b”,“r”,“u”,“f”,“l”的作用

文章目录 1、字符串前加 u2、字符串前加 r3、字符串前加 b4、字符串前加 f5、字符串前加 “l” 1、字符串前加 u 例:u"我是含有中文字符组成的字符串。" name "中文字符".replace(u"中"," ")作用: 前缀u表示…

webpack、rollup、parcel 优势和劣势?

结论先行: webpack 是模块化构建工具,具有强大的 loader 和插件生态,适用于大型复杂项目的构建; rollup 适用于基础库的打包,功能没有webpack 强大; parcel 适用于简单的实验性项目,在公司真…

搜维尔科技:Varjo在心理学、医学研究、技术、工程学等领域都在使用

该软件用于心理学、医学研究、可用性、品牌和营销等领域。vajio头显组合到了运动8.0平台中,提供了在高保真虚拟环境中进行的行为研究,否则这些环境的成本太高,不切实际,甚至无法在现实世界中再现。 在心理学、医学研究、可用性、技术、工程学、市场营销等领域工作的学术和商业研…

【编程语言发展史】C语言的诞生及其影响

目录 一、C语言的历史背景 二、C语言的设计思想 三、C语言的语法特点 四、C语言的应用领域 五、C语言的影响 六、总结 C语言是一种高级计算机编程语言,它的诞生和发展对计算机科学和软件工程领域产生了深远的影响。本文将详细介绍C语言的诞生及其影响&#xf…

分类预测 | Matlab实现KOA-CNN-GRU-selfAttention多特征分类预测(自注意力机制)

分类预测 | Matlab实现KOA-CNN-GRU-selfAttention多特征分类预测(自注意力机制) 目录 分类预测 | Matlab实现KOA-CNN-GRU-selfAttention多特征分类预测(自注意力机制)分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matla…

springboot源码阅读需要提前了解的知识点

SpringBoot 源码透彻解析——必须提前了解的几个知识点(这些玩意充斥到springboot源码的各个角落) SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class,getClass().getClassLoader() : 根据 spring.factories文件,获取实现…

线代学习笔记-向量

numpy广播机制,自动增加维数 numpy中的array函数生成向量,()是函数标配,()下必有一个[]表示向量元素集合,第一层[]下的后每一个[]代表一行,没有这个[],表示这…

AI图像识别初次尝试

1.人形识别结果 2.代码 pythonOpenCVyolov3训练库,代码如下: #!/usr/bin/env python3 # -*- coding: utf-8 -*- import cv2 import numpy as np import osimgFiles["pic03.jpg", "pic04.jpg"]netNone classesNone colorsNonedef r…

Python小试牛刀:GUI(图形界面)实现计算器UI界面(二)

上一篇:Python小试牛刀:GUI(图形界面)实现计算器UI界面(一)-CSDN博客 在上一篇文章中介绍了Python GUI常用的库,以及运用GUI标准库tkinter仅设计了计算器的UI界面。 而在本篇文章,…

【c++|opencv】二、灰度变换和空间滤波---5.中值滤波

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 1. 中值滤波 #include<iostream> #include<opencv2/opencv.hpp> #include"Salt.h"using namespace cv; using namespace std;voi…

一篇文章认识【性能测试】

一、 性能测试术语解释 1. 响应时间 响应时间即从应用系统发出请求开始&#xff0c;到客户端接收到最后一个字节数据为止所消耗的时间。响应时间按软件的特点再可以细分&#xff0c;如对于一个 C/S 软件的响应时间可以细分为网络传输时间、应用服务器处理时间、数据库服务器…

Web安全系列——敏感信息泄露与加密机制

一、前言 数字化时代&#xff0c;越来越多的数据正在被传输到Web应用程序中&#xff0c;这其中不乏个人或机构的敏感信息。 如果Web应用程序未采取正确的加密机制&#xff0c;这些信息可能会遭到窃取或篡改&#xff0c;从而使用户数据或机构的财产受到威胁。 二、加密机制失…