首页 > 其他分享 >libev 库使用

libev 库使用

时间:2022-10-19 17:05:12浏览次数:35  
标签:EV libev watcher 使用 ev TYPE event loop

 1、libev所实现的功能就是一个强大的reactor,可能notity事件主要包括下面这些:

  • ev_io            // IO可读可写
  • ev_stat         // 文件属性变化
  • ev_async          // 激活线程
  • ev_signal                       // 信号处理
  • ev_timer                        // 定时器
  • ev_periodic                   // 周期任务
  • ev_child                         // 子进程状态变化
  • ev_fork                          // 开辟进程
  • ev_cleanup                   // event loop退出触发事件
  • ev_idle                          // 每次event loop空闲触发事件
  • ev_embed                     // TODO(zhangyan04):I have no idea.
  • ev_prepare                    // 每次event loop之前事件
  • ev_check                      // 每次event loop之后事件
说明定义
EV_P event parameter            struct ev_loop* loop
EV_P_             EV_P,
EV_A event argument           loop
EV_A_             EV_A,

2、struct ev_loop结构体

event_loop允许动态创建和销毁,并且允许绑定自定义数据

struct ev_loop

struct ev_loop * ev_loop_new (unsigned int flags);
void ev_loop_destroy (EV_P);
void ev_set_userdata (EV_P_ void *data);
void *ev_userdata (EV_P);

我们这里主要关注一下flags.这里面主要是选择使用什么backend来进行poll操作,可以选择的有:

EVBACKEND_SELECT
EVBACKEND_POLL
EVBACKEND_EPOLL         // 通常我们选择这个
EVBACKEND_KQUEUE
EVBACKEND_DEVPOLL
EVBACKEND_PORT
但是还有三个比较重要选项:

EVFLAG_NOINOTIFY          // 不适用inofity调用来使用ev_stat.这样可以减少fd使用。
EVFLAG_SIGNALFD          // 使用signalfd来检测信号是否发生,同样这样可以减少fd使用。

大部分时候我们使用EVFLAG_AUTO(0)一般就足够满足需求了,
从代码角度来看如果支持epoll的话那么首先会选择epoll.
因为在watcher的回调函数里面是可以知道当前event_loop的,
这样就可以获得自定义数据。然后我们看看这个event_loop如何运行和停止的

void ev_run (EV_P_ int flags);

void ev_break (EV_P_ int how);

同样我们这里比较关注flags和how这两个参数。flags有下面这几个:

  • 0.通常这是我们想要的,每次轮询在poll都会等待一段时间然后处理pending事件。
  • EVRUN_NOWAIT.运行一次,在poll时候不会等待。这样效果相当于只是处理pending事件。
  • EVRUN_ONCE.运行一次,但是在poll时候会等待,然后处理pending事件。

而how有下面这几个:

  • EVBREAK_ONE.只是退出一次ev_run这个调用。通常来说使用这个就可以了。
  • EVBREAK_ALL.退出所有的ev_run调用。这种情况存在于ev_run在pengding处理时候会递归调用。

在event_loop里面我们还关心一件事情,就是每次event_loop轮询的时间长短。
通常来说这个不会是太大问题,但是在高性能情况下面我们需要设置

void ev_set_io_collect_interval (EV_P_ ev_tstamp interval);

void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval);

 

3、Watcher

然后我们关心一下EventHandler.在libev下面watcher相当于EventHandler这么一个概念,通常里面会绑定fd回调函数以及我们需要关注的事件。然后一旦触发事件之后会触发我们使用的回调函数,回调函数参数通常有reactor,watcher以及触发的事件。这里不打算重复文档里面的watcher 相关的内容和对应的API,但是对于某些内容的话可能会提到并且附带一些注释。之前我们还是看看通用过程,这里使用TYPE区分不同类型watcher.

typedef void (*)(struct ev_loop *loop, ev_TYPE *watcher, int revents) callback; // callback都是这种类型
ev_init (ev_TYPE *watcher, callback); // 初始化watcher
ev_TYPE_set (ev_TYPE *watcher, [args]); // 设置watcher
ev_TYPE_init (ev_TYPE *watcher, callback, [args]); // 通常使用这个函数最方便,初始化和设置都在这里
ev_TYPE_start (loop, ev_TYPE *watcher); // 注册watcher
ev_TYPE_stop (loop, ev_TYPE *watcher); // 注销watcher
ev_set_priority (ev_TYPE *watcher, int priority); // 设置优先级
ev_feed_event (loop, ev_TYPE *watcher, int revents); // 这个做跨线程通知非常有用,相当于触发了某个事件。

bool ev_is_active (ev_TYPE *watcher); // watcher是否active.
bool ev_is_pending (ev_TYPE *watcher); // watcher是否pending.
int ev_clear_pending (loop, ev_TYPE *watcher); // 清除watcher pending状态并且返回事件

wacther的状态有下面这么几种:

  • initialiased. 调用init函数初始化
  • active. 调用start进行注册
  • pending. 已经触发事件但是没有处理
  • inactive. 调用stop注销。这个状态等同于initialised这个状态。

其实关于每个watcher具体是怎么实现的没有太多意思,因为大部分现有代码都差不多。会在下一节说说内部数据结构是怎么安排的,了解内部数据结构以及过程之后很多问题就可以避免了,比如"The special problem of disappearing file descriptors"这类问题。

 

标签:EV,libev,watcher,使用,ev,TYPE,event,loop
From: https://www.cnblogs.com/ink-white/p/16806949.html

相关文章

  • 安卓 WebView使用说明
    WebVies类介绍[WebResourceRequest]添加于API21,封装了一个Web资源的请求信息,包含:请求地址,请求方法,请求头,是否主框架,是否用户点击,是否重定向-[WebResourceResponse]封装了一......
  • 使用ERP|仓库管理系统,ERP|库存管理软件的诸多好处
    库存管理是保持供应链平稳运行的必要过程。当您有一个装满存储和客户订单的仓库时,有效的库存管理可以让您更好地组织和简化您的日常流程。做得好,可以获得利益,包括降低资......
  • Keytool 工具的介绍与使用
    Keytool工具的介绍与使用keytool简介Keytool是一个Java数据证书的管理工具,Keytool将密钥(key)和证书(certificates)存在一个称为keystore的文件中。keystore文......
  • 怎么在uboot下使用通用GPIO接口
    一:在uboot下的defconfig打开如下配置CONFIG_DM=yCONFIG_DM_GPIO=yCONFIG_DWAPB_GPIO=yCONFIG_CMD_GPIO=y二:重新编译u-boot后会生成cmd:gpio在板端执行"gpiostat......
  • 使用gulp对sass文件进行打包压缩遇到的小问题
    使用constsass=require('gulp-sass')导入了sass转换模块,但在执行gulp命令时报错了---------------------------Errorinplugin"gulp-sass"Message:gulp-sassnol......
  • JavaScript字符串一些方法使用charAt、charCodeAt、replace、split、substr
    charAt():根据下标返回字符1<script>2letstr='abcde';3console.log(str.charAt(1));//返回结果:b4</script> charCodeAt():根据下标返回字......
  • 使用docker exec进入Docker容器
    除了上面几种做法之外,docker在1.3.X版本之后还提供了一个新的命令exec用于进入容器,这种方式相对更简单一些,下面我们来看一下该命令的使用:$sudodockerexec--help接......
  • Dinky的使用——parquet2mysql
     需求:将parquet数据文件同步数据到mysql数据库需要通过创建parquet格式的hive表,从hdfs中将数据文件下载,我这里提前做好了 一、添加依赖包在dinky的plugins目录和flin......
  • R.swift 的使用 swift
    导入方式:https://github.com/mac-cain13/R.swift 调用方式:letview=UIImageView(image:R.image.right_arrow()) right_arrow为导入到工程中图片的名......
  • Limit讨论,K8s 使用 CPU Limit 后,服务响应变成龟速...
    你应当小心设定k8s中负载的CPUlimit,太小的值会给你的程序带来额外的、无意义的延迟,太大的值会带来过大的爆炸半径,削弱集群的整体稳定性。 1.request和limitk8s的......