(十二)定时事件集成到多路IO机制

备战蓝桥杯单片机:从省赛真题中学硬件编程思维(以第十二届第二场为例) 本文以蓝桥杯单片机省赛真题为例,深入解析硬件编程思维的核心要点,包括状态机设计、硬件抽象层构建、数据流与显示逻辑解耦等关键技巧。通过分析第十二届省赛第二场的具体代码实现,帮助参赛者掌握单片机编程的实战方法,提升在蓝桥杯等竞赛中的解题能力。 阅读详情

前言

在本小节中,我们将展开对定时事件的研究。首先还是和研究信号事件部分一样,先看看它是如何集成到多路I/O中的(或者说是如何与event_base联系起来的)。

如何将定时事件集成到主循环中

由于seletc、poll、epoll这类多路I/O机制支持定时,所以将定时事件集成到主循环中比起信号事件容易的多。我们只需要将定时事件注册到小根堆上,然后根据堆顶(最短超时事件)来计算多路I/O机制需要等待的最大超时时间,这样超时之后,就可以处理就绪的定时事件了。

在主循环中,有这样一段代码:

if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) {
/* 没有激活的事件并且是非阻塞时 */
        timeout_next(base, &tv_p);
} else {
        /*
         * if we have active events, we just poll new events
         * without waiting.
         */
        evutil_timerclear(&tv);
}
...
res = evsel->dispatch(base, evbase, tv_p);
...
timeout_process(base);

timeout_next用于计算主循环最大的等待时间,这里将tv_p赋值为等待的时间。
然后evsel->dispatch调用具体的多路I/O机制的等待函数,比如epoll的epoll_wait,最后一个参数设置的定时时间就是timeout_next计算得出的时间。这样的话,就不用来一个定时事件就调用epoll_wait等待,而是将定时事件都集中在一起处理。

在这段代码中,有三个核心函数timeout_next、dispatch、timeout_process。接下来我们会介绍第一个和最后一个,dispatch放在关于多路I/O机制集成部分的小节讲。

timeout_next

static int
timeout_next(struct event_base *base, struct timeval **tv_p)
{
        struct timeval now;
        struct event *ev;
        struct timeval *tv = *tv_p;
        /* min_heap_top返回处于小根堆的堆顶的定时事件 */
        if ((ev = min_heap_top(&base->timeheap)) == NULL) {
                /* if no time-based events are active wait for I/O */
                //没有定时时间,讲等待时间赋为null,返回
                *tv_p = NULL;
                return (0);
        }
        //获取当前时间
        if (gettime(base, &now) == -1)
                return (-1);
        /*
         * 比较当前最快超时的时间与当前时间
         * 小与等与:不用等待了,直接返回
         */
        if (evutil_timercmp(&ev->ev_timeout, &now, <=)) {
                evutil_timerclear(tv);
                return (0);
        }
        //计算需要等待的时间,即超时时间-当前时间,并将结果赋给tv
        evutil_timersub(&ev->ev_timeout, &now, tv);

        assert(tv->tv_sec >= 0);
        assert(tv->tv_usec >= 0);

        event_debug(("timeout_next: in %ld seconds", tv->tv_sec));
        return (0);
}

该函数的作用就是计算需要等待的时间,步骤如下:

  1. 取得最快超时的时间
  2. 将其与当前时间比较
  3. 如若小于等与当前时间,证明已经超时了,将tv置成0,返回之后,dispatch会很快将其激活(等待时间都赋成0了)
  4. 如若大于当前时间,证明还有段时间需要等待,调用evutil_timersub函数做个减法,将等待时间赋给tv

tv指向tv_p,而tv_p用于给dispatch指定超时时间。

timeout_process

void
timeout_process(struct event_base *base)
{
        struct timeval now;
        struct event *ev;

        if (min_heap_empty(&base->timeheap))
                return;

        gettime(base, &now);
        //取得小根堆顶的事件,即最有可能已经超时的事件。
        while ((ev = min_heap_top(&base->timeheap))) {
                //如果当前定时事件的时间还没达到,直接退出循环
                if (evutil_timercmp(&ev->ev_timeout, &now, >))
                        break;

                /* delete this event from the I/O queues */
                event_del(ev);

                event_debug(("timeout_process: call %p",
                         ev->ev_callback));
                //激活
                event_active(ev, EV_TIMEOUT, 1);
        }
}

这个函数的逻辑也很简单:

  1. 把小根堆顶的事件的超时时间拿来和当前时间比较
  2. 如果大于,则证明时间还没到,那么小根堆其余的事件也不可能超时了
  3. 如果小于,证明该事件已经满足激活条件了(超时),将其激活
  4. 重复查看新的小根堆顶是否满足条件,直至不满足条件或者堆中已经没有事件了。

小结

在本小节中,我们知道了定时事件是如何集成到一起让主循环去处理的,并且仔细看了timeout_next以及timeout_process这两个重要的函数,在下一小节中,我们将看到关于时间管理部分的函数,即timeout_correct还有时间的加减、获取等。

Java面试第十二山!《Redis缓存》 Redis是Java面试必考的高频知识点,掌握其核心概念、数据结构、缓存问题解决方案及高可用架构,能让你在面试中脱颖而出。 阅读详情

相关推荐

嵌入式铁头山羊stm32:一文总结

本文是一篇STM32嵌入式开发的综合知识总结,涵盖了STM32基础概念、GPIO、通信协议、外设驱动等核心内容。文章首先介绍了STM32的基本概念和型号含义,然后详细讲解了GPIO的8种工作模式及实验案例。接着重点阐述了USART、I2C、SPI三种通信协议的原理和实现方法,包括硬件连接、编程接口和实验应用。此外还介绍了OLED显示原理、中断系统、定时器、ADC转换等关键技术,每个模块都配有对应的实验案例和代码实现参考。文章内容全面系统,既包含理论知识,又提供实践指导,适合作为STM32开发的快速参考手册。

古泽汉书的博客 2783

libevent学习笔记十:libevent集成定时器事件

libevent学习笔记十:libevent集成定时器事件 现在再来详细分析libevent中I/O事件和Timer事件的集成,与Signal相比,Timer事件的集成会直观和简单很多。Libevent对堆的调整操作做了一些优化,本节还会描述这些优化方法。 1、集成到事件主循环 因为系统的I/O机制像select()和epoll_wait()都允许程序制定一个最大等待...

jyl_sh的专栏 1359

【BlueZ】5.x 整体架构总览:用户态 + 内核态分层设计核心逻辑

本文系统解析了BlueZ 5.x蓝牙协议栈的架构设计与实现机制。主要内容包括:1. 架构演进:从多守护进程到统一bluetoothd进程,引入ManagementInterface革新内核交互方式。2. 分层设计:详细拆解用户态核心组件(适配器/设备管理、Profile框架、插件系统)、D-Bus抽象层、IO抽象层(GLib到ELL迁移)及内核协议栈交互机制。3. 关键技术:深入分析ManagementInterface的工作流程、GATT服务架构、OBEX子系统和事件驱动模型。

byte轻骑兵的技术小窝 1万+

[libevent]timeout_next()

static int timeout_next(struct event_base *base, struct timeval **tv_p) { struct timeval now; struct event *ev; struct timeval *tv = *tv_p; if ((ev = min_heap_top(&base->timeheap)) == NULL) {//如果

scnuxiaotao的博客 560

Python异步协程爬虫优化:解决aiohttp中ServerDisconnectedError的高效策略

本文深入探讨了在Python异步协程爬虫中使用aiohttp时,如何高效解决常见的ServerDisconnectedError问题。核心策略包括全局复用ClientSession、精细配置TCPConnector连接池、实施请求重试与速率限制,从而构建稳定、高效的异步爬虫架构,有效避免服务器断开连接错误。

pz890123的博客 857

在国产麒麟V10(arm64)上离线部署Docker 24.0.6和Compose 2.30.1,保姆级避坑实录

本文详细介绍了在国产麒麟V10(arm64)操作系统上离线部署Docker 24.0.6和Compose 2.30.1的完整流程,包括环境准备、架构认知、安装步骤、系统服务优化及生产环境加固。特别针对ARM64架构的兼容性问题提供了解决方案,帮助用户在信创环境中高效部署容器化技术。

weixin_30342209的博客 484

libevent的简单应用 .

http://blog.youkuaiyun.com/liuguanghui1988/article/details/7090531 Libevent的应用主要围绕几大事件:超时事件、信号事件、读/写事件。 下面就一一简单介绍一下它们的使用。 超时事件 示例:   [cpp] view plaincopy /*   * Compi

happylife1527的专栏 661

NHANES更新数据后,权重计算方式也更新了

官网说明在此:如果你比我还懒,我下载了几个说明文件。2021年8月至2023年8月的总样本量与之前的2年周期相似。然而,。特别是,与之前包括过度抽样的周期相比,非西班牙裔白人的样本量较高,而非西班牙裔黑人的样本量较低。此外,60岁及以上人群的样本量较高,而年轻群体的样本量较低。子组的估计值可能具有较低的精确度,因此,检测组间差异的统计能力可能较低。此外,年龄和种族/西班牙裔亚组(尤其是儿童和青少年年龄组)的估计值可能会显示意想不到的模式。

珏世佳人的博客 2410

Libevent源码分析-----超时event的处理

Libevent允许创建一个超时event,使用evtimer_new宏。

luotuo44的专栏 9974

Android——Handler详解

1. 简介 Handler是一套 Android 消息传递机制 可以说只要有异步线程与主线程通信的地方就一定会有 Handler。 在多线程的应用场景中,将工作线程中需更新UI的操作信息 传递到 UI主线程,从而实现 工作线程对UI的更新处理,最终实现异步消息的处理 使用Handler消息传递机制主要是为了多个线程并发更新UI的同时,保证线程安全 2. 相关概念解释 Handler、Message、Message Queue、Looper Android消息机制: 以Handler的sendMes

Yawn 7万+

字节跳动高频111道核心前端面试题解析,web开发增强

但是本人觉得看书也很必要,可以节省很多时间,常见的javascript的书,例如:javascript的高级程序设计,是每位前端工程师必不可少的一本书,边看边用,了解js的一些基本知识,基本上很全面了,如果有时间可以读一些,js性能相关的书籍,以及设计者模式,在实践中都会用的到。内容包括html,css,JavaScript,ES6,计算机网络,浏览器,工程化,模块化,Node.js,框架,数据结构,性能优化,项目等等。自定义指令(v-check、v-focus)的方法有哪些?v-model是什么?

2401_84094620的博客 1200

偷懒的网络框架libevent、libev框架介绍

本文对libevent的api进行深入的讲解,并剖析libevent的evbuffer源码。

清风 3467

数据分析案例-对某宝用户评论做情感分析

目录 原始数据 绘制词云图 情感分析 原始数据 原始数据为某宝一商品的用户评论数据 绘制词云图 # coding=utf-8 import jieba import re import wordcloud import imageio # 打开需要分析词频的文本 with open('淘宝评论3.0.txt', encoding='utf-8') as f: data = f.read() # 文本预处理 :去除一些无用的字符只提取出中文出来 new_data

m0_64336780的博客 1万+

Redis设计与实现 学习笔记 第十二章 事件

3.对文件事件和时间事件的处理都是同步、有序、原子地执行的,服务器不会中途中断事件处理,也不会对事件进行抢占,因此,不管是文件事件的处理器,还是时间事件的处理器,它们都会尽可能减少程序的阻塞时间,并在有需要时主动让出执行权,从而降低造成事件饥饿的可能性。当回复能发送时,将产生AE_WRITABLE事件,触发命令回复处理器执行,当命令回复处理器将全部回复写入套接字后,将不再监听客户端套接字的AE_WRITABLE事件。正常情况下,服务器几乎是将无序链表退化成一个指针来使用,因此不会影响事件执行的性能。

tus00000的博客 899

基于STM32的录音机设计(STM32F103+VS1053B)

本项目设计并实现了一款基于STM32微控制器的便携式录音机。该录音机采用STM32F103C8T6作为主控芯片,结合VS1053B音频编解码模块、SD卡存储、OLED显示屏以及按键模块,提供了手动录音、自动录音和录音回放等多种功能。

1万+

多模态大模型:技术原理与实战 全球多模态大模型介绍

关键词:多模态大模型、深度学习、计算机视觉、自然语言处理、跨模态学习、迁移学习、人工智能随着人工智能技术的飞速发展,多模态大模型已经成为了当前AI领域最热门的研究方向之一。多模态大模型能够同时处理和理解多种类型的数据,如文本、图像、音频和视频等,这为AI系统在复杂场景下的应用提供了更加强大和灵活的能力。本文将深入探讨多模态大模型的技术原理,介绍其实战应用,并对全球主要的多模态大模型进行全面的介绍和比较。

AI天才研究院 4267

《Redis设计与实现》第十二章 事件

Redis服务器是一个事件驱动程序,服务器需要处理一下两类事件: 1、文件事件:Redis服务器通过套接字与客户端(或者其他redis服务器)进行连接,而文件事件就是服务器对套接字操作的一抽象。 2、时间事件:Redis服务器的一些操作(ServerCron)需要在给定时间点执行。 12.1 文件事件 Redis基于Reactor模式开发了自己的网络事件处理器file event handler...

Za七杂⑧ 261

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

从阻塞 IO 到 epoll:把 Linux 网络 IO 一次讲透

本文系统梳理了Linux网络IO的核心机制,从阻塞IO到epoll的实现原理。首先解析IO操作的本质分为等待数据就绪和数据拷贝两个阶段,重点分析了不同IO模型的区别。深入探讨了IO多路复用技术如何通过一个线程同时监控多个文件描述符,详细剖析select/poll的底层实现机制及其性能瓶颈。特别揭示了内核等待队列的工作方式,以及select/poll每次被唤醒后必须全量遍历所有fd的设计缺陷,为理解epoll的优化原理奠定基础。全文以清晰的逻辑主线串联起Linux网络IO的关键概念,帮助读者建立系统性的认知框

有趣的中国人的博客 645

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Linux高性能服务器编程 学习笔记 第十二章 高性能IO框架库Libevent

所有具有相同信号值的信号事件处理器通过ev.ev_signal.ev_signal_next成员串联成一个尾队列,我们称之为信号事件队列,ev.ev_signal.ev_ncalls成员指定信号事件发生时,Reactor需要执行多少次该事件对应的事件处理器中的回调函数,ev.ev_signal.ev_pncalls指针成员要么是NULL,要么指向ev.ev_signal.ev_ncalls。所有已经注册的事件处理器(包括IO事件处理器和信号事件处理器)通过该成员串联成一个尾队列,我们称之为注册事件队列。

tus00000的博客 405

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

【学习日记】【第五十二章 Linux非阻塞IO实验】【流程图】——正点原子I.MX6U嵌入式Linux驱动开发

本文主要是笔者根据《正点原子I.MX6U嵌入式Linux驱动开发》中 “第五十二章 Linux阻塞和非阻塞IO实验” 的程序绘制的流程图,该程序使用非阻塞IO实现了和五十一章实验同样的功能,并对函数流程进行了分析。

Witheart 的博客。 869

《Redis设计与实现》之第十二章:事件

Redis服务器是一个事件驱动程序,服务器需要处理两类事件: 文件事件: 文件事件就是服务器对套接字(socket)操作的抽象,服务器和客户端的通信会产生文件事件 时间事件: 时间事件就是服务器对定时操作(比如serverCron函数)的抽象,Redis服务器中的一些操作需要在给定的时间点执行 一,文件事件 文件事件处理程序是基于Reactor的网络通信程序,是对套接字操作的抽象,每...

weixin_34281537的博客 86

libevent网络编程汇总

libevent源码剖析: ========================================================== 1、libevent源码剖析一(序) 2、libevent源码剖析二(Reactor框架) 3、libevent源码剖析三(基础使用) 4、libevent源码剖析四(代码组织) 5、libevent源码剖析五(核心:event) 6、li...

weixin_30527323的博客 82

GPTM定时器:从核心原理到PWM生成的嵌入式实战指南

定时器是嵌入式系统的核心外设,其本质是一个可编程的数字计数器,将时间概念转化为微控制器可处理的计数值。其工作原理基于系统时钟驱动计数器,通过配置不同的工作模式(如单次、周期、PWM、边沿捕获)来实现多样化的时序控制。这项技术的核心价值在于以硬件方式实现高精度、低CPU占用的时间管理与信号生成,是构建高效、实时嵌入式系统的基石。其应用场景广泛,从基础的延时、系统节拍,到复杂的**PWM波形生成**、电机控制、**事件捕获**与频率测量,都离不开定时器的支持。本文以通用定时器模块(GPTM)为例,深入解析其设计

weixin_33874713的博客 431

JAVA面试题合集十二(Redis)

1.Redis常见面试题 2.什么是Redis? Redis是一个基于C语言编写的开源的高性能非关系型BoSql的键值对数据库 Redis可以存储键和5种不同类型的值之间的映射.键类型只能为字符串.值可以为字符串,集合,有序集合,列表,哈希(散列表) 与传统数据库不同的是,Redis存储在内存中,所以读写速率非常快,.应用于缓存,每秒10万次读写 是性能最快的Key-Value DB。另外,Redis 也经常用来做分布式锁。Redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。 3.R

qq_44773677的博客 272

【分布式系统与RPC框架系列】基于 C++17 + Protobuf + ZooKeeper + Reactor 的长连接多路复用RPC 框架设计与演进

客户端 服务端 业务代码 业务实现 ↓ ↑ Stub Service ↓ ↑ MprpcChannel RpcProvider ↓ ↑ 网络通信层 网络通信层 五、传统RPC的问题在哪里(短连接模型) 在最初的MPRPC实现中,客户端每次RPC调用都会: 创建新的TCP连接(socket + connect) 发送请求(send) 同步等待响应(recv) 关闭连接(close) 这种设计虽然简单直接,但存在明显问题: 性能问题:每次RPC都要经历TCP三次握手/四次挥手 资源浪费:TCP连接无法复用 阻塞

努力努力再努力wz的博客 736
上一篇: (十一)信号事件的管理
下一篇: (十三)时间管理
UKey_
博客等级 码龄10年 258粉丝 186原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值