当前位置 博文首页 > sherlock_lin:libuv事件循环
事件循环是 libuv 的核心功能,负责 IO 的轮询和事件回调的调度。
事件循环数据类型,结构体
uv_loop_t.data 用于传递用户数据,libuv 不会触碰
传递给 uv_walk() 方法的回调函数类型
void (*uv_walk_cb)(uv_handle_t* handle, void* arg);
int uv_loop_init(uv_loop_t* loop);
初始化 uv_loop_t 结构体
要注意,调用之前需要先给 uv_loop_t 分配内存资源,否则会崩溃
int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...);
设置事件循环配置,一般应该在第一次调用 uv_run() 之前执行
返回值: 0表示成功,错误则返回一个 UV_E 错误码,UV_ENOSYS 表示平台不支持该事件循环配置
支持选项:
int uv_loop_close(uv_loop_t* loop);
释放所有内部循环资源
仅当所有循环完成并且所有打开的句柄和请求都已经关闭的时候才可调用此函数,否则将返回 UV_EBUSY
此函数返回后,用户可以释放为循环申请的内存
uv_loop_t* uv_default_loop(void);
返回 libuv 的默认事件循环,如果分配失败了,可能返回NULL
这个方法是在整个应用程序中进行全局循环的一个便捷的方式,和自定义的事件循环相同
int uv_run(uv_loop_t* loop, uv_run_mode mode);
运行事件循环,mode 指定运行模式,有如下几种:
uv_run() 方法是不可重入的,它不能作为回调函数被调用
int uv_loop_alive(const uv_loop_t* loop);
判断事件循环是否还在活动,返回非0表示还在活动
有以下几种情况之一表示还在活动:
void uv_stop(uv_loop_t* loop);
停止事件循环,会让 uv_run() 方法尽快结束
该方法调用之后,下次事件循环迭代之前结束循环,正在进行的事件循环仍然继续
如果该函数在 IO 阻塞之前执行,则在当前的事件迭代中, IO 不会被阻塞
size_t uv_loop_size(void);
返回 uv_loop_t 结构体 size
int uv_backend_fd(const uv_loop_t* loop);
获取后端文件描述符,仅使用于 kqueue、epoll 和 事件端口
该方法可以和 run(loop, UV_RUN_NOWAIT) 一起联合使用,在一个线程中轮询 IO 和处理回调
int uv_backend_timeout(const uv_loop_t* loop);
获取 IO 轮询超时时间,单位为毫秒,没有超时时返回 -1
uint64_t uv_now(const uv_loop_t* loop);
返回当前的时间戳,单位毫秒
时间戳在事件循环开始时缓存
void uv_update_time(uv_loop_t* loop);
更新事件循环的时间戳,会影响 uv_now() 的返回值,libuv 会在事件循环开始时缓存当前时间,以减少系统的时间相关的方法的调用
通常情况下不需要调用此方法,除了事件循环中的某个回调会阻塞相当长的时间,这个所谓的相当长的时间是有些主观的,可能是一毫秒或者更长
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 为遍历中的某个句柄
int uv_loop_fork(uv_loop_t* loop);
在调用 fork(2) 之后,如果有必要,在子进程中重新初始化内核状态
在子进程中以观察者的身份继续事件循环
如果你想继续在子进程中使用事件循环,包括默认的事件循环(尽管不想在父进程中使用它),那么,在每个父进程中创建的事件循环中显示地调用此方法是很有必要的
该方法必须在 uv_run() ,或者其他想要在子进程中调用其他API之前调用。如果不这样做,可将将导致一些未知的错误,比如事件被重复交给父进程和子进程,或者子进程异常退出
可以的话,最好在子进程中创建一个新的循环,而不是重复使用父进程创建的循环。在 fork 子进程之后,并在子进程中创建的新的循环不应该使用此方法
该方法不适用于windows操作系统,他会返回 UV_ENOSYS
需要注意的是,该方法可能存在BUG
void* uv_loop_get_data(const uv_loop_t* loop);
返回 loop->data
void* uv_loop_set_data(uv_loop_t* loop, void* data);
设置 loop->data 的值