1、概述

libevent是一个C语言编写的、轻量级开源高性能事件通知库。作为底层网络库,已经被广泛应用(如:memcached、Vomit、Nylon、Netchat等)。主要有以下几个亮点:

  • 事件驱动(event-driven)
  • 高性能
  • 轻量级,专注网络。
  • 源码精炼,易读
  • 跨平台
  • 支持多种I/O多路复用技术,如epoll、poll、dev/poll、select、kqueue等。
  • 支持I/O,定时器和信号等事件
  • 注册事件优先级

官网地址:https://libevent.org/

2、框架介绍

1)event_base 创建与释放

// 创建event_base
struct event_base* base = event_base_new()
// 释放event_base_free
event_base_free(struct event_base* base);

2)事件创建与释放

调用event_new()函数之后,新事件处于已初始化和非未决状态。

// 创建新事件
struct event *event_new(
struct event_base *base,
evutil_socket_t fd, - // 文件描述符 - int **底层是对epollin与epollout的封装**
short what,
event_callback_fn cb, // 事件的处理回调函数
void *arg //回调函数传参
);
// 事件的处理回调函数
typedef void (*event_callback_fn)(evutil_socket_t, short, void *);
// short what
#define EV_TIMEOUT 0x01 // 已淘汰(忽略)
#define EV_READ 0x02
#define EV_WRITE 0x04
#define EV_SIGNAL 0x08 //libevent封装了信号相关的操作 SIGNAL
#define EV_PERSIST 0x10 // 持续触发
#define EV_ET 0x20 // 边沿模式

最后需要event_free进行释放。

// 创建event_free
void event_free(struct event *event);

3)event_add()函数

创建事件之后,再将其添加到event_base之前,实际上是不能对其做任何操作的。所以需要使用event_add将事件添加到event_base上去。此时状态由非未决事件->未决事件。

// event_add
int event_add(
struct event *ev,
const struct timeval *tv
);

函数调用成功返回0,失败返回-1。

4)event_base_dispatch()函数

最后,使用event_base_dispatch函数添加事件循环。

// event_base_dispatch(简化版event_base_loop())
int event_base_dispatch(struct event_base* base);
//等同于没有设置标志的 event_base_loop ( )
//将一直运行,直到没有已经注册的事件了,或者调用 了event_base_loopbreak()或者 event_base_loopexit()为止

5)event_base_loop()函数

// event_base_loop()
int event_base_loop(struct event_base *base, int flags);
//正常退出返回0, 失败返回-1 //flages
#define EVLOOP_ONCE 0x01
//事件只会被触发一次
//事件没有被触发, 阻塞等
#define EVLOOP_NONBLOCK 0x02
//非阻塞 等方式去做事件检测
//不关心事件是否被触发了
#define EVLOOP_NO_EXIT_ON_EMPTY 0x04
//没有事件的时候, 也不退出轮询检测

6)event_base_loopexit()函数

执行当前后退出。

//如果 event_base 当前正在执行激活事件的回调 ,它将在执行完当前正在处理的事件后立即退出
int event_base_loopexit(
struct event_base *base,
const struct timeval *tv
);
//参数struct timeval *tv
struct timeval {
long tv_sec;
long tv_usec;
};

7)event_base_loopbreak()函数

立即退出循环

//让event_base 立即退出循环
int event_base_loopbreak(struct event_base *base);
//返回值: 成功 0, 失败 -1

8)Demo

用例(采用fifo通信方式,不带缓冲区操作)

/*************************************************************************
> File Name: read_fifi.c
> Author:
> Mail:
> Created Time: 2021年04月19日 星期一 10时24分57秒
************************************************************************/ #include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
#include<fcntl.h>
#include<event2/event.h> //读取回调函数
void read_cb(evutil_socket_t fd,short what,void *arg)
{
//读管道
char buf[1024] = {0};
int len = read(fd,buf,sizeof(buf));
printf("data len = %d ,buf = %s\n" ,len,buf);
printf("read event: %s\n",what &EV_READ ? "Yes":"No");//对what 类型对判断
} int main()
{
unlink("libeventfifo");
//创建有名管道
mkfifo("libeventfifo",0664);
//open File int fd = open("libeventfifo",O_RDONLY | O_NONBLOCK); if(fd == -1)
{
perror("open error");
exit(1);
}
//读管道
struct event_base* base = NULL;
base = event_base_new(); //创建事件
struct event* ev = NULL;
ev = event_new(base,fd,EV_READ | EV_PERSIST,read_cb,NULL); // 添加事件
event_add(ev,NULL); //事件循环
event_base_dispatch(base); //释放资源
event_free(ev); event_base_free(base);
close(fd);
return 0 ;
}
/*************************************************************************
> File Name: write_fifi.c
> Author:
> Mail:
> Created Time: 2021年04月19日 星期一 10时24分43秒
************************************************************************/ #include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
#include<fcntl.h>
#include<event2/event.h> //读取回调函数
void write_cb(evutil_socket_t fd,short what,void *arg)
{
//写管道
char buf[1024] = {0};
int len = read(fd,buf,sizeof(buf));
static int num = 999;
sprintf(buf,"hello world == %d \n" ,num);
write(fd,buf,strlen(buf)+1);
} int main()
{
int fd = open("libeventfifo",O_WRONLY | O_NONBLOCK);
if(fd == -1)
{
perror("open error");
exit(1);
}
struct event_base * base = NULL;
base = event_base_new(); struct event* ev = NULL; ev = event_new(base,fd,EV_WRITE,write_cb,NULL); event_add(ev,NULL); event_base_dispatch(base); //释放资源
event_free(ev); event_base_free(base);
close(fd);
return 0 ;
}

用gcc 分别编译文件:

gcc write_fifi.c -o write -levent
gcc read_fifi.c -o read -levent

最后分别执行程序:

./read
./write

最新文章

  1. [VB.NET]Dictionary类
  2. html&amp;css&amp;js随笔-问题集锦
  3. Spring AOP实现方式一【附源码】
  4. 运用MyEclipse插件(link方式注意点)
  5. 校验 MD5 值
  6. 文件查找和比较命令 来自: http://man.linuxde.net/find
  7. 201521123054 《Java程序设计》第13周学习总结
  8. 大数据 --&gt; MapReduce原理与设计思想
  9. 使用GDB调试STL容器
  10. 轻松学习UML之用例图,时序图
  11. Serializable 和Parcelable 的区别
  12. uva 1232
  13. MyBatis3 入门学习指南
  14. webpack 创建vue项目过程中遇到的问题和解决方法
  15. 对象回收过程?线程池执行过程? map原理?集合类关系?synchronized 和 volatile ? 同一个类的方法事务传播控制还有作用吗?java 锁
  16. 【Linux】 基于centos7.2 安装 LAMP
  17. DevExpress中Tile Application窗体的模型架构图
  18. nginx重写链接
  19. unicode and utf-8
  20. Python 中的map函数,filter函数,reduce函数

热门文章

  1. 1057 - Collecting Gold
  2. Rainbond通过插件整合ELK/EFK,实现日志收集
  3. vue使用v-chart图表出现的问题
  4. 生成对抗网络GAN与DCGAN的理解
  5. 使用 Eclipse 创建一个静态的登录页面
  6. 基于MCRA-OMLSA的语音降噪(三):实现(续)
  7. SpringCloud使用汇总Config
  8. 初识python: 生成器并行(做包子,吃包子)
  9. 在使用django admin的后台搜索时报错
  10. Limiting Command Size