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. C语言-表达式和运算符

    表达式:表达式是c语言的主体,在c语言中,表达式由操作符和操作数组成.简单的表达式可以只有一个操作数.根据操作符的个数,可以将表达式分为简单表达式和复杂表达式,简单的表达式只含有一个操作符(如:5+5 ...

  2. CSS-position 属性&元素脱离文档流引发父级边框塌陷问题

    CSS-position 属性 CSS 定位机制 CSS 有三种基本的定位机制:普通流.浮动(float)和绝对定位(position). 除非专门指定,否则所有框都在普通流中定位.也就是说,普通流中 ...

  3. ES6 浅谈Reflect

    Reflect 属于一个静态类,不能通过new的方法去创建实例,只能调用静态类中的一些静态方法,Reflect内部封装了一系列对对象的底层操作, Reflect 成员方法就是Proxy处理对象的默认实 ...

  4. 九、kafka伪分布式和集群搭建

    伪分布式: 1.先将zk启动,如果是在伪分布式下,kafka已经集成了zk nohup /kafka_2.11-0.10.0.1/bin/zookeeper-server-start.sh /kafk ...

  5. 中移动ipv6-老毛子固件获取ipv6设置

    对于有ipv6的服务商原理上可以参照下图

  6. 风炫安全web安全学习第三十七节课 15种上传漏洞讲解(二)

    风炫安全web安全学习第三十七节课 15种上传漏洞讲解(二) 05后缀名黑名单校验之上传.htaccess绕过 还是使用黑名单,禁止上传所有web容器能解析的脚本文件的后缀 $is_upload = ...

  7. swack的wiki站上线

    swack的个人wiki网址:www.swack.cn [服务器破旧,速度较慢,见谅!]

  8. redis 5.0.5 安装

    redis 5.0.5 安装脚本: #!/bin/bash cd /data/src/ test -e tcl8.6.9-src.tar.gz || wget http://downloads.sou ...

  9. MalformedByteSequenceException: 1字节的 UTF-8 序列的字节 1 无效

    记住,每次修改了配置之后都 clean 一下,把 target 删除 第一种解决方案 去掉 pom.xml 中的 properties <properties> <maven.com ...

  10. 【Linux】使用grep快速比较两个文件不同

    两个文件的比较,会有同学说使用diff,和vimdiff就可以快速比较,为什么还要使用grep呢? 有些时候,diff和vimdiff的时候环境不符合,这样的情况,就可以使用grep来解决这个问题. ...