(十一)信号事件的管理

QT 事件和信号  仔细来看,事件与信号其实并无多大差别,从我们对其需求上来说,都只要能注册事件或信号响应函数,在事件或信号产生时能够被通知到即可。但有一项区别在于,事件处理函数的返回值是有意义的,我们要根据这个返回值来确定是否还要继续事件的处理,比如在QT中,事件处理函数如果返回true,则这个事件处理已完成,QApplication会接着处理下一个事件,而如果返回false,那么事件分派函数会继续向上寻找下 阅读详情

前言

在上一小节中我们主要讲解了信号事件是如何合并到多路I/O复用机制中的以及信号事件的初始化。在本小节中,我们将看到有关信号事件的主要操作。

信号事件的注册

前面我们看到了信号事件是在何时何地如何被初始化的,一个事件无非就是初始化、注册、激活、回调、注销这几个重要的操作。接下来我们看看信号事件注册相关的,即evsignal_add函数,它在signal.c文件中定义。

int
evsignal_add(struct event *ev)
{
    int evsignal;
    struct event_base *base = ev->ev_base;
    struct evsignal_info *sig = &ev->ev_base->sig;
    //读/写事件不属于这儿
    if (ev->ev_events & (EV_READ|EV_WRITE))
        event_errx(1, "%s: EV_SIGNAL incompatible use", __func__);
    /*
     * 这里是个宏函数,在event.h中定义如下
     * #define EVENT_SIGNAL(ev)   (int)(ev)->ev_fd
     * 作用就是取得信号值
     */
    evsignal = EVENT_SIGNAL(ev);
    assert(evsignal >= 0 && evsignal < NSIG);
    //没有事件注册到该evsignal信号上
    if (TAILQ_EMPTY(&sig->evsigevents[evsignal])) {
        event_debug(("%s: %p: changing signal handler", __func__, ev));
        /* 如有必要,扩大给sh_old分配的内存
         * 给该信号设置新的信号捕捉函数
         */
        if (_evsignal_set_handler(
                base, evsignal, evsignal_handler) == -1)
            return (-1);

        /* catch signals if they happen quickly */
        evsignal_base = base;
        //该信号事件未注册过
        if (!sig->ev_signal_added) {
            //注册该事件
            if (event_add(&sig->ev_signal, NULL))
                return (-1);
            sig->ev_signal_added = 1;
        }
    }

    /* multiple events may listen to the same signal */
    //将信号事件添加到信号evsignal对应的事件链表中
    TAILQ_INSERT_TAIL(&sig->evsigevents[evsignal], ev, ev_signal_next);

    return (0);
}

该函数主要逻辑就是:

  • 判断信号有无对应的注册事件链表
    1. 无,判断是否需要重新分配内存,接着便注册该事件
    2. 有,直接将该事件添加到信号对应的事件链表中

这里初看的话可能你会觉得有点迷糊,因为有两个注册事件的操作,而且不一样。
- event_add注册的事件,是到时候信号事件被激活了,真正执行的操作。
- TAILQ_INSERT_TAIL这个执行的操作虽然也是将信号事件加入链表中,但是是不同的链表。它是收到信号之后,会执行的操作,可以看到_evsignal_set_handler设置的都是evsignal_handler捕捉函数,不管是哪个信号。等下我们会讲这个函数。

总的来说,evsignal_handler,主要是执行写socket这边写数据触发读socket事件,然后多路I/O机制就可以成功的知道信号发生了,从而将event_add注册的信号事件激活。
evsignal_handler代码如下:

static void
evsignal_handler(int sig)
{
    int save_errno = errno;

    if (evsignal_base == NULL) {
        event_warn(
            "%s: received signal %d, but have no base configured",
            __func__, sig);
        return;
    }

    evsignal_base->sig.evsigcaught[sig]++;
    evsignal_base->sig.evsignal_caught = 1;

#ifndef HAVE_SIGACTION
    signal(sig, evsignal_handler);
#endif

    /* Wake up our notification mechanism */
    send(evsignal_base->sig.ev_signal_pair[0], "a", 1, 0);
    errno = save_errno;
}

里面完成的就主要是注册信号捕捉函数以及给读socket发送数据。这样就可以理解前面那个可能导致你迷惑的知识了。

激活信号事件

我们最后再来看看是如何激活一个信号事件的:

void
evsignal_process(struct event_base *base)
{
    struct evsignal_info *sig = &base->sig;
    struct event *ev, *next_ev;
    sig_atomic_t ncalls;
    int i;

    base->sig.evsignal_caught = 0;
    /*
     * NSIG是个宏定义,代码支持的信号最大值
     * 遍历该信号的事件链表
     */
    for (i = 1; i < NSIG; ++i) {
        ncalls = sig->evsigcaught[i];
        //ncalls代表信号接收到的次数,为0则不需要进行激活了
        if (ncalls == 0)
            continue;
        sig->evsigcaught[i] -= ncalls;

        //处理该信号对应事件链表上的每个事件
        for (ev = TAILQ_FIRST(&sig->evsigevents[i]);
            ev != NULL; ev = next_ev) {
            next_ev = TAILQ_NEXT(ev, ev_signal_next);
            //如果不是永久事件,则激活了将其删除
            if (!(ev->ev_events & EV_PERSIST))
                event_del(ev);
            //进行激活操作
            event_active(ev, EV_SIGNAL, ncalls);
        }

    }
}

小结

关于信号事件管理部分,还有注销等操作,这些和注册大致相同,就不一一讲解了。主要是要理解socket pair以及它们各自对应的事件是怎样的。关于写socket这边,信号发生之后,会调用send函数给读socket发数据从而触发读事件,导致该事件被激活,最后被调度。
接下来,我们会取看一看关于定时事件方面的管理。

在freertos中,事件组的用途,相比与信号量有什么优势,事件组适合应用于什么场合,而这种场合却是信号量无法实现的 任务可以等待多个事件的组合(如“事件 A 和事件 B”或“事件 A 或事件 B”),而信号量无法实现这种功能。事件组可以表示系统的复杂状态(如多个任务的完成状态),而信号量只能表示简单的资源可用性或事件发生。任务可以同时等待多个事件的组合(如“事件 A 和事件 B”或“事件 A 或事件 B”)。任务需要等待多个事件的发生(如“事件 A 和事件 B”或“事件 A 或事件 B”)。任务需要等待多个事件的组合(如“事件 A 和事件 B”或“事件 A 或事件 B”)。一个任务需要通知多个任务某个事件的发生。 阅读详情

相关推荐

libevent中的信号管理

一、前言 Libevent(1.4.13 版本)的源码中,event_base 结构体中的成员 sig 用于管理信号事件,sig 的变量类型为 struct evsignal_info。 二、相关结构体 struct evsignal_info 定义在 evsignal.h 头文件中,如下: typedef void (*ev_sighandler_t)(int); struct evsigna...

zhwenx3的博客 508

Swoole 源码分析——Server模块之Signal信号处理

前言 信号处理是网络库不可或缺的一部分,不论是 ALARM、SIGTERM、SIGUSR1、SIGUSR2、SIGPIPE 等信号对程序的控制,还是 reactor、read、write 等操作被信号中断的处理,都关系着整个框架程序的正常运行。 Signal 数据结构 Signal 模块的数据结构很简单,就是一个 swSignal 类型...

weixin_34342905的博客 1122

PyQt5事件和信号

一、事件 所有的应用都是事件驱动的。事件大部分都是由用户的行为产生的,当 然也有其他的事件产生方式,比如网络的连接,窗口管理器或者定时器 等。调用应用的exec_()方法时,应用会进入主循环,主循环会监听和分发事件 在事件模型中,有三个角色: 事件源 事件 事件目标 事件源就是发生了状态改变的对象,事件是这个对象状态的改变撞他改变的内容,事件目标是事件想作用的目标,事件源绑定事件处理函数, 然后作用于事件目标身上 PyQt5处理事件方面有个signal and slot机制。Signals and sl

markshui的博客 635

翻译:libevent参考手册第四章:与事件一起工作

翻译:libevent参考手册第四章:与事件一起工作  (2011-04-10 20:40:27) 转载 标签:  libevent   非阻塞io   公用超时   激活   网络编程   未决   信号事件   it 分类: Libevent 译自http://www

CrazyCode_Lee的专栏 1586

Gtk事件与信号关系

Gtk事件与信号关系--分析中相关的源码包 gtk+2.0-2.12.9      Gtk所提供的工具库与Gtk应用程序与都是基于事件触发机制来管理。所有的Gtk应用程序都是基于事件驱动,如果没有事件发生,应用程序将处于等待状态,不会执行任何操作,一旦事件发生,将根据不同的事件做出相应的处理。在GTK+中,一个事件就是从X Server传出来的一个信息。当一个事件发生时,Gtk程序就会通过发送一个

Just Programming Myself (c_spark) 6842

Godot引擎开发:VR信号与事件系统_(7).自定义VR事件与信号

在Godot引擎中,VR信号与事件系统是实现虚拟现实交互的重要组成部分。通过自定义VR事件和信号,开发者可以更灵活地处理用户在虚拟环境中的操作,从而提升游戏的沉浸感和交互体验。本节将详细介绍如何在Godot引擎中自定义VR事件与信号,包括信号的创建、发送和接收,以及如何在VR场景中应用这些自定义事件。在Godot引擎中,创建自定义信号非常简单。您可以在任何脚本中定义信号,并在需要时发送这些信号。以下是一个简单的例子,展示如何在Godot脚本中定义和发送自定义信号。首先,您需要在脚本中定义一个自定义信号。

chenlz2007的博客 948

[libevent]evsignal_add()

int evsignal_add(struct event *ev) { int evsignal; struct event_base *base = ev->ev_base; struct evsignal_info *sig = &ev->ev_base->sig; if (ev->ev_events & (EV_READ|EV_WRITE)) event_errx(1, "%

scnuxiaotao的博客 904

Godot引擎开发:信号与事件系统_信号与事件系统的性能优化

在某些情况下,Godot引擎提供的信号机制可能不完全满足性能要求。通过自定义信号处理机制,可以进一步优化性能。自定义信号处理机制可以更精细地控制信号的传递和处理,但需要更多的开发工作和维护成本。自定义优化适用于特定的高性能需求场景。# 自定义信号传递脚本# 初始化信号队列pass# 玩家脚本通过以上各种优化策略,我们可以在Godot引擎中有效地提高信号与事件系统的性能。减少不必要的信号连接:按需连接和断开信号,避免过多的内存开销和性能负担。避免信号的过度传递。

chenlz2007的博客 926

量化分析入门10:backtrader的策略入门2(策略示例)

#量化分析入门10:backtrader的策略入门2(策略示例) #作者:冯德平(山野雪人) #这里是一个简单的移动平均线交叉的片段(以股票万科为例)。 from datetime import datetime import backtrader as bt class SmaCross(bt.SignalStrategy): def init(self): sma1, sma2 = bt.ind.SMA(period=10), bt.ind.SMA(period=30) crossover = bt.i

weixin_42238077的博客 491

signal_add_noise_NOISE_高斯噪声_瑞利衰落信号_matlab_addnoise_

产生一定频率的正弦信号,并利用matlab函数加瑞利噪声和高斯噪声,模拟传输信道的衰落,最后画图对比加噪前后的信号。

Aspice的理解

ASPICE 是由汽车行业的主要公司和组织合作开发的,包括德国汽车工业联合会(VDA)和国际汽车工作组(Automotive SIG)。其目标是通过标准化的软件开发流程,提高汽车电子系统的软件质量和可靠性。

hkj8808的博客 2015

PyQt的布局管理、事件与信号

PyQt的布局管理、事件与信号一、布局管理1、绝对布局2、盒布局3、栅格布局4、特殊的布局----QSplitter二、事件与信号1、常规事件2、键盘事件3、鼠标跟随 一、布局管理   在一个GUI程序里,布局是一个很重要的方面。布局就是如何管理应用中的元素和窗口。有两种方式可以搞定:绝对定位和PyQt5的layout类 1、绝对布局 import sys from PyQt5.QtWidgets import QApplication,QLabel,QWidget class Example(QWidg

Itsme_MrJJ的博客 1036

平衡电桥检测高压绝缘电阻的原理

检测绝缘漏电的高压拓扑如下:BMU需要连接BAT+,BAT-和PE线,并测量电池总压(Ubatt)和负母线电压(Un),并计算出正母线电压(Up)。

booksyhay的专栏 1万+

activiti之信号触发事件

信号----广播----对应所有定义信号事件的执行流 消息---打电话--对应当前用户的执行流 import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; import org.activiti.engine.RepositoryService; import org...

kaige8312的博客 1317

Isaac Sim 车辆动力学:从参数调优到户外仿真的挑战与实战

本文深入探讨了Isaac Sim在车辆动力学仿真中的应用,从参数调优到户外场景模拟的实战经验。详细解析了悬架系统、轮胎物理模型等核心参数的设置技巧,并分享了应对户外仿真挑战的实用方案。通过Vehicle Wizard高级使用和传感器配置,帮助开发者高效完成车辆仿真与算法开发。

weixin_29192211的博客 404

MobaXterm破解14个会话限制的保姆级教程(附Python环境配置指南)

本文提供了MobaXterm破解14个会话限制的详细教程,并深入讲解了如何配置稳定的Python环境以支持相关脚本运行。通过理解软件授权机制、安全实践步骤以及许可文件的应用,帮助用户解除会话数量限制,实现高效的远程服务器管理与自动化运维。

weixin_29211309的博客 1645

pyqt5教程6:信号和事件

PyQt5的事件:GUI 应用程序是事件驱动的。事件主要由应用程序的用户生成。但它们也可以通过其他方式生成;例如Internet 连接、窗口管理器或计时器。当我们调用应用程序的 exec_ 方法时,应用程序进入主循环。主循环获取事件并将它们发送给对象。事件本身是一个对象体,从其源发起,最后到达目的地。

gongdiwudu的专栏 6677

YOLO11-pose关键点检测:训练实战篇 | 自己数据集从labelme标注到生成yolo格式的关键点数据以及训练教程

通过本教程,我们完整地学习了如何使用YOLO11-pose进行关键点检测任务的训练。从数据标注、格式转换到模型训练和评估,每个步骤都提供了详细的代码和说明。更高的精度:随着算法改进,关键点检测的精度将进一步提高实时性能:模型优化将使实时高性能关键点检测成为可能多模态融合:结合深度信息、热成像等多模态数据提升检测能力领域自适应:模型能够更好地适应不同场景和领域希望本教程能够帮助你在自己的项目中成功应用YOLO11-pose进行关键点检测。如果你有任何问题或建议,欢迎在评论区留言讨论!

QQ_778132974的博客 739

Qt事件及信号

Qt事件及信号 概述 文章目录Qt事件及信号前言一、事件学习?事件、信号和线程相关性重写 QCoreApplication::notify总结 前言 首先要明白的是:“在 Qt 里,一个事件就是一个对象,所有事件的祖先都来自于 QEvent”。意思就是说,只要有一个事件发生(如鼠标单击事件),此时就会有一个 QEvent 对象被创建出来,然后开始各种传送。由于 Qt 事件系统是依托于元对象系统的,所以所有的 QObject 类都可以接收/处理 QEvent 事件。 说起事件,其实无非就是围绕着“产生-

weixin_43763292的博客 1231

二、TCP/IP协议之网络层(IP地址的格式、分类、报文格式)

数据报每经过一个路由器,路由器都要重新计算一下首部检验和,若首部未发生变化,则此结果必为 0,于是就保留这个数据报。对于网络号相的设备,无论实际所处的物理位置如何,它们都是处在同一个网络中。在首部的固定部分的后面是一些可选字段,其长度是可变的。IPv4 软件在存储器中维持一个计数器,每产生一个数据报,计数器就加 1,并将此值赋给标识字段。表示数据报在网络中的寿命,英文缩写是 TTL(Time To Live),功能是“跳数限制”。地址的网络号码字段用来标识一个网络,网络号码字段的前几位用来区分。

锦慈的技术博客 185

2️⃣ Coze创建智能体教学(2025年全新版本)

扣子平台提供强大支持,可将智能体轻松集成至各类社交平台,使智能体得以服务更为庞大的用户群体。当下支持集成的平台如下:​1️⃣豆包:作为聚焦 AI 内容创作的平台,非常适合发布充满创意、娱乐性强的智能体。​2️⃣飞书:适合发布用于办公协作的智能体,助力团队提升工作效率。​3️⃣微信:借助公众号或小程序的形式,能够服务海量微信用户。​4️⃣抖音:适合发布与短视频相关的智能体,为用户提供创意与娱乐服务。​

李同学Lino的博客 4576

PyQt5 布局管理、事件、信号以及对话框

PyQt5常用功能一

weixin_47988426的博客 1340

Python 爬虫实战:医学临床指南爬取(含 PDF 解析与结构化存储)

在当今数字化时代,医学临床指南作为医生进行科学诊疗的重要参考资料,包含大量经过临床验证的诊疗路径和建议。这些指南通常发布在权威医学网站上,数量庞大且更新频繁。如何自动化地抓取并存储这些指南,成为医疗数据分析、医学研究以及医疗 AI 模型训练等工作的关键第一步。本文将系统讲解如何利用 Python 爬虫技术从权威医学网站爬取临床指南内容,并实现 PDF 解析与结构化存储。

u014481728的博客 449

【PyQt5】5.事件和信号

所有的应用都是事件驱动的。事件大部分都是由用户的行为产生的,当然也有其他的事件产生方式,比如网络的连接,窗口管理器或者定时器等。调用应用的exec()方法时,应用会进入主循环,主循环会监听和分发事件。事件源就是发生了状态改变的对象。事件是这个对象状态改变的内容。事件目标是事件想作用的目标。事件源绑定事件处理函数,然后作用于事件目标身上。PyQt5处理事件方面有信号与槽(signal and slot)机制。信号与槽用于对象间的通讯。

qq_50798554的博客 877

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

libevent学习笔记七——集成信号事件到事件主循环

概述 在linux系统中有现成的信号捕获接口如sigaction,它可以捕获指定的信号并执行用户自定义信号处理函数,那么如何将这种机制集成到libevent事件管理模型中呢? libevent采用了socketpair的方式将信号事件集成到了其自身的事件处理模型中。 具体做法如下简述: 初始化socketpair; 调用接口sigaction设置指定信号的信号处理函数,该信号处理函数所做工作为向...

NMG_CJS的博客 454

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Qt信号槽机制和事件机制的理解

唯一不同的是:槽还可以和信号连接在一起,在这种情况下,每当发射这个信号的时候,就会自动调用这个槽。内省功能对于实现信号和槽是必需的,并且允许应用程序的开发人员在运行时获得有关QObject 子类的“元信息”(meta-information),包括一个含有对象的类名以及它所支持的信号和槽的列表。(3) 信号与槽在多线程时支持异步调用在单线程应用时,你可以把信号与槽看成是一种对象间的同步通信机制,这是因为在这种情况下,信号的释放过程是阻塞的,一定要等到槽函数返回后这个过程才结束,也就是不支持异步调用。

mj348940862的博客 1886

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

上一篇: (十)信号事件集成到多路I/O机制
下一篇: (十二)定时事件集成到多路IO机制
UKey_
博客等级 码龄10年 258粉丝 186原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值