网络编程:信号、定时器、Libevent

1. 信号

(1)信号:由用户、系统或进程发送给目标进程的信息,以通知目标进程某个状态的改变或系统异常;

可由下述条件产生:

  • 对前台进程,用户可以通过终端给它发送信号,如输入 Ctrl+C
  • 系统异常,如浮点异常等
  • 系统状态变化,如定时器到期
  • 运行 kill 命令或调用 kill 函数

1.1 信号概述

1.1.1 发送信号

一个进程给其他进程发送信号

#include <sys/types.h>
#include <signal.h>
// 成功返回 0,失败返回 -1 并设置 errno
int kill( pid_t pid, int sig );

目标进程由 pid 指定

pid取值含义
pid > 0信号发送给 PID 为 pid 的进程
pid = 0信号发送给本进程组内的其他进程
pid = -1发给除 init 进程外的所有进程,发送者需要拥有对目标进程发送信号的权限
pid < -1发给 PGID 为 -pid 的进程组的所有成员

信号值 sig 为 0,不发送任何信号(检测目标进程或进程组是否存在,这种检测方式不可靠);

errno 为 EINVAL 表示无效的信号;EPERM 该进程没有权限给目标进程发送信号;ESRCH 目标进程或进程组不存在;

1.1.2 信号处理函数
#include <signal.h>
typedef void (*__sighandler_t) ( int );

参数用来指示信号的类型,必须保证是可重入的;

#include <bits/signum.h>
#define SIG_DFL ((__sighandler_t) 0)
#define SIG_IGN ((__sighandler_t) 1)

SIG_IGN 表示忽略目标信号,SIG_DFL 表示使用信号默认处理方式,例如结束进程(Term)、忽略信号(Ign)、结束进程并生成核心转储文件(Corn)、暂停进程(Stop)、继续进程(Cont);

1.1.3 Linux 信号
信号默认行为含义
SIGHUPTerm控制终端挂起
SIGPIPETerm往读端被关闭的管道或 socket 连接中写数据
SIGURGIgnsocket 连接上接收到紧急数据
SIGALRMTerm由 alarm 或 setitimer 设置的实时闹钟超时引起
SIGCHLDIgn子进程状态发送变化(退出或暂停)
1.1.4 中断系统调用

处于阻塞状态的系统调用接收到信号,并且为该信号设置了信号处理函数,默认情况下系统调用将被中断,其返回的 errno 为 EINTR;

可以使用 sigaction 为信号设置 SA_RESTART 标志以重新启动被该信号中断的系统调用;

Linux 独有:对默认行为是 Stop 的信号,没有设置信号处理函数,也可以中断某些系统调用(如 connectepoll_wait

1.2 信号函数

1.2.1 signal系统调用

为信号设置处理函数;

#include <signal.h>
_sighandler_t signal ( int sig, _sighandler_t _handler );

成功时返回一个函数指针,指向前一次该信号处理函数的函数指针(可能是默认处理函数指针 SIG_DEF 也可能是上一次调用 signal 函数传入的函数指针)

出错时返回 SIG_ERR,设置 errno;

1.2.2 sigaction 系统调用

更健壮的设置信号处理函数

// 成功时返回 0,失败返回 -1 设置 errno
int sigaction ( int sig, const struct sigaction* act, struct sigaction* oact );

act 指定新的信号处理方式,oact 输出先前的处理方式;

1.3 信号集

sigset_t 是一个长整型数组,每一位代表一个信号,共 1024 位;

1.4 网络编程相关信号

1.4.1 SIGHUP
1.4.2 SIGHUP
1.4.3 SIGURG

(1)select异常事件检测带外数据
(2)SIGURG 信号;

2. 定时器

alarm 系统调用一次只会引起一次 SIGALRM 信号;

2.1 socket 选项 SO_RCVTIMEO 和 SO_SNDTIMEO

分别用来设置 socket 接收数据 / 发送数据超时时间,数据类型为 timeval(和 select 超时参数相同);
在这里插入图片描述

2.2 SIGALRM 信号

2.2.1 基于升序链表的定时器

定时器通常包含至少两个成员:超时时间和任务回调函数;

按照超时时间做升序排序链表;

2.2.2 处理非活动连接

管理所有长时间处于非活动状态的连接

通过alarm每隔一段时间,发送 SIGALRM 信号;
有新的连接到来时,会在 connfd 上设置定时器; 每当 connfd 上有数据可读时,会重置其定时器;
超时处理函数中会检测在升序链表中是否有定时器超时,若有,则删除其 fd 上的注册事件并关闭 fd;

2.3 IO 复用系统调用的超时参数

IO 复用系统调用都可以设置超时参数,但可能会被就绪事件触发提前返回,因此需要不断更新定时参数以反馈剩余时间;

在系统调用执行前后记录当前时间,从而获得执行该系统调用的时间;

2.4 高性能定时器

2.4.1 时间轮

循环队列 + 哈希思想(类似手表),将循环队列划分为 N 个槽,槽之间的时间间隔为 SI;

插入定时器时,插入到每个 Slot 头部;

每过 SI 时间,调用 tick(),判断当前 Slot 是否有到期的定时器,并向前走一个 Slot;

2.4.2 时间堆

用最小堆实现

将堆顶定时器的超时值作为定时间隔,一旦 tick 被调用,堆顶定时器必然到期,再从剩余的定时器中找到超时时间最小的一个,并将这段时间间隔作为下一次的定时间隔;

3. 高性能 IO 框架库

3.1 概述

在这里插入图片描述

(1)句柄与事件绑定,内核通过句柄向应用程序通知事件就绪;

在 Linux 下,IO事件对应的句柄就是文件描述符,信号事件对应的句柄就是信号值;定时器事件对应固定值;

(2)事件多路分发器;统一各系统的 IO 复用系统调用;

(3)事件处理器;实现业务逻辑;与句柄绑定;

(4)Reactor;

  • handle_events;执行事件循环,重复过程:等待事件,依次调用就绪事件对应的事件处理器;
  • register_handler;往事件多路分发器中注册事件;
  • remove_handler;删除事件多路分发器中的事件;

3.2 libevent 源码分析

event 是一个事件处理器;

(1)event_base :相当于一个 Reactor 实例;

base->evsel 表示选择的 IO 复用机制,即 selectepoll等;

(2)event_new :创建事件处理器;参数为关联的 base、事件对应句柄、事件类型、具体处理函数;称为 initialized;

(3)event_add :内部调用 event_queue_insert,将事件处理器加入到各种事件队列中,根据 ev->ev_flags 进行区分;称为 pending;

(4)event_base_dispatch / event_base_loop:执行事件循环,遍历 event_base 上注册的事件直到有事件就绪,将就绪事件加入 active 事件队列中(按优先级划分的相应队列),调用相应的事件处理器;

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

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

相关文章

c++ qt 模态框和阻拦器 优先级 问题 修复 已解决

在c项目中。有 加载动画 和 模态框提醒的功能, 导致发生一个问题&#xff0c;有提示框的时候&#xff0c;动画也停止&#xff0c;必须点击 按钮 所有代码才能有效。 解决办法 谨慎使用 deleteLater,因为和模态框拦截有冲突, 使用 隐藏 或者 删除指针。 deleteLater 使用逻辑是 …

融资项目——vue之双向数据绑定

上一篇文章中使用的v-bind是单向绑定方法&#xff0c;即数据改变&#xff0c;网页相应的视图发生改变&#xff0c;但是网页视图发生改变其相关联的数据不会发生改变。但是双向数据绑定不同之处在于网页视图发生改变其相关联的数据也会发生改变。Vue可以使用v-model进行双向数据…

振动试验的工装夹具(GB/T 2423.43-2008)

但当试件体积较大&#xff0c;而且形状复杂时&#xff0c;这种固定方法显然很困难&#xff0c;这时需要制作夹具&#xff0c;让试件安装在夹具上然后把夹具牢固地固定在振动台面上&#xff0c;因此实际上夹具是试件与振动台面连接的过渡体&#xff0c;其功能是将振动台的振动和…

实在智能成功完成近2亿元C轮融资,全面迎接2024年Agent智能体应用元年

在这个最冷的季节&#xff0c;杭州实在智能科技有限公司&#xff08;以下简称“实在智能”&#xff09;依然表现火爆&#xff0c;近日&#xff0c;实在智能成功完成C轮融资近2亿元人民币&#xff0c;由金泰富资本和安吉智慧谷共同领投、安吉两山国创跟投。 在此轮融资以前&…

数据结构 | 北京大学期末试卷查漏补缺

目录 顺序存储 优点 缺点 适用于&#xff1a; 链式存储 优点 缺点 适用于&#xff1a; 折半查找为什么要使用顺序存储结构 树的存储结构​编辑 对于一个数据结构&#xff0c;一般包括 DFS&BFS 什么是递归程序 C语言不带头结点的单链表逆置 检测字符…

DMA实验3-外设到内存搬运

实验要求 使用 DMA 的方式将串口接收缓存寄存器的值搬运到内存中&#xff0c;同时闪烁 LED1 。 CubeMX 配置 DMA 配置&#xff1a; 串口中断配置 代码实现 如何判断串口接收是否完成&#xff1f;如何知道串口收到数据的长度&#xff1f; 使用串口空闲中断&#xff08;IDL…

python:删除空白

删除字符串末尾的空白 例如&#xff0c;下面的代码&#xff0c;变量hobby指向的字符串在末尾有一个空格&#xff1a; 可以使用函数rstrip()删除字符串末尾的空格&#xff0c;如下&#xff1a; 因为删除字符串末尾的空格并没有赋值给原变量hobby&#xff0c;所以此时查看hobb…

排障启示录-无线终端信号弱

现象&#xff1a;无线终端显示信号弱 信息收集&#xff1a; AP的实际发射功率低。外置天线型AP&#xff0c;天线松动或者没插天线现场环境问题&#xff0c;信号穿透衰减终端接入远端AP终端个体问题 排查步骤&#xff1a; 1、AP的发射功率低 查看AP的射频功率&#xff0c;判…

KnowLM知识抽取大模型

文章目录 KnowLM项目介绍KnowLM项目的动机ChatGPT存在的问题 基于LLama的知识抽取的智析大模型数据集构建及训练过程预训练数据集构建预训练训练过程指令微调数据集构建 指令微调训练过程开源的数据集及模型局限性信息抽取Prompt 部署环境配置模型下载预训练模型使用LoRA模型使…

解释Keil-MDK中Code、RO-data、RW-data、ZI-data

一、概念 Code&#xff1a;即代码域&#xff0c;它通常是指编译器生成的机器指令&#xff0c;这些内容会被存储到ROM区。 RO-data&#xff1a;Read Only data&#xff0c;即只读数据域&#xff0c;它指程序中用到的只读数据&#xff0c;这些数据被存储在ROM区&#xff0c;因而…

制作系统盘

老毛桃&#xff08;LaoMaoTao&#xff09; 制作启动盘 第一步.进入官方网站下载我们的老毛桃 下载老毛桃U盘制作工具后&#xff0c;双击打开老毛桃的运行程序。 打开老毛桃U盘制作工具&#xff0c;插入需要制作的U盘&#xff08;如图所示U盘winpe系统制作界面&#xff09;。…

两种经典的现货白银假突破类型

假突破是现货白银市场中一种具有反大众性的市场行为。它通常和一种强势的市场行为突破联系在一起&#xff0c;但是它的方向是和突破完全相反的&#xff0c;识别假突破的类型&#xff0c;有助于降低我们亏损的风险&#xff0c;那如何识别呢&#xff1f;下面我们来介绍两种假突破…