龙空技术网

不懂就问:什么是 Eventloop?

嵌入式开发卡贝 889

前言:

今天各位老铁们对“timertimeout”都比较看重,各位老铁们都需要分析一些“timertimeout”的相关资讯。那么小编在网上网罗了一些对于“timertimeout””的相关知识,希望姐妹们能喜欢,朋友们一起来了解一下吧!

最近了解了一下 Eventloop 这个概念,写篇文章整理一下思路。1、Eventloop 是什么?

我在网上看了一些资料,都比较复杂,而且大多和 JavaScript 扯上关系,对初学者不友好。

我个人理解的 Eventloop,其实就是在一个大循环里,处理各种各样的事件。只是不同的 Eventloop 机制或者库,在性能和适用场景之间有差别罢了。

一个程序,只要它需要一直工作,就会处于一个持续循环运行的状态,我把这个循环的状态,称为 Eventloop。

最简单的例子:

int main(){    int choice;    do {        // 等待用户输入     choice = getch();        switch (choice) {        case 'q':            break;        case 'a':            add_record();            break;        [...]        }    } while (choice != 'q');    exit(EXIT_SUCCESS);}

上面这个程序,在一个 while 循环里,根据不同的键盘输入事件,而执行不同的操作。

这就是一个简单的 Eventloop,只是这个 Eventloop 只处理一种事件:键盘输入,且是阻塞等待,虽然很简陋,但是对于上面这个场景而言,已经够用了。

Eventloop 随处可见:

许多开源软件,只要它们有持续运行 + 事件处理的需求,就会有自己的 Eventloop 实现,例如:

图形库 Qt 里的 QGuiApplication::run();

多媒体库 SDL2 里的 SDL_PollEvent();

网络库 Mongoose 里的 mg_mgr_poll();

本质上都是一种 Eventloop,只是由于需求和应用场景的不一样,各自的实现方法有所差异。

合格的 Eventloop:

一个合格的 Eventloop,需要有哪些特性?

我个人认为:

1、不要阻塞,即不要调用可能会阻塞的系统调用,或总是以 nonblocking 的方式调用系统调用。

2、能异步处理事件。

3、性能尽量高,以满足业务需求为下限。

满足上述 3 点,这个 Eventloop 在功能上就是够用的。

2、Eventloop 怎么用?

基于 select 的 Eventloop:

这是来自 UNIX 网络编程 16.2 章节的一个例子,其大致代码如下:

str_cli(FILE *fp, int sockfd){    ...    // set nonblock    val = Fcntl(sockfd, F_GETFL, 0); Fcntl(sockfd, F_SETFL, val | O_NONBLOCK);    // eventloop    for ( ; ; ) {        ...        Select(maxfdp1, &rset, &wset, NULL, NULL);        if (FD_ISSET(sockfd, &rset)) {            // do something        }        ... // other event    }}

这个程序会从标准输入中读取一行数据,然后通过 socket 发送给服务端,然后接收服务端的响应,最后将响应也写到标准输出。

最关键的点是先调用 fcntl 将所有的输入输出都设置为 nonblock,然后用 select 监测所有的文件描述符。

基本上所有的开源事件库,本质上和这个程序没差别。

嵌入式物联网需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!

无偿分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!某鱼上买估计至少要好几十。

点击这里找小助理0元领取:嵌入式物联网学习资料(头条)

各种开源的 Eventloop 库:

由于 Eventloop 是一个比较通用的需求,在开源软件里,有许多优秀的异步事件库都实现了这个功能。

比较适合嵌入式领域异步事件库有 3 个:

libevent:an event notification library.

名气最大,应用最广泛,历史最悠久的跨平台事件库。

libev:a high performance full-featured event loop written in C.

较 libevent 而言,设计更简练,但对 Windows 支持不够好,且和开源社区不怎么接轨。

libuv:a multi-platform support library with a focus on asynchronous I/O

点击查看大图

开发 node.js 的过程中需要一个跨平台的事件库,目前非常活跃,推荐大家重点学习。

libev 最精简,入门最容易,这里用它来介绍一下事件库的用法:

#include <ev.h>#include <stdio.h> // 定义两个事件 watcherev_io stdin_watcher;ev_timer timeout_watcher;// io watcher 的回调函数static voidstdin_cb (EV_P_ ev_io *w, int revents){  puts ("stdin ready");  ev_io_stop (EV_A_ w);   ev_break (EV_A_ EVBREAK_ALL);}// timer watcher 的回调函数static voidtimeout_cb (EV_P_ ev_timer *w, int revents){  puts ("timeout");  ev_break (EV_A_ EVBREAK_ONE);} int main (void){  // 定义 eventloop  struct ev_loop *loop = EV_DEFAULT;  // 初始化 io watcher   ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);  ev_io_start (loop, &stdin_watcher);  // 初始化 timer watcher   ev_timer_init (&timeout_watcher, timeout_cb, 2, 0.);  ev_timer_start (loop, &timeout_watcher);   // 启动 eventloop  ev_run (loop, 0);   return 0;}

libev 用 watcher 来检测各种事件,当事件发生时,会调用 watcher 的回调函数。

具体支持哪些事件类型呢?

如果你对 libev 感兴趣,可以根据下面这张图阅读 其源码:

3、进一步学习?

本文并没有深入分析各种开源事件库里 Eventloop 的实现,感兴趣的小伙伴,可以看看结合下面这些教程,阅读它们的代码。

Unix 网络编程卷1 / 第16章 非阻塞式IO

感谢阅读,欢迎转发!

—— The End ——

推荐阅读:

专辑 | Linux 系统编程

专辑 | Linux 驱动开发

专辑 | Linux 内核品读

专辑 | 每天一点 C

专辑 | 开源软件

专辑 | Qt 入门

原文作者:吴伟东Jack

作品来源:老吴嵌入式

来源链接:

标签: #timertimeout