libuv之事件循环loop

libuv是一个强制使用异步、事件驱动编程风格的库,核心是事件循环(event-loop),用于处理I/O和其他事件的回调。它提供定时器、非阻塞网络、文件系统访问及子进程等工具。事件驱动编程中,libuv收集并处理事件,调用回调函数。而非阻塞I/O避免了传统阻塞式I/O造成的性能瓶颈,通过操作系统事件通知实现高效运行。libuv的事件循环与操作系统事件紧密结合,确保了事件的及时处理。

libuv强制使用异步的,事件驱动的编程风格。它的核心工作是提供一个event-loop,还有基于I/O和其它事件通知的回调函数。libuv还提供了一些核心工具,例如定时器,非阻塞的网络支持,异步文件系统访问,子进程等。

在事件驱动编程中,程序会关注每一个事件,并且对每一个事件的发生做出反应。libuv会负责将来自操作系统的事件收集起来,或者监视其他来源的事件。这样,用户就可以注册回调函数,回调函数会在事件发生的时候被调用。event-loop会一直保持运行状态。用伪代码描述如下:

 

while there are still events to process:
    e = get the next event
    if there is a callback associated with e:
        call the callback

 

系统编程中最经常处理的一般是输入和输出,而不是一大堆的数据处理。问题在于传统的输入/输出函数(例如readfprintf)都是阻塞式的。实际上,向文件写入数据,从网络读取数据所花的时间,对比cpu的处理速度差得太多。任务没有完成,函数是不会返回的,所以你的程序在这段时间内什么也做不了。对于需要高性能的的程序来说,这是一个主要的障碍。

其中一个标准的解决方案是使用多线程。每一个阻塞的I/O操作都会被分配到各个线程中(或者是使用线程池)。当某个线程一旦阻塞,处理器就可以调度处理其他需要cpu资源的线程。

但是libuv使用了另外一个解决方案,那就是异步,非阻塞。大多数的现代操作系统提供了基于事件通知的子系统。例如,一个正常的socket上的read调用会发生阻塞,直到发送方把信息发送过来。但是,实际上程序可以请求操作系统监视socket事件的到来,并将这个事件通知放到事件队列中。这样,程序就可以很简单地检查事件是否到来(可能此时正在使用cpu做数值处理的运算),并及时地获取数据。说libuv是异步的,是因为程序可以在一头表达对某一事件的兴趣,并在另一头获取到数据(对于时间或是空间来说)。它是非阻塞是因为应用程序无需在请求数据后等待,可以自由地做其他的事。libuv的事件循环方式很好地与该模型匹配, 因为操作系统事件可以视为另外一种libuv事件. 非阻塞方式可以保证在其他事件到来时被尽快处理(当然还要考虑硬件的能力)。

Note:

我们不需要关心I/O在后台是如何工作的,但是由于我们的计算机硬件的工作方式,线程是处理器最基本的执行单元,libuv和操作系统通常会运行后台/工作者线程, 或者采用非阻塞方式来轮流执行任务。

Bert Belder,一个libuv的核心开发者,通过一个短视频向我们解释了libuv的架构和它的后台工作方式。如果你之前没有接触过类似libuv,libev,这个视频会非常有用。视频的网址是https://youtu.be/nGn60vDSxQ4

包含了libuv的event-loop的更多详细信息:

http://docs.libuv.org/en/v1.x/design.html#the-i-o-loop

### 如何停止 Libuv 事件循环 为了停止 Libuv事件循环,可以调用 `uv_stop()` 函数。此函数的作用是在下一次迭代时使事件循环停止运行[^1]。 需要注意的是,在当前迭代中已经准备好处理的事件仍然会被执行,因此 `uv_stop()` 并不能立即终止所有的操作,而是让事件循环在完成当前轮次后再退出。这意味着即使调用了 `uv_stop()`,任何已经在队列中的回调仍会在本次迭代内被执行完毕。 当 `uv_stop()` 被调用之后,事件循环不会在此后的这次迭代里等待 I/O 操作的发生;然而,这并不影响那些已经被标记为可读写状态并准备就绪的任务继续被处理。具体来说,`ran_pending = uv__run_pending(loop)` 这段代码会遍历待处理队列,并依次触发相应的回调函数来响应这些已发生的事件[^2]。 下面是一个简单的例子展示如何使用 `uv_stop()` 来结束一个正在运行的事件循环: ```c #include <stdio.h> #include <uv.h> void on_timeout(uv_timer_t* handle) { printf("Timer triggered\n"); // 停止事件循环 uv_stop(handle->loop); } int main() { uv_loop_t *loop = uv_default_loop(); uv_timer_t timer_handle; uv_timer_init(loop, &timer_handle); uv_timer_start(&timer_handle, on_timeout, 1000, 0); // 开始事件循环 uv_run(loop, UV_RUN_DEFAULT); // 此处表示事件循环已被成功停止 printf("Event loop stopped.\n"); return 0; } ``` 在这个程序片段中,设置了一个定时器,在一秒后触发 `on_timeout` 回调函数,该函数内部通过调用 `uv_stop()` 请求停止事件循环。一旦这个请求得到满足,控制权就会返回给主线程,并打印出 "Event loop stopped." 字样。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JXES智能生态系统

如文章对你有用,请作者喝个咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值