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. 浅谈connect,withRouter,history,useState,useEffect

    1.connect in umi connect 可以链接不同的组件,从而在这个组件中使用其他组件的参数,常用于获取redux中存取的值. 2.withRouter in umi withRouter ...

  2. Vue基础语法与指令

    项目初始化 用vscode打开终端,输入npm init -y生成package.json 然后安装vue npm install vue 需要注意的是,我遇到了这个问题 出现原因:文件夹名和生成的p ...

  3. Linux应急响应--入侵排查

    1.入侵者可能会删除机器的日志信息,可以查看日志信息是否还存在或者是否被清空,相关命令示例: ll -h /var/log/*  系统日志一般都存在/var/log下常用的系统日志如下:核心启动日志: ...

  4. 【栈和队列】5、队列概述与数组队列的基本实现 - Java

    3-5 数组队列 简单记录 - bobo老师的玩转算法系列–玩转数据结构 - 栈和队列 队列Queue 队列也是一种线性结构 相比数组,队列对应的操作是数组的子集 只能从一端(队尾)添加元素,只能从另 ...

  5. P1967 货车运输(倍增LCA,生成树)

    题目链接: https://www.luogu.org/problemnew/show/P1967 题目描述 A国有n座城市,编号从 1到n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制, ...

  6. URL重定向 - Pikachu

    概述: 不安全的url跳转问题可能发生在一切执行了url地址跳转的地方.如果后端采用了前端传进来的(可能是用户传参,或者之前预埋在前端页面的url地址)参数作为了跳转的目的地,而又没有做判断的话就可能 ...

  7. 【JAVA并发第三篇】线程间通信

    线程间的通信 JVM在运行时会将自己管理的内存区域,划分为不同的数据区,称为运行时数据区.每个线程都有自己私有的内存空间,如下图示: Java线程按照自己虚拟机栈中的方法代码一步一步的执行下去,在这一 ...

  8. pycharm工具的使用

    一.Pycharm常用快捷键 快捷键 作用 备注  ctrl + win + 空格  自动提示并导包  连按两次  ctrl + alt + 空格  自动提示并导包  连按两次  Alt + Ente ...

  9. .NET 项目中的单元测试

    .NET 项目中的单元测试 Intro "不会写单元测试的程序员不是合格的程序员,不写单元测试的程序员不是优秀的工程师." -- 一只想要成为一个优秀程序员的渣逼程序猿. 那么问题 ...

  10. Java中的Date类型无法赋值给数据库的datetime类型

    因为Java中new Date()的结果是"Thu Aug 27 19:03:54 CST 2020",而mysql中的datetime不接受这样的日期格式,插入数据会报错. 解决 ...