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. 一言不合就开始搞JDK源码

    ​Java是一门面向对象的编程语言,那什么是面向对象呢,下面将是历史上最通俗易懂的解释了,请看下图: 哈哈,解释的够清楚的了吧.闪. 从源码学编程的好处 学Java编程时,最好同时看一些Java的源码 ...

  2. hdfs读写删除过程解析

    一.hdfs文件读取过程 hdfs有一个FileSystem实例,客户端通过调用这个实例的open()方法就可以打开系统中希望读取的文件,hdfs通过rpc协议调用Nadmenode获取block的位 ...

  3. centos6.8环境搭建

    1.centos6 yum源失效解决方案 下载使用阿里的云仓库 curl -o /etc/yum.repos.d/CentOS-Base.repo https://www.xmpan.com/Cent ...

  4. 每日CSS_滚动页面动画效果

    每日CSS_滚动页面动画效果 2021_1_13 源码链接 1. 代码解析 1.1 html 代码片段 <section> <h2>开 始 滑 动</h2> < ...

  5. Both Dolby Atmos driver and API need to be installed问题的一个解决方法

    问题的原因在于缺少以下两个部分: Dolby Atmos driver:指你的声卡驱动中自带的杜比文件 如果驱动里没有,说明你的硬件可能不支持杜比,或者驱动太老没有包含杜比. Dolby Atmos ...

  6. Deep Learn I'm back.

    Intorduction: 时隔好几个月,我准备重新进入Deep Learning 的领域.昨天和老师聊了很多,之前觉得我做的工作就是排列组合,在水论文,灌水.但老师却说:这也是为将来的研究打基础. ...

  7. python模块详解 | selenium(持续更新中)

    目录: 关于selenium Selenium 安装Selenium 安装浏览器驱动 配置环境变量 selenium方法详解 定位元素 元素操作 浏览器操作 鼠标事件 浏览器事件 设置元素等待 多表单 ...

  8. Pycharm同时执行多个脚本文件

    Pycharm同时执行多个脚本文件 设置Pycharm使它可以同时执行多个程序 打开Pycharm 找到Run,点击确认 点击Edit Configurations 右上角Allow parallel ...

  9. 【Linux】rsync的相关用途

    Rsync,代表"remote sync",它是本地和远程主机文件同步工具.它只同步更改的文件,以此实现最小化传输数据. 我使用Ubuntu 16.04做为例子,但是你可以把它应用 ...

  10. java创建线程安全的类

    如果一个对象想要被多个线程安全的并发访问,那么这个对象必须是或线程安全的或事实不可变的或由锁来保护的. 1.java监视器模式 大多数对象都是组合对象.当从头开始构建一个类,或者将多个非线程安全的类组 ...