Libevent

Libevent是一个用C语言编写的、轻量级的开源高性能事件通知库,主要有以下几个亮点:

事件驱动( event-driven),高性能;

轻量级,专注于网络,不如 ACE 那么臃肿庞大;

源代码相当精炼、易读;

跨平台,支持 Windows、 Linux、 *BSD 和 Mac Os;

支持多种 I/O 多路复用技术, epoll、 poll、 dev/poll、 select 和 kqueue 等;

支持 I/O,定时器和信号等事件;注册事件优先级。

基于“事件”异步通信模型 ---依赖回调

注册异步事件,检测异步事件,根据事件的触发先后顺序,调用相对应回调函数处理事件。

处理的事件包括:网络 io 事件、定时事件以及信号事件。这三个事件驱动着服务器的运行。

1. 网络io事件:
    linux:epoll、poll、select
    mac:kqueue
    window:iocp
    
2. 定时事件:
    红黑树
    最小堆:二叉树、四叉树
    跳表
    时间轮
    
3. 信号事件

下载网址:https://libevent.org/

源码包安装: 参考readme文件

tar zxvf libevent-2.1.12-stable.tar.gz  //解压

cd libevent-2.1.12-stable/   //进入解压目录

./configure       //检查安装环境 生成makefile

make              //生成 .o 和 可执行文件

make install     //将必要的资源cp至系统指定目录

cd sample/        //进入 sample 目录,运行demo验证库安装使用情况

gcc hello-world.c -o hello -levent   //编译使用库的.c时,需添加 -l选项+库名

./server      //执行

./nc 127.1 9995    //另起一终端执行

若执行 ./server 提示错误:

./hello: error while loading shared libraries: libevent-2.1.so.7: cannot open shared object file: No such file or directory

产生原因:在运行时,程序无法找到libevent-2.1.so.7这个动态库,因为该动态库在默认安装时,存放的路径在/usr/local/lib下,不在系统的默认查找路径内。

解决方法:

第一步:

sudo echo "/usr/local/lib" >> /etc/ld.so.conf

//无报错则直接转第二步

//若报错(bash: /etc/ld.so.conf: Permission denied)

vim /etc/ld.so.conf    //在文件末尾加上 /usr/local/lib

第二步:

sudo ldconfig   //更新使配置生效

1)libevent框架

头文件:#include<event2/event.h>

1、创建 event_base (乐高底座)

  • struct event_base *event_base_new(void);
  • struct event_base *base = event_base_new();

2、创建 事件event

  • 常规事件 event --> event_new();
  • 带缓冲区的事件bufferevent --> bufferevent_socket_new();

3、将事件 添加到 base

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

4、循环监听事件满足

  • int event_base_dispatch(base);
    • event_base_dispatch(base)

5、释放 event_base

  • void event_base_free(base);

2)常规事件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()的返回值

myread.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/stat.h>
#include <event2/event.h>  

void sys_err(const char *str)
{
	perror(str);
	exit(1);
}

void read_cb(evutil_socket_t fd, short what, void *arg)
{
	char buf[1024] = {0};
	int len = read(fd, buf, sizeof(buf));

	printf("what = %s, read from write : %s\n", 
			what & EV_READ ? "read YES" : "read NO", buf);
	sleep(1);

	return ;
}


int main(int argc, char *argv[])
{
	//创建 fifo
	unlink("testfifo");
	mkfifo("testfifo", 0644);

	//打开 fifo 的读端
	int fd = open("testfifo", O_RDONLY | O_NONBLOCK);
	if(fd == -1){
		sys_err("open err");
	}

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

	//创建事件
	struct event *ev = NULL;
	
	//添加事件到 event_base 上
	/*struct event *event_new(struct event_base *base, evutil_socket_t fd, 
                        short what, event_callback_fn cb, void *arg)*/
	ev = event_new(base, fd, EV_READ | EV_PERSIST, read_cb, NULL);

	//添加事件到 event_base 上
	//int event_add(struct event *ev, const struct timeval *tv);
	event_add(ev, NULL);

	//启动循环
	//int event_base_disppatch(struct event_base *base);
	event_base_dispatch(base);     // 相当于包含 while(1)


	//销毁 event_base
	event_base_free(base);

	return 0;
}

mywrite.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/stat.h>
#include <event2/event.h>  

void sys_err(const char *str)
{
	perror(str);
	exit(1);
}

void write_cb(evutil_socket_t fd, short what, void *arg)
{
	char buf[] = "hello libevent";

	write(fd, buf, strlen(buf));

	sleep(1);

	return ;
}


int main(int argc, char *argv[])
{
	//打开 fifo 的写端
	int fd = open("testfifo", O_RDONLY | O_NONBLOCK);
	if(fd == -1){
		sys_err("open err");
	}

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

	//创建 事件对象
	struct event *ev = NULL;
	
	//添加事件到 event_base 上
	/*struct event *event_new(struct event_base *base, evutil_socket_t fd, 
                        short what, event_callback_fn cb, void *arg)*/
	ev = event_new(base, fd, EV_WRITE | EV_PERSIST, write_cb, NULL);

	//添加事件到 event_base 上
	//int event_add(struct event *ev, const struct timeval *tv);
	event_add(ev, NULL);

	//启动循环
	//int event_base_disppatch(struct event_base *base);
	event_base_dispatch(base);     // 相当于包含 while(1)


	//销毁 event_base
	event_base_free(base);

	return 0;
}

编译:

gcc myread.c -o myread -levent

gcc mywrite.c -o mywrite -levent
④未决和非未决

未决:有资格被处理,但还没有被处理

非未决:没有资格被处理

posted @ 2023-08-22 17:33  洋綮  阅读(29)  评论(0)    收藏  举报