• libuv初学者学习笔记


    开始阅读前,我简单的理解觉得是,类似于leetcode的一种题,外部同时启动开始,但是内部严格的按照线程1->线程2的顺序发生过程。

    libuv框架

    从上往下看,从左往右分成网络IO与文件IO等操作:网络I/O看,linux平台通过底层epoll作为异步I/O处理,中间是抽象层uv__io_t;对于文件I/O,linux没有特定平台的异步原语,所以在线性池中执行阻塞Io来实现异步。

    同步I/O
    由于与cpu处理速度不匹配,我们采用多线程多进程来执行,不会当一个进程挂起后影响其他线程或进程。但是存在弊端,系统不会无上限的增加线程/进程,并且切换线程的开销也不能忽略,所以多线程多进程切换时间会占用cpu运行代码时间,降低性能,所以引入异步I/O。
    异步I/O
    简单来说就是,用户不需要等待内核完成实际对io的读写操作就直接返回了。

    异步 事件驱动
    libuv提供一套事件循环和基于I/O通知的回调函数还有loop。
    在这里插入图片描述

    libuv提供的核心工具->计时器、非阻塞网络编程(tcp)、异步访问文件系统……
    loops:职责:收集事件或监控其它事件。
    事件驱动编程,程序会关注事件,对于每个事件产生反应。
    上图就是所有I/O事件循环处理的过程,即uv_run()函数执行过程。

    1. 首先判断循环是否活着,通过是否存在alive活动状态的句柄,不存在则退出。
    2. 开始倒计时,维护所有的定时器,若句柄超时就告知应用层,退出或者重新加入循环。
    3. 调用待处理的回调函数,如果有待处理的就去处理它。
    4. 运行空闲句柄。
    5. 运行准备回调句柄,在某个I/O要阻塞前,有需要的话就运行回调函数。
    6. 计算轮询超时,在阻塞I/O前循环会计算阻塞时间,并将I/O进入阻塞状态。
      规则(先留印象,后理解):

    如果使用该UV_RUN_NOWAIT模式运行循环,则超时为0。
    如果要停止循环(uv_stop()被调用),则超时为0。
    如果没有活动的句柄或请求,则超时为0。
    如果有任何空闲的句柄处于活动状态,则超时为0。
    如果有任何要关闭的句柄,则超时为0。
    如果以上情况均不匹配,则采用最接近的定时器超时,或者如果没有活动的定时器,则为无穷大。

    1. 检查句柄回调,此时如果有可读可写的
      操作就调用相应回调,如果超时了就调用超时回调。

    2. 如果通过调用uv_close()函数关闭,则调用close关闭。

    3. 在超时后更新下一次循环时间。通过UV_RUN_DEFAULT模式运行循环。

    uv_run(loop, UV_RUN_DEFAULT);

    读取写入是一个会降低性能的过程,与cpu速度差的很多,所以要改善这个问题。
    在这里插入图片描述
    常见的解决方式是多线程,但是libuv采用了异步的解决方法,非阻塞风格。
    初始化loop前,给其分配相应的内存。在用uv_loop_close(uv_loop_t *)关闭loop后,要回收内存空间。
    libuv通过创造对应的I/O设备、定时器、进程等handle来实现。
    handle是不透明的数据结构,其中对应的类型uv_TYPE_t的type指定handle的使用目的。

    handle(句柄)代表持久性对象。相应的handle有许多相关联的request,request是一个短暂性对象(对比于持久性就是只维持一个回调函数的时间),对映着handle的I/O操作。

    以上就是本博客的全文,本人限于能力,上文中难免有错误的地方,若读者发现上文的错误,请于评论区中指出,本人看到之后会立即修改的,谢谢。

  • 相关阅读:
    当客户说价格高时我会这样做
    C++与OPENCV实战学习
    vue - vue基础/vue核心内容
    Web前端开发具有哪些特点?
    【MySql】3- 实践篇(一)
    springboot+旅游管理系统 毕业设计-附源码261117
    Linux三级等保基本设置
    nrf52832通过自定义profile实现BLE串口透传功能
    html属性值可以不用引号吗,实例验证
    mysql-Optimization Overview-数据库调优
  • 原文地址:https://blog.csdn.net/weixin_43786143/article/details/126298205