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. vue中使用AES.js和crypto.js加密

    一:crypto-js加密 1.1:安装依赖 npm install crypto-js --save-dev 1.2 :在项目目录上创建一个js文件里面写入加密,解密的代码 mport Crypto ...

  2. istio kiali 亲和性调度

    一.节点调度 在开始 kiali 亲和性调度之前,先演示一个简单的例子介绍 pod 选择调度到指定 node: 节点打标 使用命令查看当前所有 k8s 节点: [root@k8s-master ~]# ...

  3. redis简介与window安装:

    redis简介与window安装: 花开堪折直需折,莫待无花空折枝 Redis 概念:Redis (REmote DIctionary Server) 是用 C 语言开发的一个开源的高性能键值对(ke ...

  4. 安装Linux Deploy和Termux之后,再安装ftp服务软件都是多余的!

    之前以为Debian 9 running via Linux Deploy或者Termux在安卓系统部署之后,一定要安装vsftpd或者pure-ftpd这些专门的ftp服务器软件,才能提供ftp服务 ...

  5. Docker-ce Centos8 笔记二:常见问题

  6. Jquery实现对Array数组实现类似Linq的Lambda表达式的Where方法筛选

    平时使用Linq,习惯了Lambda表达式,用着非常顺手,奈何在Jquery里面不能这样用,只能循环一个个判断.趁空闲时间找了找,自己写了这样的扩展方法.目前写出了三种方案,没有比较性能,觉得都可以用 ...

  7. 一文读懂 TKE 及 Kubernetes 访问权限控制

    你有了解过Kubernetes的认证授权链路吗?是否对TKE的权限控制CAM策略.服务角色傻傻分不清楚?本文将会向你介绍腾讯云TKE平台侧的访问控制.Kubernetes访问控制链路,以及演示如何将平 ...

  8. PAT练习num1-害死人补偿命的3n+1猜想

    卡拉兹(Callatz)猜想: 对任何一个正整数 n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把 ( 砍掉一半.这样一直反复砍下去,最后一定在某一步得到 n=1.卡拉兹在 1950 年的世界 ...

  9. (05)-Python3之--运算符操作

    1.算数运算 num_a = 100 num_b = 5000 # 加法 + print(num_a + num_b) # 减法 - print(num_a - num_b) # 乘法 * print ...

  10. Linux kernel 同步机制

    Linux kernel同步机制(上篇) https://mp.weixin.qq.com/s/mosYi_W-Rp1-HgdtxUqSEgLinux kernel 同步机制(下篇) https:// ...