libuv事件循环中的三种句柄
1、说明
本文会简单介绍 libuv 的事件循环,旨在入门级别的使用,而不做深入探究,简单来说就是,会大概用就行,先用熟练了,再去探究原理和源码
下图为官网的 libuv 的不同部分及其涉及的子系统的图:

libuv 使用 handles 和 requests 来结合使用事件循环
handles 表示能够执行某些耗时的长时间存在的对象
requests 表示短暂的操作,可以在一个 handles 上执行
下图为官网的事件循环:

这张图其实表明了 libuv 中的时间循环的处理过程,也就是 uv_run() 方法执行的过程,该方法内部是一个 while 循环:
- 先判断循环是都处于活动状态,通过判断当前是否处于 alive 状态,来确定事件循环是否退出;
- 运行倒计时定时器(维护所有句柄的定时器);
- 执行待执行的回调函数;
- 运行 idle 句柄;
- 运行 prepare 句柄;
- 轮询 I/O;
- 运行 check 句柄;
- 调用 close 回调;
上述步骤中,有三个句柄被重点标出,我们就来讨论这三个句柄
2、idle句柄
idle handle 即空闲句柄,从上面流程图上可以看出,如果启动了 idle handle,每次事件循环的时候都会执行一遍其回调
2.1、uv_idle_init
该方法用于初始化 idle handle
int uv_idle_init(uv_loop_t* loop, uv_idle_t* idle)
uv_idle_t 是 idle 句柄类型
该方法永远执行成功,返回值0
2.2、uv_idle_start
该方法用于开始 idle handle
int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb)
该方法用于都是执行成功的(返回值0),除非回调函数设置为 NULL(此时返回 UV_EINVAL)
回调函数声明如下:
void (*uv_idle_cb)(uv_idle_t* handle);
回调函数会把句柄带过去
2.3、uv_idle_stop
该方法用于停止 idle handle
int uv_idle_stop(uv_idle_t* idle)
该方法永远执行成功,返回值0
执行之后,回调不会再执行
3、prepare句柄
可以理解成准备句柄,从流程图中可以看出,在 idle 之后,在轮询 IO 之前执行其回调
其API和 idle 差不多
3.1、uv_prepare_init
int uv_prepare_init(uv_loop_t* loop, uv_prepare_t* prepare);
初始化句柄,uv_prepare_t 为 prepare 句柄类型
返回值0,总是成功的
3.2、uv_prepare_start
int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb);
开始句柄,执行总是成功的(返回0),除非回调函数为 NULL(此时返回 UV_EINVAL )
void (*uv_prepare_cb)(uv_prepare_t* handle);
3.3、uv_prepare_stop
int uv_prepare_stop(uv_prepare_t* prepare);
停止句柄,回调函数不会再执行
4、check句柄
可以理解为检查句柄,如果程序中启动了 check 句柄,则在每次轮询 IO 之后执行其回调函数,正好和 prepare 前后呼应
这种设计的机制是 libuv 为用户预留的借口,在轮询 IO 循环状态前后进行准备和校验操作
其 API 和上面两种句柄类似
4.1、uv_check_init
int uv_check_init(uv_loop_t* loop, uv_check_t* check);
初始化句柄,uv_check_t 为 check 句柄类型
方法执行总是成功的
4.2、uv_check_start
int uv_check_start(uv_check_t* check, uv_check_cb cb);
开始句柄,回调函数可以为 NULL
方法执行总是成功的(返回0),除非回调函数为 NULL(返回UV_EINVAL )
void (*uv_check_cb)(uv_check_t* handle);
4.3、uv_check_stop
int uv_check_stop(uv_check_t* check);
停止句柄,回调函数不会再执行
方法执行总是成功的,返回0
5、代码示例
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>
#define MAX_NUM 3
int count = 0;
void idle_cb(uv_idle_t *handle)
{
count++;
printf("idle handle callback, count = %d\n", count);
if (count >= MAX_NUM)
{
printf("idle handle stop, count = %d\n", count);
uv_stop(uv_default_loop());
}
}
void prepare_cb(uv_prepare_t *handle)
{
printf("prepare handle callback\n");
}
void check_cb(uv_check_t *check)
{
printf("check handle callback\n");
}
int main()
{
uv_idle_t idle;
uv_prepare_t prepare;
uv_check_t check;
uv_idle_init(uv_default_loop(), &idle);
uv_idle_start(&idle, idle_cb);
uv_prepare_init(uv_default_loop(), &prepare);
uv_prepare_start(&prepare, prepare_cb);
uv_check_init(uv_default_loop(), &check);
uv_check_start(&check, check_cb);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
return 0;
}
输出结果如下:
idle handle callback, count = 1
prepare handle callback
check handle callback
idle handle callback, count = 2
prepare handle callback
check handle callback
idle handle callback, count = 3
idle handle stop, count = 3
prepare handle callback
check handle callback
上例子中没有 IO 相关的代码,主要用于熟悉三种句柄回调函数的执行顺序
libuv事件循环中的三种句柄的更多相关文章
- libuv事件循环
目录 1.说明 2.数据类型 2.1.uv_loop_t 2.2.uv_walk_cb 3.API 3.1.uv_loop_init 3.2.uv_loop_configure 3.3.uv_loop ...
- Java三大框架之——Hibernate中的三种数据持久状态和缓存机制
Hibernate中的三种状态 瞬时状态:刚创建的对象还没有被Session持久化.缓存中不存在这个对象的数据并且数据库中没有这个对象对应的数据为瞬时状态这个时候是没有OID. 持久状态:对象经过 ...
- iOS容易造成循环引用的三种场景
iOS容易造成循环引用的三种场景 ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是--循环引用.循环引用可以简单理解为 ...
- Asp.Net中的三种分页方式
Asp.Net中的三种分页方式 通常分页有3种方法,分别是asp.net自带的数据显示空间如GridView等自带的分页,第三方分页控件如aspnetpager,存储过程分页等. 第一种:使用Grid ...
- 研究分析JS中的三种逻辑语句
JS中的三种逻辑语句:顺序.分支和循环语句. 一.顺序语句 代码规范如下:1. <script type="text/javascript"> var a = 10; ...
- Netty中的三种Reactor(反应堆)
目录: Reactor(反应堆)和Proactor(前摄器) <I/O模型之三:两种高性能 I/O 设计模式 Reactor 和 Proactor> <[转]第8章 前摄器(Proa ...
- js oop中的三种继承方法
JS OOP 中的三种继承方法: 很多读者关于js opp的继承比较模糊,本文总结了oop中的三种继承方法,以助于读者进行区分. <继承使用一个子类继承另一个父类,子类可以自动拥有父类的属性和方 ...
- SQL Server中的三种Join方式
1.测试数据准备 参考:Sql Server中的表访问方式Table Scan, Index Scan, Index Seek 这篇博客中的实验数据准备.这两篇博客使用了相同的实验数据. 2.SQ ...
- 【转载】C#批量插入数据到Sqlserver中的三种方式
引用:https://m.jb51.net/show/99543 这篇文章主要为大家详细介绍了C#批量插入数据到Sqlserver中的三种方式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 本篇, ...
随机推荐
- flowable的多人会签和一票否决
项目结构: 接下来代码: Duorenhuiqian.bpmn20.xml: <?xml version="1.0" encoding="UTF-8"?& ...
- day114:MoFang:基于支付宝沙箱测试环境完成创建充值订单接口&服务端处理支付结果的同步通知和异步通知
目录 1.基于支付宝提供的沙箱测试环境开发支付接口 1.后端提供创建充值订单接口 2.前端调用AlipayPlus发起支付 3.注意:自定义APPLoader完成接下来的开发 4.下载支付宝沙箱钱包A ...
- MongoDB插入数据,除去Class key
本文来源于: 来源:CSDN 原文:https://blog.csdn.net/ClementAD/article/details/50849680 去除class字段的本质为设置 DefaultMo ...
- Access-Control-Allow-Headers等基础常识
跨源资源共享 (CORS) (或通俗地译为跨域资源共享)是一种机制,该机制使用附加的 HTTP 头来告诉浏览器,准许运行在一个源上的Web应用访问位于另一不同源选定的资源. 当一个Web应用发起一个与 ...
- Eclipse导入外部jar包的步骤
(1)首先在项目的跟目录下先建一个名字为lib的文件夹,通常外部导入的jar包都放在这个文件夹下面. (2)将需要用到的jar包复制到lib文件夹下面. (3)在项目中导入jar包 右键项目,选择Bu ...
- [从源码学设计]蚂蚁金服SOFARegistry之服务上线
[从源码学设计]蚂蚁金服SOFARegistry之服务上线 目录 [从源码学设计]蚂蚁金服SOFARegistry之服务上线 0x00 摘要 0x01 业务领域 1.1 应用场景 1.1.1 服务发布 ...
- Centos 7 杂章
CentOS-7-x86_64-DVD-2003.iso 下载地址: http://mirrors.aliyun.com/centos/7/isos/x86_64/CentOS-7-x86_64-DV ...
- Java进阶专题(二十一) 消息中间件架构体系(3)-- Kafka研究
前言 Kafka 是一款分布式消息发布和订阅系统,具有高性能.高吞吐量的特点而被广泛应用与大数据传输场景.它是由 LinkedIn 公司开发,使用 Scala 语言编写,之后成为 Apache 基金会 ...
- 翻译 - ASP.NET Core 托管和部署 - 在 Linux 上使用 Nginx 托管 ASP.NET Core 网站
翻译自 https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-5.0 本文介 ...
- 奇技淫巧,还是正统功夫? - Python推导式最全用法
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取 python免费学习资 ...