1、说明

事件循环是 libuv 的核心功能,负责 IO 的轮询和事件回调的调度。

2、数据类型

2.1、uv_loop_t

事件循环数据类型,结构体

uv_loop_t.data 用于传递用户数据,libuv 不会触碰

2.2、uv_walk_cb

传递给 uv_walk() 方法的回调函数类型

void (*uv_walk_cb)(uv_handle_t* handle, void* arg);

3、API

3.1、uv_loop_init

int uv_loop_init(uv_loop_t* loop);

初始化 uv_loop_t 结构体

要注意,调用之前需要先给 uv_loop_t 分配内存资源,否则会崩溃

3.2、uv_loop_configure

int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...);

设置事件循环配置,一般应该在第一次调用 uv_run() 之前执行

返回值: 0表示成功,错误则返回一个 UV_E 错误码,UV_ENOSYS 表示平台不支持该事件循环配置

支持选项:

  • UV_LOOP_BLOCK_SIGNAL :轮询新事件时阻塞指定事件,uv_loop_configure 的第二个参数是信号编号;
  • UV_METRICS_IDLE_TIME :在事件的提供者的事件循环中收集空闲时间,使用 uv_metrics_idle_time() 方法需要使用这个选项

3.3、uv_loop_close

int uv_loop_close(uv_loop_t* loop);

释放所有内部循环资源

仅当所有循环完成并且所有打开的句柄和请求都已经关闭的时候才可调用此函数,否则将返回 UV_EBUSY

此函数返回后,用户可以释放为循环申请的内存

3.4、uv_default_loop

uv_loop_t* uv_default_loop(void);

返回 libuv 的默认事件循环,如果分配失败了,可能返回NULL

这个方法是在整个应用程序中进行全局循环的一个便捷的方式,和自定义的事件循环相同

3.5、uv_run

int uv_run(uv_loop_t* loop, uv_run_mode mode);

运行事件循环,mode 指定运行模式,有如下几种:

  • UV_RUN_DEFAULT :运行事件循环,知道没有活动的和被引用的句柄和请求。如果使用 uv_stop() 方法终止还未停止的循环(仍然有活动的和被引用的句柄和请求),则返回值非0,其他情况下返回0;
  • UV_RUN_ONCE :只进行一次 IO 口轮询,如果没有需要执行的回调函数,这个方法会阻塞,返回0表示完成(没有活动的和被引用的句柄和请求),返回非0表示需要进行更多的回调(此时,需要再次进行事件循环);
  • UV_RUN_NOWAIT :和 UV_RUN_ONCE 的区别是,不会阻塞;

uv_run() 方法是不可重入的,它不能作为回调函数被调用

3.6、uv_loop_alive

int uv_loop_alive(const uv_loop_t* loop);

判断事件循环是否还在活动,返回非0表示还在活动

有以下几种情况之一表示还在活动:

  • 有被引用的活动句柄或者活动请求;
  • 正在关闭的句柄;

3.7、uv_stop

void uv_stop(uv_loop_t* loop);

停止事件循环,会让 uv_run() 方法尽快结束

该方法调用之后,下次事件循环迭代之前结束循环,正在进行的事件循环仍然继续

如果该函数在 IO 阻塞之前执行,则在当前的事件迭代中, IO 不会被阻塞

3.8、uv_loop_size

size_t uv_loop_size(void);

返回 uv_loop_t 结构体 size

3.9、uv_backend_fd

int uv_backend_fd(const uv_loop_t* loop);

获取后端文件描述符,仅使用于 kqueue、epoll 和 事件端口

该方法可以和 run(loop, UV_RUN_NOWAIT) 一起联合使用,在一个线程中轮询 IO 和处理回调

3.10、uv_backend_timeout

int uv_backend_timeout(const uv_loop_t* loop);

获取 IO 轮询超时时间,单位为毫秒,没有超时时返回 -1

3.11、uv_now

uint64_t uv_now(const uv_loop_t* loop);

返回当前的时间戳,单位毫秒

时间戳在事件循环开始时缓存

3.12、uv_update_time

void uv_update_time(uv_loop_t* loop);

更新事件循环的时间戳,会影响 uv_now() 的返回值,libuv 会在事件循环开始时缓存当前时间,以减少系统的时间相关的方法的调用

通常情况下不需要调用此方法,除了事件循环中的某个回调会阻塞相当长的时间,这个所谓的相当长的时间是有些主观的,可能是一毫秒或者更长

3.13、uv_walk

void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg);

遍历句柄列表,执行回调

arg 参数会传递给回调函数

void (*uv_walk_cb)(uv_handle_t* handle, void* arg);

handle 为遍历中的某个句柄

3.14、uv_loop_fork

int uv_loop_fork(uv_loop_t* loop);

在调用 fork(2) 之后,如果有必要,在子进程中重新初始化内核状态

在子进程中以观察者的身份继续事件循环

如果你想继续在子进程中使用事件循环,包括默认的事件循环(尽管不想在父进程中使用它),那么,在每个父进程中创建的事件循环中显示地调用此方法是很有必要的

该方法必须在 uv_run() ,或者其他想要在子进程中调用其他API之前调用。如果不这样做,可将将导致一些未知的错误,比如事件被重复交给父进程和子进程,或者子进程异常退出

可以的话,最好在子进程中创建一个新的循环,而不是重复使用父进程创建的循环。在 fork 子进程之后,并在子进程中创建的新的循环不应该使用此方法

该方法不适用于windows操作系统,他会返回 UV_ENOSYS

需要注意的是,该方法可能存在BUG

3.15、uv_loop_get_data

void* uv_loop_get_data(const uv_loop_t* loop);

返回 loop->data

3.16、uv_loop_set_data

void* uv_loop_set_data(uv_loop_t* loop, void* data);

设置 loop->data 的值

libuv事件循环的更多相关文章

  1. libuv事件循环中的三种句柄

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

  2. node源码详解(六) —— 从server.listen 到事件循环

    本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource6 本博客同步在https://cnodejs.o ...

  3. Node.js 事件循环(Event Loop)介绍

    Node.js 事件循环(Event Loop)介绍 JavaScript是一种单线程运行但又绝不会阻塞的语言,其实现非阻塞的关键是“事件循环”和“回调机制”.Node.js在JavaScript的基 ...

  4. node 事件循环

    什么是事件循环 Node只运行在一个单一线程上,至少从Node.js开发者的角度是这样的.在底层, Node是通过libuv来实现多线程的. Libuv库负责Node API的执行.它将不同的任务分配 ...

  5. [译] 所有你需要知道的关于完全理解 Node.js 事件循环及其度量

    原文地址:All you need to know to really understand the Node.js Event Loop and its Metrics 原文作者:Daniel Kh ...

  6. nodejs事件循环

    1. 只有一个主线程,node开始执行脚本时,会先进事件循环初始化(同步任务,发出异步请求,规划定时器生效时间,执行promise.nextTick等),这是事件循环还未开始. 2. nodejs每一 ...

  7. Node.js 事件循环机制

    Node.js 采用事件驱动和异步 I/O 的方式,实现了一个单线程.高并发的 JavaScript 运行时环境,而单线程就意味着同一时间只能做一件事,那么 Node.js 如何通过单线程来实现高并发 ...

  8. 浏览器与Node的事件循环(Event Loop)有何区别?

    前言 本文我们将会介绍 JS 实现异步的原理,并且了解了在浏览器和 Node 中 Event Loop 其实是不相同的. 一.线程与进程 1. 概念 我们经常说 JS 是单线程执行的,指的是一个进程里 ...

  9. js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)

    javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环 ...

随机推荐

  1. 软件工程UML第一次作业

    这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzzcxy/2018SE1/ 这个作业要求在哪里 https://edu.cnblogs.com/campus/f ...

  2. 不吹不黑,jupyter lab 3.0客观使用体验

    1 简介 jupyter lab于近期发布了其具有里程碑意义的3.0版本,随之带来的一些重要新特性,想必广大读者朋友已在各大公众号所翻译转载的jupyter lab团队官方介绍文章中知晓了很多. 图1 ...

  3. 项目实战--@Transactional 的使用

    @Transactional 介绍 Spring 事务管理分为编码式和声明式的两种方式,编程式事务指的是通过编码方式实现事务:声明式事务基于 AOP,将具体业务逻辑与事务处理解耦.@Transacti ...

  4. Kafka 探险 - 架构简介

    Kafka 探险 - 架构简介 这个 Kafka 的专题,我会从系统整体架构,设计到代码落地.和大家一起杠源码,学技巧,涨知识.希望大家持续关注一起见证成长! 我相信:技术的道路,十年如一日!十年磨一 ...

  5. 【排序】题解_P1093奖学金

    题目描述 奖学金 某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金.期末,每个学生都有3门课的成绩:语文.数学.英语.先按总分从高到低排序,如果两个同学总分相同,再按语文 ...

  6. docker 创建数据卷容器

    数据卷容器 --volumes-from 容器名/id 先起一个容器 docker run -it --name docker01 centos 然后同步 docker01 的数据卷 --volume ...

  7. 【Linux】dlopen failed: /lib/lsiRAID.so: cannot open shared object file: No such file or directory

    遇到这个问题,首先第一反应,是看其他的服务器中是否有这个库文件,如果有的话直接cp过来一份就行 但是检查发现,其他的系统中也不存在lsiRAID.so这个库文件,很神奇.. 但是看日志持续报错,查看s ...

  8. LeetCode671. 二叉树中第二小的节点

    题目 纯暴力 1 class Solution { 2 public: 3 vector<int>ans; 4 int findSecondMinimumValue(TreeNode* r ...

  9. 负载均衡和故障转换(Failover)的连接RAC方法

    TAF:Transparent Application Failover,透明的应用切换,即在切换的过程中,用户感知不到.可以实现会话的切换(无法实现事务的切换,即没有提交的事务会回滚),即在不断开连 ...

  10. Angular入门到精通系列教程(11)- 模块(NgModule),延迟加载模块

    1. 摘要 2. NgModule举例.说明 3. Angular CLI生成模块 4. 延迟加载模块 5. 总结 环境: Angular CLI: 11.0.6 Angular: 11.0.7 No ...