一点一滴成长

导航

libuv概述

1、综述

  libuv是一个高性能的,事件驱动的I/O库,支持跨平台(由平台决定使用libev或IOCP),诞生自node.js(关于node.js的介绍参见文章JavaScript介绍中node.js部分)。libev是网络库libevent的改进版,但libev在Windows下的性能不太好(使用select模型),而libuv则封装了Windows上的IOCP,性能更高,所以后来node.js使用libuv替换了libev。除了node.js以外,Rust编程语言也使用libuv。

  libuv使用异步的,事件驱动的编程风格,其核心工作是提供一个event-loop,以及基于I/O等其它事件的回调通知。异步事件驱动指的是我们可以提前注册感兴趣的事件,比如读取数据,然后在数据到来可读的时候得到通知。

  libuv还提供了一些核心工具,如非阻塞网络支持,异步文件系统访问,定时器,子进程等。

2、简单示例

   如下为开启一个loop的简单示例:

#include "uv.h"

int main()
{
    uv_loop_t* loop = (uv_loop_t*)malloc(sizeof(uv_loop_t)); //loop类型的handle
    uv_loop_init(loop); //初始化loop

    uv_run(loop, UV_RUN_DEFAULT); //启动event-loop,因为没有注册任何要监听的事件,所以会直接退出,除了UV_RUN_DEFAULT,还有UV_RUN_NOWAIT(只处理一个事件,没有事件的话会阻塞)和UV_RUN_ONCE(只处理一个事件,没有事件的话直接返回)

    uv_loop_close(loop); //关闭loop,回收内存
    uv_fs_t t;
    free(loop);
}

  handle代表了持久性对象,相应的handle上有许多与之关联的request,如uv_loop_t、uv_idle_t、uv_tcp_t。request是短暂性对象(通常只维持在一个回调函数的时间),通常对映着handle上的一个I/O操作,用来传递上下文,如uv_fs_t、uv_req_t、uv_connect_t。handle和request都有一个void*类型的data域,可以用来存储自定义的上下文信息。

  下面是一个使用空转handle(uv_idle_t)的例子,当达到1000的计数后,关闭空转监视器,当找不到活着的事件监视器后,uv_run()也会退出:

#include "uv.h"

int64_t counter = 0;
void wait_for_a_while(uv_idle_t* handle) {
    counter++;

    if (counter >= 1000) {
        uv_idle_stop(handle);
        printf("stop Idling\n");
    }
}

int main()
{
        uv_idle_t idler; //空转handle
        uv_loop_t* loop = uv_default_loop(); //使用libuv提供的默认loop
    
        uv_idle_init(loop, &idler);
        uv_idle_start(&idler, wait_for_a_while);
    
        printf("Idling start\n");
        uv_run(loop, UV_RUN_DEFAULT);
    
        uv_loop_close(loop);
    
        printf("Idling end\n");
}

 3、终止event loop

  uv_stop(uv_loop_t*)用来终止event loop,loop会停止的最早时间点是在下次循环的时候,这也就意味着在本次循环中已经准备被处理的事件,依然会被处理。调用uv_stop()后,uv_loop_t::stop_flag域会被设置为1。

posted on 2024-05-09 09:50  整鬼专家  阅读(13)  评论(0编辑  收藏  举报