chromium android/linux/mac 中用libevent來做爲底層io檢測,即MessagePumpLibevent來實現io線程循環。
1 libevent 簡介(百度百科)
官網: http://libevent.org/
libevent是一個事件觸發的網絡庫,適用於windows、linux、bsd等多種平臺,內部使用select、epoll、kqueue等系統調用管理事件機制。根據libevent官方網站上公佈的數據統計,似乎也有着非凡的性能。libevent支持多線程編程,每個事件需要關聯到自己的event_base。libevent包括事件管理、緩存管理、DNS、HTTP、緩存事件幾大部分。事件管理包括各種IO(socket)、定時器、信號等事件;緩存管理是指evbuffer功能;DNS是libevent提供的一個異步DNS查詢功能;HTTP是libevent的一個輕量級http實現,包括服務器和客戶端。libevent也支持ssl,這對於有安全需求的網絡程序非常的重要,但是其支持不是很完善,比如http server的實現就不支持ssl。
2. libevent 簡單使用
http://www.open-open.com/lib/view/open1386510630330.html
1> timer事件
<span style="font-size:12px;">#include <stdio.h>
#include <iostream>
// libevent頭文件
#include <event.h>
using namespace std;
// 定時事件回調函數
void onTime(int sock, short event, void *arg)
{
cout << "Game Over!" << endl;
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
// 重新添加定時事件(定時事件觸發後默認自動刪除)
event_add((struct event*)arg, &tv);
}
int main()
{
// 初始化
event_init();
struct event evTime;
// 設置定時事件
evtimer_set(&evTime, onTime, &evTime);
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
// 添加定時事件
event_add(&evTime, &tv);
// 事件循環
event_dispatch();
return 0;
} </span>
2> io端口監聽
僞代碼
<span style="font-size:12px;">int main(void)
{
// 初始化base
base = event_base_new();
struct event evListen;
// 設置事件
event_set(&evListen, fd, EV_READ|EV_PERSIST, CallbackFunction, NULL);
// 設置爲base事件
event_base_set(base, &evListen);
// 添加事件
event_add(&evListen, NULL);
// 事件循環
event_base_dispatch(base);
return 0;
} </span>
3. libevent 事件循環
上述例子中,調用event_base_dispatch函數就進入了libevent事件循環,但真正的循環函數是event_base_loop。event_base_dispatch調用event_base_loop,其中flags參數爲0.
int event_base_loop(struct event_base *base, int flags);
該函數可以工作在3中模式下,有flags來區分不同的模式。libevent中定義了兩個宏來區別循環模式:
#define EVLOOP_ONCE 0x01
#define EVLOOP_NONBLOCK 0x02
默認情況下,event_base_loop()函數運行event_base直到其中沒有已經註冊的事件爲止。執行循環的時候,函數重複地檢查(多種 I/O多路複用技術: epoll、poll、dev/poll、select 和kqueue )是否有任何已經註冊的事件被觸發(比如說,讀事件的文件描述符已經就緒,可以讀取了;或者超時事件的超時時間即將到達)。如果有事件被觸發,函數標記被觸發的事件爲“激活的”,並且執行這些事件。
如果設置了EVLOOP_ONCE,循環將等待某些事件成爲激活的,執行激活的事件直到沒有更多的事件可以執行,然會返回。
如果設置了EVLOOP_NONBLOCK,循環不會等待事件被觸發:循環將僅僅檢測是否有事件已經就緒,可以立即觸發,如果有,則執行事件的回調。
chromium中使用了`EVLOOP_ONCE和EVLOOP_NONBLOCK
4. 多路複用封裝eventop
struct eventop {
const char *name;
void *(*init)(struct event_base *); // 初始化
int (*add)(void *, struct event *); // 註冊事件
int (*del)(void *, struct event *); // 刪除事件
int (*dispatch)(struct event_base *, void *, struct timeval *); // 事件分發
void (*dealloc)(struct event_base *, void *); // 註銷,釋放資源
/* set if we need to reinitialize the event base */
int need_reinit;
};
epoll、poll、dev/poll、select 和kqueue 都會實現這5個接口。
資料:
http://blog.csdn.net/sparkliang/article/details/4957667
http://www.cppblog.com/mysileng/archive/2013/02/04/197719.html