设计概览

libuv 是一种支持跨平台的网络库,最初是为了NodeJS作为某个模块实现的,主要基于事件驱动的I/O 模型设计的。

这个库不仅仅对不同的I/O polling 机制提供简单的抽象。 handles 和 sreams对scokets和其他的实体提供更高层的抽象,而且还支持跨平台文件I/O和线程的功能。

下面有个图,展示了libuv的不同组成部分和他们分别属于那个系统。

Handle和requests

libuv为用户提供了两个可以使用的抽象,结合事件循环:handles和request。

Handles代表一个持久对象,存活期间可以执行一系列确定的操作。例如:

o 当一个准备好的handle在存活的时候,每次循环迭代获得一次回调函数的回调

o 一个TCP的server

handle在每次有新链接的时候都会获得一次连接回调。

而Request代表一个短期操作。

这些操作可以给予handle来实现。 写请求用来在handles上写数据,或者标志:getaddrinfo不需要一个handle直接在loop中运行。

I/O 循环

I/O 循环是libuv的核心部分。它建立起IO操作的所有内容。并且它被绑定在一个单线程上。如果你想运行多个时间循环只需要在不同的线程里面运行就可以了。libuv的事件循环(其他的API可以引入事件循环和handles)不是线程安全的除非另有说明。

event事件循环采用单线程异步I/O的方法。所有的网络I/O是非阻塞的方式执行的,异步的处理方式也是操作系统中最好的方式。linux下用的epoll, OSX和其他的BSD用的是kqueque,在SUNOS用的是event ports,而windows上用的是IOCP。作为循环迭代的一部分,循环将会阻塞等待已经被poll的I/O活动 。当套接字上的条件显示可读或者可写或者其他的操作的时候,回调将会被触发。

为了更好的理解事件循环是怎么工作的。下面的这张图展示了循环迭代的所有阶段。


解释一下上面的那张图

  1. 更新循环概念中'now'事件循环在事件循环开始的时候缓存当前的时间以减少时间相关的系统调用。
  2. 循环存活迭代开始,都在循环立刻退出。所以什么时候后循环被认为是在存活呢。如果一个循环当中有活动, ref’d请求(不知道咋翻译),活跃的请求,或者正在关闭的handle,就认为他是火存活的。
  3. 由于计时器正在运行。在循环的当前概念获得他们的回调的时候所有的计时器被调度一次。
  4. pending的callbacks被调用。所有的I/O callbacks大多数情况下在polling I/O

    之后正好被调用。也有些情况在调用的时候被推迟到下一次迭代。其实上一次的迭代将任何的I/O调用推迟就会出现这种情况。

5.idlehandle被调用。尽管这是个不幸的名字,但是idle handle在每次loop迭代都会调用,当然前提是loop存活。

6.接下来 Prepare handle被调用。 Prepare handles在loop被I/O阻塞之前恰好被调用。

7. poll 是否超时被计算。在因为I/O被阻塞之前计算它应该被阻塞多久。超时规则的计算如下:

1)如果循环以UV_RUN_NOWAIT 标志运行的,,等待时间应该为0

2)如果循环将会停止(uv_stop被调用),超时时间是0.

3)如果没有活动的handles和request,超时时间是0

4)如果没有idlehandle活动漫画。超时时间是0

5)如果没有任何的handle期望结束,超时时间是0

6)如果以上没有任何一个条件满足,取最近的时间计时器,否则设为无穷大。

8. 循环因I/O阻塞。这里循环将会因上一步中I/O计算而阻塞。这里所有管理读写或其他操作的文件描述符的相关handle将得到调用。

9. check handle 被调用。 check handles恰好在loop阻塞之前恰好被调用。check handles和prepare handles是对应的。

10. close handles 被调用。 如果一个handle 被调用uv_close时候被关闭。close回调会被调用

11. 特别情况下loop可以以UV_RUN_ONCE调用。在I/O阻塞之后没有I/O调用被触发也是可能的。但是有些时间已经过去了,所以一些计时器已经到期了。这些计时器获得调用。

12.迭代停止。如果loop运行flag是 UV_RUN_NOWAIT 和 UV_RUN_ONCE迭代将会结束并且Uv_run() 将会返回。如果循环以UV_RUN_DEFAULT运行, loop存活的话会从头开始运行,否则就结束。

特别的:libuv利用线程池让异步 I/O操作变得可能。所以网络I/O 总是在单线程,每个loop是个线程。


文件I/O

不像网络 I/O, 文件I/O没有平台特殊性的文件I/O基本元可依赖。当前的方案是在线程池中运行阻塞的I/O操作。

libuv用的全局线程池,所有的事件循环都可以在上面工作。有三种类型的操作在池上运行。

文件系统操作

DNS函数

用户通过uv_queue_work()声明的代码

看一下线程池的调度部分,其实线程池大小很有限。

libuv 网络库设计概览译的更多相关文章

  1. Linux多线程服务端编程:使用muduo C++网络库

    内容推荐本 书主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread.这 ...

  2. 字节跳动在 Go 网络库上的实践

    https://mp.weixin.qq.com/s/wSaJYg-HqnYY4SdLA2Zzaw RPC 框架作为研发体系中重要的一环,承载了几乎所有的服务流量.本文将简单介绍字节跳动自研网络库 n ...

  3. 网络库libevent、libev、libuv对比

    Libevent.libev.libuv三个网络库,都是c语言实现的异步事件库Asynchronousevent library). 异步事件库本质上是提供异步事件通知(Asynchronous Ev ...

  4. REST API设计指导——译自Microsoft REST API Guidelines(四)

    前言 前面我们说了,如果API的设计更规范更合理,在很大程度上能够提高联调的效率,降低沟通成本.那么什么是好的API设计?这里我们不得不提到REST API. 关于REST API的书籍很多,但是完整 ...

  5. REST API设计指导——译自Microsoft REST API Guidelines(二)

    由于文章内容较长,只能拆开发布.翻译的不对之处,请多多指教. 另外:最近团队在做一些技术何架构的研究,视频教程只能争取周末多录制一点,同时预计在下周我们会展开一次直播活动,内容围绕容器技术这块. 所有 ...

  6. [开源] gnet: 一个轻量级且高性能的 Golang 网络库

    Github 主页 https://github.com/panjf2000/gnet 欢迎大家围观~~,目前还在持续更新,感兴趣的话可以 star 一下暗中观察哦. 简介 gnet 是一个基于 Ev ...

  7. 长文梳理muduo网络库核心代码、剖析优秀编程细节

    前言 muduo库是陈硕个人开发的tcp网络编程库,支持Reactor模型,推荐大家阅读陈硕写的<Linux多线程服务端编程:使用muduo C++网络库>.本人前段时间出于个人学习.找工 ...

  8. 《Linux多线程服务端编程:使用muduo C++网络库》上市半年重印两次,总印数达到了9000册

    <Linux多线程服务端编程:使用muduo C++网络库>这本书自今年一月上市以来,半年之内已经重印两次(加上首印,一共是三次印刷),总印数达到了9000册,这在技术书里已经算是相当不错 ...

  9. C/C++ 网络库介绍

    C/C++ 网络库介绍 Aggregated List of Libraries(Source Link) Boost.Asio is really good. Asio is also availa ...

  10. 跨平台网络库(采用C++ 11)

    I:跨平台设计基础 在windows下使用0字节的WSARecv/WSASend(读写)作为读写检测,将IOCP作为一个通知模型,而"抛弃"它的异步模型. 即:把它当作epoll来 ...

随机推荐

  1. vulnhub靶场之GROTESQUE: 3.0.1

    准备: 攻击机:虚拟机kali.本机win10. 靶机:Grotesque: 3.0.1,下载地址:https://download.vulnhub.com/grotesque/grotesque3. ...

  2. [OpenCV实战]12 使用深度学习和OpenCV进行手部关键点检测

    目录 1 背景 2 实现 3 结果和代码 4 参考 手部关键点检测是在手指上找到关节以及在给定图像中找到指尖的过程.它类似于在脸部(面部关键点检测)或身体(人体姿势估计)上找到关键点.但是手部检测不同 ...

  3. CentOS7.6搭建Hadoop2.7.2运行环境-三节点集群模式

    一 环境准备 1.    准备机器 2.    修改静态IP 3.    修改主机名 4.    关闭防火墙 5.    创建普通用户hadoop 添加hadoop用户 [root@hadoop102 ...

  4. 巧用Fiddler开启运营商定制版路由器被阉割的功能,免去刷公版固件的风险

    前言: 三大运营商都有自己的定制版路由器,一般会在自家营销活动中作为赠品送给用户 正巧我家里就有两台电信定制版的华为路由器,都是这两年双十一在某宝上买宽带时送的 两台路由器型号分别是TC7001和TC ...

  5. python之路50 ORM执行SQL语句 操作多表查询 双下线方法

    ORM执行查询SQL语句 有时候ORM的操作效率可能偏低 我们是可以自己编写SQL的 方式1: models.User.objects.raw('select * from app01_user;') ...

  6. 分布式拒绝服务攻击(DDoS)和僵尸网络(Botnet)

    DDos和僵尸网络是相辅相成的两种攻击手段,本文仅介绍基本概念,详细请查看文末参考资料. 分布式拒绝服务攻击(DDoS) 分布式拒绝服务攻击DDoS是一种基于DoS的特殊形式的拒绝服务攻击,是一种分布 ...

  7. 一文解决如何使用 C 语言判断质数(素数)[ 附解析与源码 ]

    前言 质数历来都是数学界的宠儿,是数学里神秘的谜团. 质数又和 C 语言有着不解之缘,本篇文章将讲解如何用 C 语言判断质数. 为了方便大家在读完此文章后使用文中程序,我会将判断质数的程序封装成函数, ...

  8. (20)go-micro微服务Elasticsearch使用

    目录 一 Elasticsearch介绍 二 Elasticsearch的主要功能及应用场景 1.Elasticsearch 主要具有如下功能: 2.Elasticsearch 的主要应用场景如下: ...

  9. Python3+Selenium3自动化测试-(八)

    使用selenium进行测试,当然是需要进行验证的,此时结合python的断言函数就变得非常有用了.测试中设定好预期,当实际情况与预期有差别,给出错误信息,好像正是所希望的. 来一段简单的代码看下断言 ...

  10. 处理流中的异常-JDK7-和JDK9流中异常的处理

    处理流中的异常 JDK7和JDK9流中异常的处理 jdK7的新特性在try的后边可以增加一个(),在括号中可以定义流对象那么这个流对象的作用域就在try中有效try中的代码执行完毕,会自动把流对象释放 ...