33 Linux内核高精度定时器实现延时

Linux内核时间管理与延时机制:从jiffies到高精度定时器实战 在操作系统与嵌入式开发中,时间管理是核心基础概念,涉及系统调度、硬件交互和性能优化等多个层面。其原理基于计算机的时钟中断机制,通过周期性中断驱动时间计数与任务调度。这一机制的技术价值在于平衡精度与开销,为上层应用提供可靠的时间基准。在驱动开发、实时系统和高性能计算等应用场景中,开发者需要根据具体需求选择合适的时间度量与延时方法。本文聚焦Linux内核中的时间处理,深入解析jiffies机制与高精度定时器(hrtimer)的实现差异,帮助开发者避免常见陷阱,提升代码的稳健性与效率。 阅读详情

33.1 前言

对于Linux驱动开发来说,我们不可避免会使用到延时函数,其中最为常见的延时函数有msleep、usleep(sleep这些是睡眠不占用cpu的),还有mdelay、udelay(delay是CPU忙等待,定时精准但占用cpu),上述延时函数各有优缺点。对于普通情况的延时,也就是多一秒也没大关系的用sleep类延时函数完全没问题,对于有精准延时的用delay类函数一般也没啥问题。如果涉及到硬件时序操作的,我们必定要使用精准的延时函数,如果在对应的地方使用不精准的sleep类延时函数,则会出现下面时序巨大的时序偏差。

                              

然而,如果使用delay函数对于系统性能来说是一个硬伤害,CPU忙等待表示CPU干不了其它事情,只能瞎等。因此,为了解决这种资源浪费问题,必须用另外一个办法解决,那就是使用高精度定时器+条件等待,实现延时函数的功能。

33.2 hrtimer高精度定时器

内核从2.6.16开始加入了高精度定时器架构,高精度定时器架构具有稳定快速的查找、插入、删除定时能力及排序功能,红黑树(rbtree)来组织hrtimer,红黑树已经以库的形式存在于内核中,并被成功地使用在内存管理子系统和文件系统中,随着系统的运行,hrtimer不停地被创建和销毁,新的hrtimer按顺序被插入到红黑树中,树的最左边的节点就是最快到期的定时器,内核用一个hrtimer结构来表示一个高精度定时器。

hrtimer相关函数

void hrtimer_init(struct hrtimer *timer, clockid_t clock_id, enum hrtimer_mode mode)

高精度定时器初始化;timer高精度定时器数据结构;clockid定时的时间类型(如实时时间、开机时间);mode定时器模式

hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)

高精度定时器启动;timer定时器结构;tim定时时间;mode定时器模式

ktime_t ktime_set(const long secs, const unsigned long nsecs)

定时器时间设定函数;secs秒;nsecs纳秒

hrtimer_forward_now(struct hrtimer *timer, ktime_t interval)

设置超时时间;interval下次超时时间

int hrtimer_cancel(struct hrtimer *timer)

关闭定时器

enum hrtimer_restart (*function)(struct hrtimer *)

定时器超时回调函数

33.3 Linux等待队列

在驱动开发中,有时不可避免需要进行阻塞,如当硬件数据未准备好,此时程序必须阻塞等待数据准备好才能读,否则读取到的数据内容将是无效数据。为了支持应用层这种阻塞与非阻塞的功能,驱动程序就需要提供阻塞(如等待队列,中断)和非阻塞方式(如轮询,异步通知)机制。

Linux内核中,等待队列是常用的阻塞条件出发机制,在数据或任务不能被读取或执行时,将要执行的任务放入等待队列中,当条件到达及唤醒等待队列时再执行即可。

等待队列阻塞分为ASK_UNINTERRUPTIBLE(不可打断)模式睡眠、TASK_INTERRUPTIBLE(可打断)模式睡眠,在不可打断睡眠中,就算发送kill信号程序也不会响应。

等待队列函数

wait_queue_head_t queue;

等待队列结构

init_waitqueue_head(wait_queue_head_t* queue)

初始化等待队列;

wait_event(*queue, int condition)

不可打断等待;condition等待条件

wait_event_interruptible(*queue, int condition)

可打断等待模式;

wait_event_timeout(queue, condition, timeout)

超时条件等待不可中断函数;

wait_event_interruptible_timeout(queue, condition, timeout)

超时条件等待可中断函数

wake_up(wait_queue_head_t *queue);

等待唤醒queue所有进程

wake_up_interruptible(wait_queue_head_t *queue)

等待唤醒queue所有进程

33.4 高精度定时器延时驱动实例

#include <linux/module.h>    
#include <linux/kernel.h>    
#include <linux/hrtimer.h>    
#include <linux/jiffies.h>    
  
struct _stIdelayMngr{  
    int nQueWaiting;                    /*等待队列条件*/  
    wait_queue_head_t iwaitQue;         /*等待队列*/  
    struct hrtimer ihrtimer;            /*高精度定时器*/  
};  
struct _stIdelayMngr stIdelayMngr;  
  
//示例程序  
int hrtimer_main()  
{  
    while(1)  
    {  
        /*启动高精度定时器,结合等待队列延时1ms*/      
        hrtimer_start(&stIdelayMngr.ihrtimer,ktime_set(0,1000*1000),HRTIMER_MODE_REL);  
        wait_event(stIdelayMngr.iwaitQue,stIdelayMngr.nQueWaiting);  
        stIdelayMngr.nQueWaiting = 0;  
  
        /*do something you want*/  
        //.....  
    }  
    return 0;  
}  
  
/* 定时器回调函数 */    
static enum hrtimer_restart hrtimer_hander(struct hrtimer *timer)    
{  
    stIdelayMngr.nQueWaiting = 1;  
    wake_up(&stIdelayMngr.iwaitQue);  
    return HRTIMER_NORESTART;  
}  
  
static int __init hrtimer_demo_init(void)    
{  
    memset(&stIdelayMngr,0,sizoef(stIdelayMngr));  
    /*初始化等待队列*/  
    stIdelayMngr.nQueWaiting = 0;  
    init_waitqueue_head(&stIdelayMngr.iwaitQue);  
  
    /*初始化高精度定时器*/  
    hrtimer_init(&stIdelayMngr.ihrtimer,CLOCK_MONOTONIC,HRTIMER_MODE_REL);    
    stIdelayMngr.ihrtimer.function = hrtimer_hander;    /* 设置回调函数 */    
    hrtimer_start(&stIdelayMngr.ihrtimer,ktime_set(1,0),HRTIMER_MODE_REL);  /* hrtimer启动 */    
  
    return 0;    
}  
  
static void __exit hrtimer_demo_exit(void)    
{  
    /* hrtimer注销 */    
    hrtimer_cancel(&stIdelayMngr.ihrtimer);  
}  
  
module_init(hrtimer_demo_init);    
module_exit(hrtimer_demo_exit);    
MODULE_LICENSE("GPL");  

 

 

 

Matlab pause函数精度不够?试试这几种替代方案(附性能对比) 本文深入探讨了Matlab中pause函数精度不足的问题,并提供了多种高精度延时替代方案,包括Java线程方案、定时器对象及跨平台优化实践。通过性能对比和实战案例,帮助开发者在信号处理、硬件通信等场景中实现从毫秒到微秒级的精确控制,显著提升系统稳定性和数据采集准确性。 阅读详情

相关推荐

避坑指南:在OpenWrt上为SDI-12传感器写Linux字符设备驱动,时序调试全记录

本文详细解析了在OpenWrt系统上为SDI-12传感器编写Linux字符设备驱动的全过程,重点解决了时序调试中的关键问题。通过GPIO配置优化、RT-Preempt内核补丁应用及硬件层调试技巧,实现微秒级精确控制,提升传感器通信稳定性,适用于环境监测等嵌入式场景。

weixin_30252709的博客 419

Linux内核中的延时函数详解

本文讲述了内核中涉及的两种不同性质的延时函数,并分析了各自的应用场景。

Leon的博客 1万+

【信息科学与工程学】【产品体系】计算机科学与自动化——第一百八十九篇 操作系统内核(微内核/宏内核)函数与算法02

宏内核(Linux)更多典型内核函数/算法,从编号271开始,覆盖中断管理、热插拔、PCI、ACPI、固件、崩溃转储、kexec、休眠、watchdog、RTC、hwmon、LED、backlight、input子系统、remoteproc等更多领域。编号类型领域内核类型内核中的函数/算法/模块/模组模块的调用关系模块/函数/算法逐步推理思考的数学表达式及参数列表及参数数值设计模块的C/C++/其他代码关联知识271中断管理中断描述符宏内核 / (中断子系统核心)驱动申请中断 → → → 分配irq_

weixin_49199313的博客 110

linux 内核中的延时函数

linux 内核中的延时函数

我的博客 622

【BlueZ 】内核态驱动适配:通用蓝牙芯片的驱动对接逻辑

本文基于BlueZ 5.87与Linux内核蓝牙子系统,深度解析通用蓝牙芯片与BlueZ协议栈的驱动对接全链路。从HCI驱动架构、hciattach工具初始化流程,到UART/H4/BCSP等协议层对接,详述了Broadcom、Intel、Atheros等主流芯片的初始化机制,涵盖固件加载、波特率切换、事件上报及异常处理。重点剖析N_HCI线路规程与ioctl交互原理,揭示用户态与内核态协同机制,并提供驱动移植、调试实战与适配规范,实现对蓝牙硬件的标准化、可扩展驱动开发。

byte轻骑兵的技术小窝 6768

【ShaderToy】开篇

写在前面呜呼,好久没有写博客了,好惭愧。题外话,感觉越大就越想家,希望可以一直和家人在一起,哪怕只是坐在一起不说话也觉得很温暖,一想到要分开眼睛就开始酸,哎。开学还是爬上来老实更新博客学习吧~今天爬上来一看,发现优快云的博客编辑终于更新了!进步总是好的,以前的编辑器实在很捉急。使用这种标记语言的确方便了很多,但好像颜色字体没法设置?程序员果然对美观没什么追求。ShaderToy如果你还没听过Sha

candycat 8万+

内核延迟函数分析

<br />linux内核提供3个函数分别进行纳秒,微妙和毫秒延时:<br />void ndelay(unsigned long nsecs);<br /><br />void udelay(unsigned long usecs);<br />void mdelay(unsigned long msecs);<br />这3个函数的延时原理是忙等待,也就是说在延时的过程中并没有放弃cpu,根据cpu的频率进行一定次数的循环。<br />在内核中对于毫秒级以上的延时,最好不要直接使用mdelay函数,这将

fdaopeng的专栏 5509

Synopsys工具链实战:如何用VCS、DC、ICC和Calibre跑通你的第一个数字IC设计项目?

本文详细介绍了如何使用Synopsys工具链(VCS、Design Compiler、ICC和Calibre)完成数字IC设计项目,从RTL代码到GDSII版图的全流程。涵盖环境配置、RTL设计验证、逻辑综合、物理实现及签核验证等关键步骤,帮助工程师掌握高效的数字IC设计流程。

weixin_42525005的博客 197

延时函数

一、内核的延时函数 应用程序的睡眠函数 #include <unistd.h> unsigned int sleep(unsigned int sec) int usleep(unsigned int usec) 驱动程序的睡眠函数 睡眠延时,会形成阻塞,导致进程调度(长延时)。 优点:优点不占用CPU资源。 缺点:时间精确度低 #include <linux/delay.h> void ssleep(unsigned int seconds) //秒级别 void

weixin_42832472的博客 1966

ORB-SLAM3复现的详细过程——配置安装及ROS和脚本运行---Ubuntu20.04

所提供的图像具有高动态范围,事先进行了光度标定,用20Hz的帧率采集,分辨率为1024像素*1024像素;需要下载数据集dataset-room1_512_16和rgbd_dataset_freiburg1_desk。在一键安装ROS后,只需要再安装Pangolin即可,其他所有的需要都已经存在。用微型飞行器采集的视觉惯性数据集,包含双目相机和IMU同步测量数据及位姿的真值。第二条命令中的${ROS_PACKAGE_PATH}是自己文件的路径。其采用的相机和IMU传感器,在硬件上进行了时间同步。

琉璃轻纱的博客 1万+

【Bug已解决】Anthropic tool_result 找不到对应 tool use id 解决方案

方案适用场景推荐指数每个tool_use必须生成对应tool_result最基础的原则,所有Harness都必须遵守⭐⭐⭐⭐⭐裁剪历史时成对处理实现了上下文裁剪/压缩逻辑的Harness⭐⭐⭐⭐⭐并行工具调用结果数量校验支持多工具并行调用的场景⭐⭐⭐⭐使用官方SDK高层封装不需要特别定制消息组装逻辑⭐⭐⭐⭐请求前主动校验中间件追求生产级健壮性,提前拦截问题⭐⭐⭐⭐⭐这类报错,本质上是。

一键难忘的博客 1万+

linux内核中的睡眠函数*delay、*sleep

内核中的睡眠、延时函数。

7583

基于Simulink进行步进电机的重复控制仿真建模

重复控制概述目的:通过引入一个周期延迟环节来补偿系统的周期性误差,从而提高系统对周期性参考信号或扰动的跟踪性能。方法内部模型原理:在控制器中嵌入一个与周期性信号相关的模型(例如周期延迟环节),以实现对周期性误差的零稳态误差控制。滤波器设计:为了避免高频噪声放大,通常会在重复控制器中加入低通滤波器。优势对周期性信号具有良好的跟踪性能。不需要精确的数学模型即可实现高性能控制。挑战:需要合理设计重复控制器的参数以避免系统不稳定。

amy_mhd的博客 268

C/C++高精度时间获取与延时实现:从steady_clock到混合等待

在性能调优、实时控制和音视频同步等场景中,高精度时间测量与延时控制往往是决定系统稳定性的关键。从早期的time()到现代C++的std::chrono库,开发者面临多种时间获取与定时方案的选择。单调时钟与墙上时钟的差异、线程休眠与忙等的精度权衡,以及Linux和Windows平台不同的实现机制,都可能成为隐蔽的坑点。本文从时间源原理出发,对比clock_gettime、QueryPerformanceCounter等常见接口,深入分析纳秒级延时的误差来源,并给出混合等待、固定步长循环等工程实践方案,帮助开发

weixin_33843947的博客 441

通过WorkVisual连接KUKA机器人的具体方法

通过WorkVisual连接KUKA机器人的具体方法

Robot_PLC_HMI_Automation 6843

Linux C/C++ or 嵌入式面试之《C/C++笔面试系列》(10) C++ 前置后置增减运算符重载形式与比较

C语言的++、–运算符在此不讨论。 文章目录1、前置后置增减运算符重载的形式2、前置和后置运算符的性能比较 1、前置后置增减运算符重载的形式 自增运算符“++”和自减运算符“–”分别包含两个版本。即运算符前置形式(如 ++x)和运算符后置形式(如 x++),这两者进行的操作是不一样的。因此,当我们在对这两个运算符进行重载时,就必须区分前置和后置形式。C++根据参数的个数来区分前置和后置形式。如果按照通常的方法来重载 ++ 运算符(即作为成员函数重载时不带参数,或者作为非成员函数重载时带有一个参数),那么重载

二进制君 5831

LKMPG时间管理:jiffies与ktime高精度计时

在Linux内核模块开发中,时间管理是实现周期性任务、延时操作和性能测量的核心基础。本文将系统讲解内核中两种主流计时机制——jiffies(节拍计数)和ktime(高精度时间)的设计原理与实战应用,帮助开发者根据场景选择最优计时方案。通过[examples/kbleds.c](https://link.gitcode.com/i/d4cd63d8c0746b3875f5098ccbc77b68)等...

gitblog_01114的博客 961

uniapp - 实现集成调用zebra斑马打印机+打印标签+打印二维码详细实例代码,通过蓝牙连接打印机打印与通过打印机IP和端口两种方式适配斑马打印机(全平台兼容H5、微信小程序、苹果安卓App)

uniapp适配斑马打印机 实现标签打印,uniapp适配斑马打印机实现标签打印,uniapp调用zebra斑马打印机打印标签,uniApp连接传统蓝牙的斑马打印机打印,实现标签打印功能uniapp 蓝牙连接斑马打印机发送zpl指令打印,适配斑马(Zebra)牌打印机,小程序调用蓝牙打印机完整代码,uniapp 打印机wifi链接 蓝牙链接,uniapp斑马打印机,实现二维码标签展示以及打印,APP端连接打印机打印小票和标签,uniapp使用斑马打印中文不出来,打印机连接不上,打印没反应怎么办,打印报错,斑

🏆 前端领域优质创作者 1万+

操作系统定时器相关(AI回答)

RTC芯片仅提供基础时钟源,内核通过时间轮、红黑树等数据结构管理多个定时器。高精度定时器(hrtimer)采用红黑树实现纳秒级精度,而传统定时器(timer_list)使用双向链表管理毫秒级任务510。总结:Linux内核定时器没有统一使用优先队列,而是根据场景混合使用链表、红黑树和时间轮。Linux内核定时器的底层实现并非单一数据结构,而是根据不同类型和场景采用多种机制。内核采用多级时间轮(如Hierarchy时间轮)高效管理大量定时器,通过哈希和链表减少遍历开销610。处理函数中分时处理不同任务。

yaoct的博客 379

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

《linux设备驱动开发详解》笔记——10中断与时钟

10.1 中断与定时器   中断一般有如下类型: 内部中断和外部中断:内部中断来自CPU,例如软件中断指令、溢出、除0错误等;外部中断有外部设备触发 可屏蔽中断和不可屏蔽中断 向量中断和非向量中断,ARM一般是非向量中断,因为现在的中断源很多,如果做成向量,那中断向量表会很大。不过ARM的总异常还是按照向量的方式组织的。 ARM cortex-A9 中断体系举例: 向...

weixin_30606669的博客 301

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

STM32MP157D-DK1高精度PPS输出:从PWM配置到相位校准全指南

秒脉冲(PPS)是时间同步系统中的核心基准信号,广泛用于通信、电力自动化、测量仪器和车载设备。如何从嵌入式平台稳定输出高精度的1PPS,是许多工程师面临的实际挑战。借助硬件定时器PWM输出,可以避免软件翻转带来的抖动,但周期与相位的双重控制仍需精心设计。本文从PPS的基本原理出发,讲解在STM32MP157D-DK1上基于Linux的完整实现路径:引脚选型、内核配置、设备树修改、sysfs验证,以及通过软件锁相环进行相位校准的方法。同时记录调试过程中遇到的典型问题与解决方案,帮助开发者在嵌入式Linux板卡

weixin_33857679的博客 450

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

高精度实时运动控制:从PID算法到异构架构的工程实践

实时控制系统是自动化与嵌入式领域的核心技术,其核心在于确保任务执行的确定性与可预测性,而非单纯追求高处理速度。系统通过实时操作系统或专用硬件定时器,在严格的时间窗口内完成传感、计算与驱动输出,以满足工业控制、机器人及精密仪器等场景对时序的严苛要求。在工程实践中,PID控制算法及其抗饱和处理、前馈补偿等优化手段,是实现稳定位置闭环的关键;而S型速度规划则能有效平滑运动曲线,减少机械冲击。随着系统复杂度提升,采用通用处理器与实时协处理器相结合的异构计算架构,成为平衡开发效率与硬实时性能的主流方案。本文以运动控制

weixin_34025051的博客 1185

STM32实战:C++封装定时器输入捕获,实现超声波测距与LCD显示

在嵌入式开发中,定时器输入捕获是实现精确测量的核心技术之一,常用于频率检测、脉宽分析等场景。而C++封装外设驱动可以显著提升代码的可维护性与复用性,尤其当项目涉及传感器、显示器和通信模块协同工作时,良好的抽象设计至关重要。本文以STM32F103为平台,结合超声波测距模块与ILI9341液晶显示,深入讲解如何用C++设计定时器捕获类、处理中断回调、规避边界条件陷阱,并给出从Keil迁移到VSCode+CMake的工程化实践。通过整合测距、测频与显示任务,帮助读者解决多外设协作中的时序冲突与调试难题,真正从单

weixin_34297704的博客 384

240 MHz安全MCU实战:Cortex-M33+Wi-Fi+43 GPIO开发指南

在物联网设备设计中,安全MCU正成为兼顾性能与信任链的关键选择。以一颗基于ARM Cortex-M33内核、运行频率240 MHz并集成Wi-Fi与43个GPIO的无线MCU为例,其硬件级安全启动、TrustZone隔离和独立射频子系统为智能家居、工业网关等场景提供了高性价比方案。嵌入式开发者在选型时需综合评估主频、引脚资源与安全特性,而在工程落地中则要重点处理GPIO规划、射频天线设计、低功耗策略、安全固件签名及OTA升级等环节。理解这些通用原理,有助于将安全MCU能力转化为稳定、可量产的产品,避免因引脚

weixin_34332905的博客 384

深入解析RGMII时序优化与PHY配置实战

本文深入解析RGMII接口的时序优化与PHY配置实战,涵盖千兆以太网中的2ns时钟延时精度要求、硬件实现技巧及PHY寄存器配置方法。通过详细案例和调试技巧,帮助工程师解决信号完整性、阻抗匹配等关键问题,提升RGMII接口的稳定性和性能。

sss66的博客 622

STM32嵌入式开发全解析:从Cortex-M内核到选型与实战避坑

在嵌入式开发领域,微控制器(MCU)是构建智能硬件的基础,而基于ARM Cortex-M内核的32位处理器凭借性能、功耗与成本的均衡表现,成为工程师最常用的方案之一。Cortex-M系列分为M0、M3、M4、M7等不同等级,分别面向简单控制、实时响应、DSP运算与高性能边缘计算等场景,理解其架构与存储/外设体系是选型和开发的前提。实际项目中,HAL库与图形化配置工具大幅降低了寄存器操作门槛,GPIO、UART、定时器、ADC等外设实践构成了基本功。同时,从裸机转向FreeRTOS实时操作系统、低功耗设计、P

weixin_34279246的博客 296
上一篇: curl实现ftp客户端 ftp上送内存数据实例
下一篇: 31 Linux input子系统按键驱动--4IO驱动16按键
Chasing_Chasing
博客等级 码龄10年 233粉丝 87原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值