libevent库
libevent库
开源。精简。跨平台(Windows、Linux、maxos、unix)。专注于网络通信。
源码包安装: 参考 README、readme
./configure 检查安装环境 生成 makefile
make 生成 .o 和 可执行文件
sudo make install 将必要的资源cp置系统指定目录。
进入 sample 目录,运行demo验证库安装使用情况。
编译使用库的 .c 时,需要加 -levent 选项。
库名 libevent.so --> /usr/local/lib 查看的到。
注意:libevent.so 所在目录/usr/local/lib 不是系统目录,即动态链接器不会找到,执行是会报错找不到动态库
解决方法:1. vim /etc/ld.so.conf
2. sudo ldconfig
特性:
基于“事件”异步通信模型。--- 回调。
libevent框架:
1. 创建 event_base (乐高底座)
struct event_base *event_base_new(void);
struct event_base *base = event_base_new();
2. 创建 事件evnet
常规事件 event --> event_new();
bufferevent --> bufferevent_socket_new();
3. 将事件 添加到 base上
int event_add(struct event *ev, const struct timeval *tv)
4. 循环监听事件满足
int event_base_dispatch(struct event_base *base);
event_base_dispatch(base);
5. 释放 event_base
event_base_free(base);
创建事件event:
struct event *ev;
struct event *event_new(struct event_base *base,evutil_socket_t fd,short what,event_callback_fn cb; void *arg);
base: event_base_new()返回值。
fd: 绑定到 event 上的 文件描述符
what:对应的事件(r、w、e)
EV_READ 一次 读事件
EV_WRTIE 一次 写事件
EV_PERSIST 持续触发。 结合 event_base_dispatch 函数使用,生效。
cb:一旦事件满足监听条件,回调的函数。
typedef void (*event_callback_fn)(evutil_socket_t fd, short, void *)
arg: 回调的函数的参数。
返回值:成功创建的 event
添加事件到 event_base
int event_add(struct event *ev, const struct timeval *tv);
ev: event_new() 的返回值。
tv:NULL
从event_base上摘下事件 【了解】
int event_del(struct event *ev);
ev: event_new() 的返回值。
销毁事件
int event_free(struct event *ev);
ev: event_new() 的返回值。
未决和非未决:
非未决: 没有资格被处理
未决: 有资格被处理,但尚未被处理
event_new --> event ---> 非未决 --> event_add --> 未决 --> dispatch() && 监听事件被触发 --> 激活态
--> 执行回调函数 --> 处理态 --> 非未决 event_add && EV_PERSIST --> 未决 --> event_del --> 非未决
练习:使用libevent库编写程序,监听管道读写 管道检测的写缓冲区有空间写就触发事件
read_fifo.c
#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("read event: %s \n", what & EV_READ ? "Yes" : "No");
printf("data len = %d, buf = %s\n", len, buf);
sleep(1);
}
int main(int argc, const char* argv[])
{
unlink("myfifo");
mkfifo("myfifo", 0664);
int fd = open("myfifo", O_RDONLY);
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;
}
write_fifo.c
#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};
static int num = 0;
sprintf(buf, "hello,world-%d\n", num++);
write(fd, buf, strlen(buf)+1);
sleep(1);
}
int main(int argc, const char* argv[])
{
int fd = open("myfifo", O_WRONLY);
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 | EV_PERSIST, write_cb, NULL);
event_add(ev, NULL);
event_base_dispatch(base);
event_free(ev);
event_base_free(base);
close(fd);
return 0;
}