libuv:多平台支持库-异步I / O

http://libuv.org/

目录

概述¶

功能

文档

下载

安装

设计概述¶

把手和请求¶

I / O循环

文件I / 


概述

libuv是一个多平台支持库,主要关注异步I / O。它主要通过开发使用Node.js的,但它也使用了Luvit, 朱莉娅pyuv,和其他人

注意

 

如果您在本文档中发现错误,可以发送拉取请求来帮助您 !

功能

  • 由epoll,kqueue,IOCP和事件端口支持的功能齐全的事件循环。
  • 异步TCP和UDP套接字
  • 异步DNS解析
  • 异步文件和文件系统操作
  • 文件系统事件
  • ANSI转义码控制的TTY
  • 具有套接字共享的IPC,使用Unix域套接字或命名管道(Windows)
  • 子进程
  • 线程池
  • 信号处理
  • 高分辨率时钟
  • 线程和同步原语

下载

可以从这里下载libuv 。

安装

安装说明可在README中找到。

 

 

设计概述

libuv是跨平台支持库,最初是为Node.js编写的。它是围绕事件驱动的异步I / O模型设计的。

该库提供的不只是对不同I / O轮询机制的简单抽象:“句柄”和“流”为套接字和其他实体提供了高级抽象;还提供跨平台文件I / O和线程功能。

这是说明组成libuv的不同部分以及它们与哪个子系统有关的图:

libuv:多平台支持库-异步I / O

把手和请求

libuv与事件循环结合为用户提供2种抽象的处理方式:句柄和请求。

句柄表示活动时能够执行某些操作的长寿命对象。一些例子:

  • 准备句柄在活动时每次循环迭代都会调用一次其回调。
  • 一个TCP服务器句柄在每次有新连接时都会调用其连接回调。

请求代表(通常)短暂的操作。这些操作可以在一个句柄上执行:写请求用于在句柄上写数据;还是独立运行:getaddrinfo请求不需要直接在循环上运行的句柄。

I / O循环

I / O(或事件)循环是libuv的核心部分。它建立所有I / O操作的内容,并且将其绑定到单个线程。只要每个事件循环在不同的线程中运行,就可以运行多个事件循环。除非另有说明,否则libuv事件循环(或与此有关的任何其他涉及循环或句柄的API)都不是线程安全的

事件循环遵循通常的单线程异步I / O方法:所有(网络)I / O在非阻塞套接字上执行,这些套接字使用给定平台上可用的最佳机制进行轮询:Linux上的epoll,OSX上的kqueue和其他BSD,SunOS上的事件端口和Windows上的IOCP。作为循环迭代的一部分,循环将阻止等待已添加到轮询器中的套接字上的I / O活动,并且将触发回调以指示套接字条件(可读,可写挂起),以便句柄可以读取,写入或执行所需的I / O操作。

为了更好地了解事件循环的运行方式,下图说明了循环迭代的所有阶段:

libuv:多平台支持库-异步I / O

  1. “ now”的循环概念已更新。为了减少与时间相关的系统调用的数量,事件循环在事件循环滴答的开始处缓存当前时间。

  2. 如果循环是活动 的,则开始迭代,否则循环将立即退出。那么,什么时候认为循环还活着?如果循环具有活动句柄和引用句柄,活动请求或关闭句柄,则认为该循环是活动的

  3. 到期计时器运行。计划在循环概念之前的某个时间的所有活动计时器现在 将调用其回调。

  4. 调用待处理的回调。大多数情况下,在轮询I / O之后立即调用所有I / O回调。但是,在某些情况下,调用此类回调会推迟到下一个循环迭代。如果先前的迭代推迟了任何I / O回调,则它将在此时运行。

  5. 空闲句柄回调被调用。尽管名称很不幸,但如果空闲句柄处于活动状态,则会在每次循环迭代中运行它们。

  6. 准备句柄回调。准备句柄在循环将阻止I / O之前立即调用其回调。

  7. 计算轮询超时。在阻塞I / O之前,循环会计算阻塞的时间。这些是计算超时的规则:

    • 如果使用该UV_RUN_NOWAIT标志运行循环,则超时为0。
    • 如果要停止循环(uv_stop()被调用),则超时为0。
    • 如果没有活动的句柄或请求,则超时为0。
    • 如果有任何空闲的句柄处于活动状态,则超时为0。
    • 如果有任何要关闭的句柄,则超时为0。
    • 如果以上情况均不匹配,则采用最接近的定时器超时,或者如果没有活动的定时器,则为无穷大。
  8. I / O的循环块。此时,循环将在上一步计算的持续时间内阻止I / O。此时,监视给定文件描述符的读写操作的所有与I / O相关的句柄都将调用其回调。

  9. 检查句柄回调被调用。在为I / O阻塞循环之后,检查句柄立即调用其回调。检查手柄本质上是准备手柄的对应物。

  10. 关闭回调被调用。如果通过调用关闭了句柄uv_close(),则将调用close回调。

  11. 如果循环使用来运行UV_RUN_ONCE,则为特例,因为这意味着前进。阻止I / O后可能没有触发任何I / O回调,但是经过了一段时间,因此可能有到期的计时器,这些计时器将调用其回调。

  12. 迭代结束。如果循环以UV_RUN_NOWAITUV_RUN_ONCE模式运行,则迭代结束并uv_run()返回。如果运行了循环,UV_RUN_DEFAULT 那么如果循环仍然存在,它将从头开始继续运行,否则也将结束。

重要

 

libuv使用线程池使异步文件I / O操作成为可能,但是网络I / O 始终在单个线程(每个循环的线程)中执行。

注意

 

尽管轮询机制不同,但是libuv使执行模型在Unix系统和Windows之间保持一致。

文件I / 

与网络I / O不同,libuv没有依赖于平台的文件I / O原语,因此当前方法是在线程池中运行阻止文件I / O操作。

要全面了解跨平台文件I / O的情况,请查看 这篇文章

libuv当前使用全局线程池,所有循环都可以在该线程池上排队工作。当前在此池上运行3种类型的操作:

  • 文件系统操作
  • DNS函数(getaddrinfo和getnameinfo)
  • 用户指定的代码通过 uv_queue_work()

警告:有关更多详细信息,请参见“ 线程池工作调度”部分,但是请记住,线程池的大小非常有限。