libevent--快速入門


libevent--快速入門

一.簡介

libevent是一個c語言寫的事件驅動庫,輕量級,專注於網絡,跨平台特性好,支持多種 I/O 多路復用.支持I/O,定時器和信號等事件,允許設置注冊事件優先級.

二.基本使用場景和事件流程

(1)初始化事件根基(槽)

struct event_base *event_base_new(void);
struct event_base *event_init(void);
  • event_base_new()函數分配並且返回一個新的具有默認設置的event_base.
  • event_init() 會調用event_base_new()創建一個event_base,並以此初始化一個全局的變量current_base .

例:

struct event_base *base = event_init();

(2)初始化事件event,設置回調函數和關注的事件,並關聯對應的事件根基(槽)event_base

typedef void (*event_callback_fn)(evutil_socket_t, short, void*);

struct event *event_new(struct event_base *, evutil_socket_t, short, 
                        event_callback_fn, void *);

int event_assign(struct event *, struct event_base *, evutil_socket_t, short, event_callback_fn, void *);

void event_set(struct event *ev, int fd, short events, 
               event_callback_fn, void *arg);
void event_base_set(struct event_base *,struct event*);
  • event_assign()的作用就是把給定的event類型對象的每一個成員賦予一個指定的值。

  • event_new()的實現其實是間接的調用的event_assign(),首先調用mm_malloc分配一塊內存,然后調用event_assign來給event類型的對象各個成員賦值。

  • event_set() 使用指定的句柄、關注的事件、事件發生時的回調函數、回調函數的額外參數,初始化設置struct event結構對象,綁定到全局current_base,設置此event結構對象的優先級,默認為current_base中總有限級數的一半

  • event_base_set() 將事件綁定到事件根基,即設置event從屬的event_base,指明event注冊到哪個event_base實例上

    例:

//SIGINT 信號事件初始化
//假定已創建事件根基struct event_base *base 
//方式一:
struct event sigint_ev;
event_assign(&sigint_ev,base,SIGINT, EV_SIGNAL | EV_PERSIST,sigint_cb,NULL);
//方式二:
struct event sigint_ev ;
event_set(&sigint_ev, SIGINT, EV_SIGNAL | EV_PERSIST, sigint_cb, NULL);
event_base_set(base, &sigint_ev);
//方式三:
struct event *sigint_ev;
sigint_ev = event_new(base,SIGINT,EV_SIGNAL | EV_PERSIST, sigint_cb, NULL);
//方式四:
struct event* sigint_ev = (struct event*)malloc(sizeof(struct event));
//sigint_ev檢測非空和置零后,用event_assign 或者event_set + event_base_set 初始化事件.

定時器事件:

#define evtimer_set(ev, cb, arg)    event_set(ev, -1, 0, cb, arg)

信號事件:

#define evsignal_new(base,signum,cb,arg) \
	event_new(base,signum,EV_SIGNAL|EV_PERSIST,cb,arg)

(3)添加事件,將事件變成未決態,即,將event加入到event_base中,等待監聽

void event_add(struct event* ,struct timeval *);

(4)程序進入無限循環,事件根基event_base開始工作,對注冊的event進行監聽.若注冊的事件的對應事件類型觸發,或者超時,會自動觸發event對應的回調函數執行

void event_base_dispatch(struct event_base *);
void event_base_loop(struct event_base *,int );

三.入門例子:

文件:test.c

編譯:

gcc -o test test.c -levent

代碼:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <event.h>
#include <sys/time.h>
#include <signal.h>
#include <string.h>
#define BUF_SIZE 1024

typedef struct{
	struct event *ev;
	char *buf;
	struct timeval *tv;
}rw_st;

void wr_cb(int fd, short event, void *arg);
void rd_cb(int fd, short event, void *arg);

struct event_base *base = NULL;
//定時事件
struct timeval tv;
struct event time_ev;
void time_cb(int fd, short event, void *arg)
{
	printf("time_cb : 5s timer wakeup\n");
	event_add(&time_ev,&tv);
}

//標准輸入 讀事件
//輸入一行,把讀事件刪掉,添加寫事件
void rd_cb(int fd,short event, void *arg)
{
	if(event & EV_TIMEOUT){
		printf("io read time out(2s)!\n");
		return ;
	}
	rw_st* rd_st = (rw_st*)arg;
	int len = read(fd, rd_st->buf, BUF_SIZE);
	rd_st->buf[len-1] = '\0';
	printf("rd_cb (stdin): %s \n",rd_st->buf);
	
	event_del(rd_st->ev);
	event_set(rd_st->ev, STDOUT_FILENO,  EV_WRITE | EV_PERSIST,
					wr_cb,(void*)rd_st);
	event_add(rd_st->ev,NULL);
}

//標准輸出 寫事件
//輸出,把寫事件刪掉,添加讀事件,邊寫邊讀
void wr_cb(int fd, short event, void *arg)
{
	rw_st *wr_st = (rw_st*)arg;
	printf("wr_cb (stdout): %s\n",wr_st->buf);
	memset(wr_st->buf,0,BUF_SIZE);
	event_del(wr_st->ev);
	event_set(wr_st->ev, STDIN_FILENO, EV_READ | EV_PERSIST,
					rd_cb, (void*)wr_st);
	event_add(wr_st->ev,wr_st->tv);
}

//SIGINT 信號事件
void sigint_cb(int fd, short event, void *arg)
{
	struct timeval tv_1s = {1,0};
	printf("SIGINT : EXIT IN 1s\n");
	event_base_loopexit(base,&tv_1s);
}

//SIGHUB 信號事件
void sighup_cb(int fd, short event, void *arg)
{
	printf("SIGHUP: EXIT AT ONCE\n");
	event_base_loopbreak(base);
}

int main()
{
	printf("pid = %ld\n",getpid());
	base = event_init();
	//定時器
	tv.tv_sec = 5;
	tv.tv_usec = 0;
	evtimer_set(&time_ev, time_cb, NULL);//一次性,默認全局的current_base
// event_set(&time_ev,-1,0,time_cb,NULL);

//	event_base_set(base, &time_ev);  //可省,在這里current_base等同base
	event_add(&time_ev,&tv);

	//io 讀事件  指針 event_new
	char buf[1024] = {0};
	struct timeval io_tv = {2,0};
	rw_st *rd_st = (rw_st*)malloc(sizeof(rw_st));
	memset(rd_st,0,sizeof(rw_st));

	struct event *io_ev = (struct event*)malloc(sizeof(struct event));
	memset(io_ev,0,sizeof(struct event));
	
	rd_st->ev = io_ev;
	rd_st->buf = buf;
	rd_st->tv = &io_tv;
	event_assign(rd_st->ev,base,STDIN_FILENO,
					EV_TIMEOUT | EV_READ | EV_PERSIST,rd_cb,(void*)rd_st);
	event_add(rd_st->ev,rd_st->tv);

	//SIGINT 信號事件
	struct event sigint_ev;

	event_assign(&sigint_ev,base,SIGINT, EV_SIGNAL | EV_PERSIST,sigint_cb,NULL);
//	event_set(&sigint_ev, SIGINT, EV_SIGNAL | EV_PERSIST, 
//											sigint_cb, NULL);
	//event_base_set(base, &sigint_ev);
	event_add(&sigint_ev,NULL);
  
//	struct event *sigint_ev = event_new(base,SIGINT,
//			 EV_SIGNAL | EV_PERSIST, sigint_cb, NULL);
//	event_add(sigint_ev,NULL);

	//SIGHUP 信號事件  
	//測試: $ kill -SIGHUP pid
	struct event *sighup_ev;
	sighup_ev = evsignal_new(base, SIGHUP, sighup_cb, NULL);	
	event_add(sighup_ev,NULL);

	event_base_dispatch(base);
	//event_base_loop(base,0);
	
	event_free(sighup_ev);
	event_base_free(base);
	free(rd_st);

	printf("EXIT\n");
	return 0;
}

原創所有,轉載注明原文出處.若有錯誤,歡迎指正,共同學習,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM