libevent
- 格式:docx
- 大小:328.62 KB
- 文档页数:32
libevent功能使用简介1. 介绍libevent是一个用来开发可扩展的网络服务器的事件通知函数库。
当一个文件描述符上的特定事件发生或是一个超时时间到达后,libev ent API提供一种执行回调函数的机制。
而且,libevent还支持基于信号或定期超时的回调功能。
libevent旨在替换在原有事件驱动网络服务器事件循环而设计的。
应用程序仅仅需要调用event_dispatch(),然后动态地添加或是移除事件就可以了,而不需要改变原有的事件循环。
目前,libevent支持/dev/poll,kqueue(2),select(2),p oll(2)和epoll(4)等高并发网络编程模型。
而它对实时信号的支持正处于实验性阶段。
内部的事件处理机制是完全独立于暴露出来的API的,并且新功能的加入并不需要重新设计应用程序,而是仅仅需要做一个简单的libevent更新即可。
因此,lievent允许可移植性的应用程序开发,并且能够提供适合特定操作系统的最具可扩展性的事件通知机制。
libevent同时也可用于多线程编程环境,更多说明请看Steve n Grimm的说明。
libevent可以在Linux,*BSD,Mac OS X,Sol aris和Windows系统上编译。
2. 标准用法每一个使用libevent的程序,都需要包含<event.h>头文件,并且需要传递-levent标志给连接器linker。
在使用任何库函数之前,需要先调用event_init()或者event_base_new()函数制执行一次li bevent库的初始化。
3. 事件通知对于每一个你想监视的文件描述符,你必须声明一个事件结构并且调用event_set()去初始化结构中的成员。
为了激活通知,你需要通过调用event_add()将该结构添加到监视事件列表。
只要是该事件存活,那么就需要保持该已allocated的事件结构,因此该事件结构需要在堆(heap)上申请。
Libevent是一个开源的事件通知库,用于在网络编程中处理事件驱动的程序。
它是一个轻量级的、高性能的库,广泛用于服务器软件的开发中。
在IPv6的网络环境下,Libevent同样可以发挥其强大的功能,本文将探讨Libevent在IPv6环境下的使用方法。
一、Libevent简介Libevent是一个基于事件驱动的网络编程库,支持跨评台(包括Unix/Linux、Windows等)和多种网络协议。
它提供了事件处理、定时器管理、信号处理等功能,可以帮助开发者编写高效的服务器程序。
Libevent使用简单,性能优异,深受广大开发者的喜爱。
二、IPv6概述IPv6是下一代的互联网协议,它是IPv4的后继者,为互联网用户提供了更多的IP位置区域空间,解决了IPv4位置区域短缺的问题。
IPv6的位置区域长度为128位,相较于IPv4的32位位置区域,拥有更大的位置区域空间和更好的路由选择,同时支持IPsec等安全性功能。
三、Libevent在IPv6环境中的使用在IPv6的网络环境下,Libevent同样可以发挥其强大的功能。
在使用Libevent进行网络编程时,我们需要注意以下几点:1. IPv6位置区域族在Libevent中,IPv6位置区域族使用的是AF_INET6。
当创建套接字时,需要指定位置区域族为AF_INET6,以便能够支持IPv6的通信。
示例代码如下:```struct sockaddr_in6 sin;memset(sin, 0, sizeof(sin));sin.sin6_family = AF_INET6;sin.sin6_port = htons(8080);sin.sin6_addr = in6addr_any;```2. 位置区域转换在IPv6环境下,我们可能需要将IPv6位置区域(如文本格式的IPv6位置区域)转换为网络字节序,或者将网络字节序的IPv6位置区域转换为文本格式。
libevent evthread_use_pthreads -回复libevent是一个开源的事件驱动网络库,它提供了一个高效的跨平台的事件驱动模型,用于构建可扩展的网络应用程序。
evthread_use_pthreads 是libevent库中的一个函数,它用于设置使用pthread线程库作为底层的多线程实现。
本文将深入探讨libevent库及其事件驱动模型以及evthread_use_pthreads函数的作用和用法。
一、libevent库和事件驱动模型简介libevent是一个轻量级、高性能、事件驱动的网络库,最初由Nick Mathewson于2000年开发,并在2002年发布。
它的设计目标是提供一个统一的、跨平台的接口,用于处理网络事件和I/O操作,以支持高并发的网络应用程序。
libevent库可以在多个操作系统上运行,包括Windows、Linux、BSD等。
libevent采用了事件驱动的编程模型,通过使用异步的、非阻塞的I/O操作和事件回调机制来处理网络事件。
在传统的阻塞式I/O模型中,每个连接都需要一个独立的线程或进程来处理,当同时有大量的连接时,会消耗大量的系统资源。
而在事件驱动模型中,通过一个主循环不断监听和分发事件,将连接的处理交给事件回调函数,可以大大提高系统的吞吐量和性能。
二、libevent库的特性和用途1. 高性能:libevent采用非阻塞I/O和事件回调机制,能够处理大量的并发连接,实现高性能的网络应用程序。
2. 跨平台:libevent可以在多个操作系统上运行,包括Windows、Linux、BSD、macOS等。
3. 支持多种网络协议:libevent支持多种常用的网络协议,如TCP、UDP、HTTP等,能够满足不同类型的网络应用需求。
4. 支持定时器:libevent提供了定时器功能,可以方便地实现定时任务的调度和执行。
5. 可扩展性:libevent的设计模式允许用户自定义事件源和事件处理器,以满足复杂应用的需求。
qt libevent编译Qt和libevent是两个不同的库,分别用于不同的领域。
Qt是一个跨平台的C++应用程序开发框架,而libevent是一个事件驱动的网络编程库。
下面将分别介绍它们的特点和用途。
一、Qt库Qt是由挪威Trolltech公司(现已被诺基亚收购)开发的,是一个跨平台的应用程序开发框架。
它提供了丰富的功能和工具,使开发者可以快速创建高性能的图形用户界面(GUI)应用程序。
Qt具有以下特点:1. 跨平台性:Qt可以在多个操作系统上运行,包括Windows、macOS、Linux等,大大简化了跨平台开发的难度。
2. 强大的图形界面设计工具:Qt提供了Qt Designer,一个直观易用的界面设计工具,开发者可以通过拖拽和放置组件的方式设计用户界面。
3. 丰富的组件库:Qt拥有丰富的组件库,包括按钮、文本框、列表框等,开发者可以直接使用这些组件来构建用户界面。
4. 高性能:Qt使用了一些优化技术,如信号槽机制和事件循环,以实现高效的事件处理和界面更新。
5. 支持多种编程语言:除了C++,Qt还支持其他编程语言,如Python和JavaScript,使开发者可以根据自己的喜好选择编程语言。
二、libevent库libevent是一个事件驱动的网络编程库,它提供了一种高效的方式来处理网络连接和事件。
libevent可以用于开发服务器程序、网络代理、网络爬虫等应用。
libevent具有以下特点:1. 轻量级:libevent是一个轻量级的库,仅依赖于标准C库,不需要其他第三方库的支持。
2. 高性能:libevent使用了事件驱动的方式来处理网络连接和事件,可以实现高并发和低延迟的网络通信。
3. 跨平台性:libevent可以在多个操作系统上运行,包括Windows、Linux、FreeBSD等。
4. 支持多种网络协议:libevent支持TCP、UDP、HTTP等多种网络协议,开发者可以根据需要选择合适的协议。
libevent编译
LibEVENT是一款跨平台的基于BSD下的高性能异步事件驱动库,用于解决异步编程难题。
它能够有效地执行异步I/O或时间事件,可极大提高程序的性能,使之变得优雅。
libevent既可以单独使用,也可以与应用程序(比如web服务器)进行集成,可是以模块的方式实现,做到最大的性能。
LibEvent的编译方法简单易行,有基于Linux、Windows、Mac、BSD等不同操作系统的编译工具。
编译分为configure-make-install三步:
首先,确定libevent的源码包路径,使用linux shell命令进行当前路径切换,cmd进行切换;
其次,执行configure脚本,这是一个自动构建libevent库所需的步骤,命令参数格式如./configure,此步负责生成makefile文件;
最后,执行make命令,此步负责根据makefile文件来编译库文件,编译完成后,安装对应的执行文件。
LibEvent的编译相对来说容易,但需要搭配系统环境,无法满足针对每一种操作系统进行定制。
因此,有时候我们可能需要重新编译libevent,以满足自己应用系统的需求,才能达到最佳性能。
标题:深入浅出-服务器高并发库libevent (一)1安装libevent是一个开源的高并发服务器开发包,官方地址/ libevent目前有两个版本一个是1.4系列版本,一个是2.0系列版本。
我们可以在官方网站上看到类似有个stable表示稳定版本。
libevent-1.4.15-stable.tar.gz对于初学者学习,建议从1.4版本学起。
在安装libevent之前先判断本电脑是否已经安装了通过指令ls -al /usr/lib|grep libevent如果没有任何信息则表示没有安装,有的话如果发现libevent是1.3以下版本,则可以同过执行rpm -e libevent —nodeps 进行卸载。
如果是其他操作系统使用其他对应卸载指令即可。
对于下好的tar包,通过tar -zxvf libevent-release-1.4.15-stable.tar.gz指令解压。
然后执行./configure命令,但是有的包可能没有configure文件,却存在一个autogen.sh 脚本,运行这个脚本。
(如果运行不起来请安装autoconf包)然后./configure–prefix=/usrmakesudo make install安装完之后执行ls -al /usr/lib/|grep libevent如果发现有libevent文件库存在就代表安装完毕。
2 简单的libevent服务器我们通过连接libevent库来进行管理libevent库,所以在使用gcc或者g++编译的时候最后需要加上-levent下面是一个简单的libevent服务器。
#include <stdio.h>#include <string.h>#include <iostream>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <unistd.h>#include <event.h>using namespace std;#define SERVER_ADDR "127.0.0.1"#define SERVER_PORT 8888// 事件basestruct event_base* base;// 读事件回调函数void onRead(int iCliFd, short iEvent, void *arg) {int iLen;char buf[1500];iLen = recv(iCliFd, buf, 1500, 0);if (iLen <= 0) {cout << "Client Close" << endl;// 连接结束(=0)或连接错误(<0),将事件删除并释放内存空间 struct event *pEvRead = (struct event*)arg; event_del(pEvRead);delete pEvRead;close(iCliFd);return;}buf[iLen] = 0;cout << "Client Info:" << buf << endl;struct bufferevent* buf_ev;buf_ev = bufferevent_new(iCliFd, NULL, NULL, NULL, NULL);buf_ev->wm_read.high = 4096;char MESSAGE[]="welcome to server..";bufferevent_write(buf_ev, MESSAGE, strlen(MESSAGE));}// 连接请求事件回调函数void onAccept(int iSvrFd, short iEvent, void *arg){int iCliFd;struct sockaddr_in sCliAddr;socklen_t iSinSize = sizeof(sCliAddr);iCliFd = accept(iSvrFd, (struct sockaddr*)&sCliAddr,&iSinSize);// 连接注册为新事件 (EV_PERSIST为事件触发后不默认删除)struct event *pEvRead = new event;event_set(pEvRead, iCliFd, EV_READ|EV_PERSIST, onRead, pEvRead);event_base_set(base, pEvRead);event_add(pEvRead, NULL);struct bufferevent* buf_ev;buf_ev = bufferevent_new(iCliFd, NULL, NULL, NULL, NULL); buf_ev->wm_read.high = 4096;char MESSAGE[]="welcome to server..";bufferevent_write(buf_ev, MESSAGE, strlen(MESSAGE));cout<<"a client connect:"<<iCliFd<<endl;}int main(){int iSvrFd;struct sockaddr_in sSvrAddr;memset(&sSvrAddr, 0, sizeof(sSvrAddr));sSvrAddr.sin_family = AF_INET;sSvrAddr.sin_addr.s_addr = inet_addr(SERVER_ADDR); sSvrAddr.sin_port = htons(SERVER_PORT);// 创建tcpSocket(iSvrFd),监听本机8888端口iSvrFd = socket(AF_INET, SOCK_STREAM, 0);bind(iSvrFd, (struct sockaddr*)&sSvrAddr,sizeof(sSvrAddr));listen(iSvrFd, 10);// 初始化basebase = (struct event_base*)event_init();struct event evListen;// 设置事件event_set(&evListen, iSvrFd, EV_READ|EV_PERSIST, onAccept, NULL);// 设置为base事件event_base_set(base, &evListen);// 添加事件event_add(&evListen, NULL);// 事件循环event_base_dispatch(base);return 0;}通过编译指令g++ server.cpp -o server -Wall -g -I ./ -levent得到可执行程序./server启动。
libevent和基于libevent的⽹络编程1 libevent介绍和安装介绍libevent是⼀个轻量级的基于事件驱动的⾼性能的开源⽹络库,并且⽀持多个平台,对多个平台的I/O复⽤技术进⾏了封装,当我们编译库的代码时,编译的脚本将会根据OS⽀持的处理事件机制,来编译相应的代码,从⽽在libevent接⼝上保持⼀致。
在当前的服务器上,⾯对的主要问题就是要能处理⼤量的连接。
⽽通过libevent这个⽹络库,我们就可以调⽤它的API来很好的解决上⾯的问题。
⾸先,可以来回顾⼀下,对这个问题的传统解决⽅法。
问题:如何处理多个客户端连接解决⽅案1:I/O复⽤技术这⼏种⽅式都是同步I/O,即当读写事件就绪,他们⾃⼰需要负责进⾏读写,这个读写过程是阻塞的,⽽异步I/O则不需要⾃⼰负责读写,只需要通知负责读写的程序就可以了。
循环假设当前我服务器有多个⽹络连接需要看管,那么我就循环遍历打开的⽹络连接的列表,来判断是否有要读取的数据。
这种⽅法的缺点很明显,那就是 1.速度缓慢(必须遍历所有的⽹络连接) 2.效率低(处理⼀个连接时可能发⽣阻塞,妨碍其他⽹络连接的检查和处理)select⽅式select对应于内核中的sys_select调⽤,sys_select⾸先将第⼆三四个参数指向的fd_set拷贝到内核,然后对每个被SET的描述符调⽤进⾏poll,并记录在临时结果中(fdset),如果有事件发⽣,select会将临时结果写到⽤户空间并返回;当轮询⼀遍后没有任何事件发⽣时,如果指定了超时时间,则select会睡眠到超时,睡眠结束后再进⾏⼀次轮询,并将临时结果写到⽤户空间,然后返回。
select返回后,需要逐⼀检查关注的描述符是否被SET(事件是否发⽣)。
(select⽀持的⽂件描述符数量太⼩了,默认是1024)。
poll⽅式poll与select不同,通过⼀个pollfd数组向内核传递需要关注的事件,故没有描述符个数的限制,pollfd中的events字段和revents分别⽤于标⽰关注的事件和发⽣的事件,故pollfd数组只需要被初始化⼀次。
libevent定时器工作原理1. 简介libevent是一个事件驱动的网络编程库,它提供了对I/O多路复用、定时器和信号处理等功能的封装。
其中,定时器是libevent中非常重要的一个组件,它可以用于实现各种定时任务,比如定时执行某个函数或发送心跳包等。
本文将详细介绍libevent定时器的工作原理,包括定时器的创建、设置回调函数、启动和停止定时器等过程。
同时,我们还会讨论libevent定时器的底层实现原理,以及如何处理定时器事件。
2. libevent定时器的创建在使用libevent定时器之前,我们首先需要创建一个定时器对象。
libevent提供了event_new函数来创建定时器对象,其函数原型如下:struct event *event_new(struct event_base *base, evutil_socket_t fd, short eve nts, event_callback_fn callback, void *arg);参数说明: - base:事件的基础结构体,表示事件所属的事件处理器。
- fd:定时器的文件描述符,由于定时器不与具体的文件描述符关联,因此可以传入-1。
- events:事件类型,定时器的事件类型为EV_TIMEOUT,表示定时器超时事件。
- callback:事件回调函数,当定时器超时时会调用该函数。
- arg:回调函数的参数。
通过调用event_new函数,我们可以得到一个定时器对象,接下来我们需要设置定时器的超时时间和回调函数。
3. libevent定时器的设置在创建定时器对象后,我们需要使用event_add函数来设置定时器的超时时间和回调函数,将定时器添加到事件处理器中。
int event_add(struct event *ev, const struct timeval *timeout);参数说明: - ev:定时器对象。
libevent 定时器工作原理libevent 定时器工作原理简介libevent是一个开源的事件驱动库,主要用于网络应用程序的开发。
其中,定时器是libevent的重要组成部分,它允许开发者在指定的时间间隔内执行某个任务或者回调函数。
工作原理libevent的定时器基于事件循环机制实现,主要包括以下几个步骤:1.创建一个事件循环对象,用于接收和处理事件。
2.创建一个定时器事件,并设置定时器回调函数。
3.将定时器事件添加到事件循环中。
4.启动事件循环,不断监听事件并执行相应的回调函数。
5.定时器触发后,事件循环会调用定时器回调函数进行处理。
6.重复上述步骤,直到不需要再使用定时器。
具体实现1. 创建事件循环对象在使用libevent定时器之前,首先需要创建一个事件循环对象,通过event_base_new()函数进行创建:struct event_base* base = event_base_new();2. 创建定时器事件使用event_new()函数创建一个定时器事件,并设置定时器回调函数和触发方式。
定时器回调函数是在定时器触发时执行的函数,开发者可以根据需求自定义回调函数。
struct event* timer_event = event_new(base, -1, EV_ PERSIST, timer_callback, NULL);3. 添加定时器事件使用event_add()函数将定时器事件添加到事件循环中,并设置定时器的触发时间间隔。
struct timeval tv;_sec = 1;_usec = 0;event_add(timer_event, &tv);4. 启动事件循环通过调用event_base_dispatch()函数启动事件循环,开始监听事件并执行相应的回调函数。
event_base_dispatch(base);5. 定时器触发当定时器的触发时间到达时,事件循环会自动调用定时器回调函数进行处理。
libevent源码深度剖析一——序幕张亮1 前言Libevent是一个轻量级的开源高性能网络库,使用者众多,研究者更甚,相关文章也不少。
写这一系列文章的用意在于,一则分享心得;二则对libevent代码和设计思想做系统的、更深层次的分析,写出来,也可供后来者参考。
附带一句:Libevent是用c语言编写的(MS大牛们都偏爱c语言哪),而且几乎是无处不函数指针,学习其源代码也需要相当的c语言基础。
2 Libevent简介上来当然要先夸奖啦,Libevent 有几个显著的亮点:事件驱动(event-driven),高性能;轻量级,专注于网络,不如ACE那么臃肿庞大;源代码相当精炼、易读;跨平台,支持Windows、Linux、*BSD和Mac Os;支持多种I/O多路复用技术,epoll、poll、dev/poll、select和kqueue等;支持I/O,定时器和信号等事件;注册事件优先级;Libevent已经被广泛的应用,作为底层的网络库;比如memcached、Vomit、Ny lon、Netchat等等。
Libevent当前的最新稳定版是1.4.13;这也是本文参照的版本。
3 学习的好处学习libevent有助于提升程序设计功力,除了网络程序设计方面外,Libevent的代码里有很多有用的设计技巧和基础数据结构,比如信息隐藏、函数指针、c语言的多态支持、链表和堆等等,都有助于提升自身的程序功力。
程序设计不止要了解框架,很多细节之处恰恰也是事关整个系统成败的关键。
只对libevent 本身的框架大概了解,那或许仅仅是一知半解,不深入代码分析,就难以了解其设计的精巧之处,也就难以为自己所用。
事实上Libevent本身就是一个典型的Reactor模型,理解Reactor模式是理解libevent 的基石;因此下一节将介绍典型的事件驱动设计模式——Reactor模式。
libevent源码深度剖析二——Reactor模式张亮前面讲到,整个libevent本身就是一个Reactor,因此本节将专门对Reactor模式进行必要的介绍,并列出libevnet中的几个重要组件和Reactor的对应关系,在后面的章节中可能还会提到本节介绍的基本概念。
1 Reactor的事件处理机制首先来回想一下普通函数调用的机制:程序调用某函数?函数执行,程序等待?函数将结果和控制权返回给程序?程序继续处理。
Reactor释义“反应堆”,是一种事件驱动机制。
和普通函数调用的不同之处在于:应用程序不是主动的调用某个API完成处理,而是恰恰相反,Reactor逆置了事件处理流程,应用程序需要提供相应的接口并注册到Reactor上,如果相应的时间发生,Reactor将主动调用应用程序注册的接口,这些接口又称为“回调函数”。
使用Libevent也是想Libevent框架注册相应的事件和回调函数;当这些时间发声时,Libevent会调用这些回调函数处理相应的事件(I/O读写、定时和信号)。
用“好莱坞原则”来形容Reactor再合适不过了:不要打电话给我们,我们会打电话通知你。
举个例子:你去应聘某xx公司,面试结束后。
“普通函数调用机制”公司HR比较懒,不会记你的联系方式,那怎么办呢,你只能面试完后自己打电话去问结果;有没有被录取啊,还是被据了;“Reactor”公司HR就记下了你的联系方式,结果出来后会主动打电话通知你:有没有被录取啊,还是被据了;你不用自己打电话去问结果,事实上也不能,你没有HR的留联系方式。
2 Reactor模式的优点Reactor模式是编写高性能网络服务器的必备技术之一,它具有如下的优点:1)响应快,不必为单个同步时间所阻塞,虽然Reactor本身依然是同步的;2)编程相对简单,可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销;3)可扩展性,可以方便的通过增加Reactor实例个数来充分利用CPU资源;4)可复用性,reactor框架本身与具体事件处理逻辑无关,具有很高的复用性;3 Reactor模式框架使用Reactor模型,必备的几个组件:事件源、Reactor框架、多路复用机制和事件处理程序,先来看看Reactor模型的整体框架,接下来再对每个组件做逐一说明。
1)事件源Linux上是文件描述符,Windows上就是Socket或者Handle了,这里统一称为“句柄集”;程序在指定的句柄上注册关心的事件,比如I/O事件。
2)event demultiplexer——事件多路分发机制由操作系统提供的I/O多路复用机制,比如select和epoll。
程序首先将其关心的句柄(事件源)及其事件注册到event demultiplexer上;当有事件到达时,event demultiplexer会发出通知“在已经注册的句柄集中,一个或多个句柄的事件已经就绪”;程序收到通知后,就可以在非阻塞的情况下对事件进行处理了。
对应到libevent中,依然是select、poll、epoll等,但是libevent使用结构体eventop 进行了封装,以统一的接口来支持这些I/O多路复用机制,达到了对外隐藏底层系统机制的目的。
3)Reactor——反应器Reactor,是事件管理的接口,内部使用event demultiplexer注册、注销事件;并运行事件循环,当有事件进入“就绪”状态时,调用注册事件的回调函数处理事件。
对应到libevent中,就是event_base结构体。
一个典型的Reactor声明方式view plainc opy to clipboardprint?1.class Reactor2.{3.public:4.int register_handler(Event_Handler *pHandler, int event);5.int remove_handler(Event_Handler *pHandler, int event);6.void handle_events(timeval *ptv);7.// ...8.};4)Event Handler——事件处理程序事件处理程序提供了一组接口,每个接口对应了一种类型的事件,供Reactor在相应的事件发生时调用,执行相应的事件处理。
通常它会绑定一个有效的句柄。
对应到libevent中,就是event结构体。
下面是两种典型的Event Handler类声明方式,二者互有优缺点。
view plainc opy to clipboardprint?1.class Event_Handler2.{3.public:4.virtual void handle_read() = 0;5.virtual void handle_write() = 0;6.virtual void handle_timeout() = 0;7.virtual void handle_close() = 0;8.virtual HANDLE get_handle() = 0;9.// ...10.};11.class Event_Handler12.{13.public:14.// events maybe read/write/timeout/close .etc15.virtual void handle_events(int events) = 0;16.virtual HANDLE get_handle() = 0;17.// ...18.};4 Reactor事件处理流程前面说过Reactor将事件流“逆置”了,那么使用Reactor模式后,事件控制流是什么样子呢?可以参见下面的序列图。
5 小结上面讲到了Reactor的基本概念、框架和处理流程,对Reactor有个基本清晰的了解后,再来对比看libevent就会更容易理解了,接下来就正式进入到libevent的代码世界了,加油!libevent源码深度剖析三——libevent基本使用场景和事件流程张亮1 前言学习源代码该从哪里入手?我觉得从程序的基本使用场景和代码的整体处理流程入手是个不错的方法,至少从个人的经验上讲,用此方法分析libevent是比较有效的。
2 基本应用场景基本应用场景也是使用libevnet的基本流程,下面来考虑一个最简单的场景,使用livevent 设置定时器,应用程序只需要执行下面几个简单的步骤即可。
1)首先初始化libevent库,并保存返回的指针struct event_base * base = event_init();实际上这一步相当于初始化一个Reactor实例;在初始化libevent后,就可以注册事件了。
2)初始化事件event,设置回调函数和关注的事件evtimer_set(&ev, timer_cb, NULL);事实上这等价于调用event_set(&ev, -1, 0, timer_cb, NULL);event_set的函数原型是:void event_set(struct event *ev, int fd, short event, void (*cb)(int, short, void *), void *arg)ev:执行要初始化的event对象;fd:该event绑定的“句柄”,对于信号事件,它就是关注的信号;event:在该fd上关注的事件类型,它可以是EV_READ, EV_WRITE, EV_SIGNAL;cb:这是一个函数指针,当fd上的事件event发生时,调用该函数执行处理,它有三个参数,调用时由event_base负责传入,按顺序,实际上就是event_set时的fd, event和arg;arg:传递给cb函数指针的参数;由于定时事件不需要fd,并且定时事件是根据添加时(event_add)的超时值设定的,因此这里event也不需要设置。
这一步相当于初始化一个event handler,在libevent中事件类型保存在event结构体中。
注意:libevent并不会管理event事件集合,这需要应用程序自行管理;3)设置event从属的event_baseevent_base_set(base, &ev);这一步相当于指明event要注册到哪个event_base实例上;4)是正式的添加事件的时候了event_add(&ev, timeout);基本信息都已设置完成,只要简单的调用event_add()函数即可完成,其中timeout是定时值;这一步相当于调用Reactor::register_handler()函数注册事件。
5)程序进入无限循环,等待就绪事件并执行事件处理event_base_dispatch(base);3 实例代码上面例子的程序代码如下所示1.struct event ev;2.struct timeval tv;3.void time_cb(int fd, short event, void *argc)4.{5. printf("timer wakeup\n");6. event_add(&ev, &tv); // reschedule timer7.}8.int main()9.{10.struct event_base *base = event_init();11. _sec = 10; // 10s period12. _usec = 0;13. evtimer_set(&ev, time_cb, NULL);14. event_add(&ev, &tv);15. event_base_dispatch(base);16.}4 事件处理流程当应用程序向libevent注册一个事件后,libevent内部是怎么样进行处理的呢?下面的图就给出了这一基本流程。