【Libevent】Libevent学习笔记(二):创建event_base
00. 目錄
文章目錄
- 00. 目錄
- 01. 簡(jiǎn)介
- 02. 創(chuàng)建默認(rèn)的event_base
- 03. 創(chuàng)建復(fù)雜的event_base
- 3.1 event_config_new函數(shù)
- 3.2 event_base_new_with_config函數(shù)
- 3.3 event_config_free函數(shù)
- 3.4 event_config_avoid_method函數(shù)
- 3.5 event_config_require_features函數(shù)
- 3.6 event_config_set_flag函數(shù)
- 3.7 event_config_set_num_cpus_hint函數(shù)
- 04. 檢查*event_base*的后端
- 4.1 event_get_supported_methods函數(shù)
- 4.2 event_base_get_method函數(shù)
- 4.3 event_base_get_features函數(shù)
- 05. 釋放event_base
- 06. 設(shè)置*event_base*的優(yōu)先級(jí)
- 07. fork之后重新初始化base
- 08. 參考
01. 簡(jiǎn)介
? 使用libevent函數(shù)之前需要分配一個(gè)或者多個(gè)event_base結(jié)構(gòu)體。每個(gè)event_base結(jié)構(gòu)體持有一個(gè)事件集合,可以檢測(cè)以確定哪個(gè)事件是激活的。
? 如果設(shè)置event_base使用鎖,則可以安全地在多個(gè)線(xiàn)程中訪(fǎng)問(wèn)它。然而,其事件循環(huán)只能運(yùn)行在一個(gè)線(xiàn)程中。如果需要用多個(gè)線(xiàn)程檢測(cè)IO,則需要為每個(gè)線(xiàn)程使用一個(gè)event_base。
每個(gè)event_base都有一種用于檢測(cè)哪種事件已經(jīng)就緒的“方法”,或者說(shuō)后端。可以識(shí)別的方法有:
- select
- poll
- epoll
- kqueue
- devpoll
- evport
- win32
? 用戶(hù)可以用環(huán)境變量禁止某些特定的后端。比如說(shuō),要禁止kqueue后端,可以設(shè)置EVENT_NOKQUEUE環(huán)境變量。如果要用編程的方法禁止后端,請(qǐng)看下面關(guān)于event_config_avoid_method()的說(shuō)明。
02. 創(chuàng)建默認(rèn)的event_base
event_base_new()函數(shù)分配并且返回一個(gè)新的具有默認(rèn)設(shè)置的event_base。函數(shù)會(huì)檢測(cè)環(huán)境變量,返回一個(gè)到event_base的指針。如果發(fā)生錯(cuò)誤,則返回NULL。選擇各種方法時(shí),函數(shù)會(huì)選擇操作系統(tǒng)支持的最快方法。
函數(shù)相關(guān)說(shuō)明:
/*** Create and return a new event_base to use with the rest of Libevent.** @return a new event_base on success, or NULL on failure.** @see event_base_free(), event_base_new_with_config()*/struct event_base *event_base_new(void); 功能: 創(chuàng)建一個(gè)默認(rèn)屬性的struct event_base對(duì)象 參數(shù):無(wú) 返回值:成功: 返回struct event_base結(jié)構(gòu)體指針失敗: NULLevent_base_new()函數(shù)聲明在*<event2/event.h>中,首次出現(xiàn)在libevent 1.4.3*版。
大多數(shù)情況下, 我們創(chuàng)建默認(rèn)的event_base就可以滿(mǎn)足我們的需求。
03. 創(chuàng)建復(fù)雜的event_base
要對(duì)取得什么類(lèi)型的event_base有更多的控制,就需要使用event_config。
event_config是一個(gè)容納event_base配置信息的不透明結(jié)構(gòu)體。需要event_base時(shí),將event_config傳遞給event_base_new_with_config()。
相關(guān)頭文件: libevent-2.0.22-stable/include/event2/event.h
3.1 event_config_new函數(shù)
/**Allocates a new event configuration object.The event configuration object can be used to change the behavior ofan event base.@return an event_config object that can be used to store configuration, orNULL if an error is encountered.@see event_base_new_with_config(), event_config_free(), event_config */ struct event_config *event_config_new(void); 功能:分配一個(gè)event_config 參數(shù):無(wú) 返回值:成功:返回struct event_config結(jié)構(gòu)體指針失敗:NULL3.2 event_base_new_with_config函數(shù)
/**Initialize the event API.Use event_base_new_with_config() to initialize a new event base, takingthe specified configuration under consideration. The configuration objectcan currently be used to avoid certain event notification mechanisms.@param cfg the event configuration object@return an initialized event_base that can be used to registering events,or NULL if no event base can be created with the requested event_config.@see event_base_new(), event_base_free(), event_init(), event_assign() */ struct event_base *event_base_new_with_config(const struct event_config * cfg); 功能:初始化一個(gè)新的event_base 參數(shù):cfg event_config結(jié)構(gòu)體指針 返回值:成功:返回一個(gè)可以用于注冊(cè)事件的初始化好的event_base對(duì)象失敗:NULL3.3 event_config_free函數(shù)
/**Deallocates all memory associated with an event configuration object@param cfg the event configuration object to be freed. */ void event_config_free(struct event_config *cfg); 功能:釋放event_config對(duì)象 參數(shù):cfg event_config_new函數(shù)的返回值 返回值:無(wú)3.4 event_config_avoid_method函數(shù)
/**Enters an event method that should be avoided into the configuration.This can be used to avoid event mechanisms that do not support certainfile descriptor types, or for debugging to avoid certain eventmechanisms. An application can make use of multiple event bases toaccommodate incompatible file descriptor types.@param cfg the event configuration object@param method the name of the event method to avoid@return 0 on success, -1 on failure. */ int event_config_avoid_method(struct event_config *cfg, const char *method); 功能:可以通過(guò)名字讓libevent避免使用特定的可用后端。 參數(shù):cfg event_config對(duì)象指針method 避免使用特定的后端返回值:成功 0失敗 -13.5 event_config_require_features函數(shù)
/**Enters a required event method feature that the application demands.Note that not every feature or combination of features is supportedon every platform. Code that requests features should be preparedto handle the case where event_base_new_with_config() returns NULL, as in:<pre>event_config_require_features(cfg, EV_FEATURE_ET);base = event_base_new_with_config(cfg);if (base == NULL) {// We can't get edge-triggered behavior here.event_config_require_features(cfg, 0);base = event_base_new_with_config(cfg);}</pre>@param cfg the event configuration object@param feature a bitfield of one or more event_method_feature values.Replaces values from previous calls to this function.@return 0 on success, -1 on failure.@see event_method_feature, event_base_new_with_config() */ int event_config_require_features(struct event_config *cfg, int feature); 功能:設(shè)置libevent不使用不能提供所有指定特征的后端。 參數(shù):cfg event_config結(jié)構(gòu)體指針feature 指定特征的后端 返回值:成功 0失敗 -1指定特征的后端
/**A flag used to describe which features an event_base (must) provide.Because of OS limitations, not every Libevent backend supports everypossible feature. You can use this type withevent_config_require_features() to tell Libevent to only proceed if yourevent_base implements a given feature, and you can receive this type fromevent_base_get_features() to see which features are available. */ enum event_method_feature {/** Require an event method that allows edge-triggered events with EV_ET. */EV_FEATURE_ET = 0x01,/** Require an event method where having one event triggered among* many is [approximately] an O(1) operation. This excludes (for* example) select and poll, which are approximately O(N) for N* equal to the total number of possible events. */EV_FEATURE_O1 = 0x02,/** Require an event method that allows file descriptors as well as* sockets. */EV_FEATURE_FDS = 0x04 };event_config_require_features()可識(shí)別的特征值有:
-
EV_FEATURE_ET:要求支持邊沿觸發(fā)的后端。
-
EV_FEATURE_O1:要求添加、刪除單個(gè)事件,或者確定哪個(gè)事件激活的操作是O(1)復(fù)雜度的后端。
-
EV_FEATURE_FDS:要求支持任意文件描述符,而不僅僅是套接字的后端。
3.6 event_config_set_flag函數(shù)
/*** Sets one or more flags to configure what parts of the eventual event_base* will be initialized, and how they'll work.** @see event_base_config_flags, event_base_new_with_config()**/ int event_config_set_flag(struct event_config *cfg, int flag); 功能:設(shè)置讓libevent在創(chuàng)建event_base時(shí)設(shè)置一個(gè)或者多個(gè)將在下面介紹的運(yùn)行時(shí)標(biāo)志。 參數(shù):cfg event_config結(jié)構(gòu)體指針flag 指定的標(biāo)志 返回值:成功 0失敗 -1對(duì)應(yīng)的標(biāo)志有
/**A flag passed to event_config_set_flag().These flags change the behavior of an allocated event_base.@see event_config_set_flag(), event_base_new_with_config(),event_method_feature*/ enum event_base_config_flag {/** Do not allocate a lock for the event base, even if we havelocking set up. */EVENT_BASE_FLAG_NOLOCK = 0x01,/** Do not check the EVENT_* environment variables when configuringan event_base */EVENT_BASE_FLAG_IGNORE_ENV = 0x02,/** Windows only: enable the IOCP dispatcher at startupIf this flag is set then bufferevent_socket_new() andevconn_listener_new() will use IOCP-backed implementationsinstead of the usual select-based one on Windows.*/EVENT_BASE_FLAG_STARTUP_IOCP = 0x04,/** Instead of checking the current time every time the event loop isready to run timeout callbacks, check after each timeout callback.*/EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08,/** If we are using the epoll backend, this flag says that it issafe to use Libevent's internal change-list code to batch upadds and deletes in order to try to do as few syscalls aspossible. Setting this flag can make your code run faster, butit may trigger a Linux bug: it is not safe to use this flagif you have any fds cloned by dup() or its variants. Doing sowill produce strange and hard-to-diagnose bugs.This flag can also be activated by settnig theEVENT_EPOLL_USE_CHANGELIST environment variable.This flag has no effect if you wind up using a backend other thanepoll.*/EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10 };event_config_set_flag()可識(shí)別的選項(xiàng)值有:
-
EVENT_BASE_FLAG_NOLOCK:不要為event_base分配鎖。設(shè)置這個(gè)選項(xiàng)可以為event_base節(jié)省一點(diǎn)用于鎖定和解鎖的時(shí)間,但是讓在多個(gè)線(xiàn)程中訪(fǎng)問(wèn)event_base成為不安全的。
-
EVENT_BASE_FLAG_IGNORE_ENV:選擇使用的后端時(shí),不要檢測(cè)EVENT_*環(huán)境變量。使用這個(gè)標(biāo)志需要三思:這會(huì)讓用戶(hù)更難調(diào)試你的程序與libevent的交互。
-
EVENT_BASE_FLAG_STARTUP_IOCP:僅用于Windows,讓libevent在啟動(dòng)時(shí)就啟用任何必需的IOCP分發(fā)邏輯,而不是按需啟用。
-
EVENT_BASE_FLAG_NO_CACHE_TIME:不是在事件循環(huán)每次準(zhǔn)備執(zhí)行超時(shí)回調(diào)時(shí)檢測(cè)當(dāng)前時(shí)間,而是在每次超時(shí)回調(diào)后進(jìn)行檢測(cè)。注意:這會(huì)消耗更多的CPU時(shí)間。
-
EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST:告訴libevent,如果決定使用epoll后端,可以安全地使用更快的基于changelist的后端。epoll-changelist后端可以在后端的分發(fā)函數(shù)調(diào)用之間,同樣的fd多次修改其狀態(tài)的情況下,避免不必要的系統(tǒng)調(diào)用。但是如果傳遞任何使用dup()或者其變體克隆的fd給libevent,epoll-changelist后端會(huì)觸發(fā)一個(gè)內(nèi)核bug,導(dǎo)致不正確的結(jié)果。在不使用epoll后端的情況下,這個(gè)標(biāo)志是沒(méi)有效果的。也可以通過(guò)設(shè)置EVENT_EPOLL_USE_CHANGELIST環(huán)境變量來(lái)打開(kāi)epoll-changelist選項(xiàng)。
注意:
設(shè)置event_config,請(qǐng)求OS不能提供的后端是很容易的。比如說(shuō),對(duì)于libevent 2.0.1-alpha,在Windows中是沒(méi)有O(1)后端的;在Linux中也沒(méi)有同時(shí)提供EV_FEATURE_FDS和EV_FEATURE_O1特征的后端。如果創(chuàng)建了libevent不能滿(mǎn)足的配置,event_base_new_with_config()會(huì)返回NULL。
3.7 event_config_set_num_cpus_hint函數(shù)
函數(shù)當(dāng)前僅在Windows上使用IOCP時(shí)有用,雖然將來(lái)可能在其他平臺(tái)上有用。這個(gè)函數(shù)告訴event_config在生成多線(xiàn)程event_base的時(shí)候,應(yīng)該試圖使用給定數(shù)目的CPU。注意這僅僅是一個(gè)提示:event_base使用的CPU可能比你選擇的要少。
/*** Records a hint for the number of CPUs in the system. This is used for* tuning thread pools, etc, for optimal performance. In Libevent 2.0,* it is only on Windows, and only when IOCP is in use.** @param cfg the event configuration object* @param cpus the number of cpus* @return 0 on success, -1 on failure.*/ int event_config_set_num_cpus_hint(struct event_config *cfg, int cpus); 功能:設(shè)置試圖給定數(shù)目的CPU。 參數(shù):cfg event_config結(jié)構(gòu)體指針cpus CPU數(shù)量 返回值:成功 0失敗 -1官方參考示例:
struct event_config *cfg; struct event_base *base; int i;/* My program wants to use edge-triggered events if at all possible. SoI'll try to get a base twice: Once insisting on edge-triggered IO, andonce not. */ for (i=0; i<2; ++i) {cfg = event_config_new();/* I don't like select. */event_config_avoid_method(cfg, "select");if (i == 0)event_config_require_features(cfg, EV_FEATURE_ET);base = event_base_new_with_config(cfg);event_config_free(cfg);if (base)break;/* If we get here, event_base_new_with_config() returned NULL. Ifthis is the first time around the loop, we'll try again withoutsetting EV_FEATURE_ET. If this is the second time around theloop, we'll give up. */ }總述:
以上函數(shù)和類(lèi)型在<event2/event.h>中聲明。
EVENT_BASE_FLAG_IGNORE_ENV標(biāo)志首次出現(xiàn)在2.0.2-alpha版本。event_config_set_num_cpus_hint()函數(shù)是2.0.7-rc版本新引入的。本節(jié)的其他內(nèi)容首次出現(xiàn)在2.0.1-alpha版本。
04. 檢查event_base的后端
有時(shí)候需要檢查event_base支持哪些特征,或者當(dāng)前使用哪種方法。
4.1 event_get_supported_methods函數(shù)
/**Gets all event notification mechanisms supported by Libevent.This functions returns the event mechanism in order preferred byLibevent. Note that this list will include all backends thatLibevent has compiled-in support for, and will not necessarily checkyour OS to see whether it has the required resources.@return an array with pointers to the names of support methods.The end of the array is indicated by a NULL pointer. If anerror is encountered NULL is returned. */ const char **event_get_supported_methods(void); 功能:獲取當(dāng)前系統(tǒng)支持的后端。 參數(shù):無(wú) 返回值:成功 返回一個(gè)指針,指向libevent支持的方法名字?jǐn)?shù)組失敗 NULL參考程序:
#include <stdio.h> #include <event.h>int main(void) {int i = 0;const char **pstr = event_get_supported_methods();if (NULL == pstr){ printf("event_get_supported_methods failed...\n"); return 1;} printf("Libevent version: %s\n", event_get_version());for (i = 0; NULL != pstr[i]; i++) { printf("\t%s\n", pstr[i]); } return 0; }執(zhí)行結(jié)果:
注意:
這個(gè)函數(shù)返回libevent被編譯以支持的方法列表。然而libevent運(yùn)行的時(shí)候,操作系統(tǒng)可能不能支持所有方法。比如說(shuō),可能OS X版本中的kqueue的bug太多,無(wú)法使用。
4.2 event_base_get_method函數(shù)
/**Get the kernel event notification mechanism used by Libevent.@param eb the event_base structure returned by event_base_new()@return a string identifying the kernel event mechanism (kqueue, epoll, etc.)*/ const char *event_base_get_method(const struct event_base *base); 功能:獲取當(dāng)前base使用的后端。 參數(shù):base event_base對(duì)象 返回值:成功 返回一個(gè)指針,指向使用的后端。失敗 NULL。參考示例:
#include <stdio.h> #include <event.h>int main(void) {struct event_base *base = NULL;//創(chuàng)建一個(gè)對(duì)象base = event_base_new();if (NULL == base){ printf("event_base_new failded...\n");return 1;} printf("methods: %s\n", event_base_get_method(base));//釋放對(duì)象event_base_free(base);return 0; }執(zhí)行結(jié)果:
4.3 event_base_get_features函數(shù)
/**Return a bitmask of the features implemented by an event base. Thiswill be a bitwise OR of one or more of the values ofevent_method_feature@see event_method_feature*/ int event_base_get_features(const struct event_base *base); 功能:返回event_base支持的特征的比特掩碼。 參數(shù):base event_base對(duì)象 返回值:成功 特征的比特掩碼。失敗 0。參考代碼:
#include <stdio.h> #include <event.h>int main(void) {struct event_base *base = NULL;enum event_method_feature f;base = event_base_new();if (NULL == base){printf("event_base_new failded...\n");return 1;}f = event_base_get_features(base);if ((f & EV_FEATURE_ET))printf(" Edge-triggered events are supported.");if ((f & EV_FEATURE_O1))printf(" O(1) event notification is supported.");if ((f & EV_FEATURE_FDS))printf(" All FD types are supported.");printf("\n");event_base_free(base);return 0; }執(zhí)行結(jié)果:
05. 釋放event_base
使用完event_base之后,使用event_base_free()進(jìn)行釋放。
/**Deallocate all memory associated with an event_base, and free the base.Note that this function will not close any fds or free any memory passedto event_new as the argument to callback.@param eb an event_base to be freed*/ void event_base_free(struct event_base *base); 功能:釋放base 參數(shù):base event_base對(duì)象 返回值:無(wú)參考代碼:
#include <stdio.h> #include <event.h>int main(void) {struct event_base *base = NULL;//創(chuàng)建base對(duì)象base = event_base_new();if (NULL == base){ printf("event_base_new failded...\n");return 1;} //釋放baseevent_base_free(base);return 0; }注意:
這個(gè)函數(shù)不會(huì)釋放當(dāng)前與event_base關(guān)聯(lián)的任何事件,或者關(guān)閉他們的套接字,或者釋放任何指針。
event_base_free()定義在*<event2/event.h>中,首次由libevent 1.2*實(shí)現(xiàn)。
06. 設(shè)置event_base的優(yōu)先級(jí)
? libevent支持為事件設(shè)置多個(gè)優(yōu)先級(jí)。然而,event_base默認(rèn)只支持單個(gè)優(yōu)先級(jí)。可以調(diào)用event_base_priority_init*()設(shè)置event_base的優(yōu)先級(jí)數(shù)目。
event_base_priority_init函數(shù)
/**Set the number of different event prioritiesBy default Libevent schedules all active events with the same priority.However, some time it is desirable to process some events with a higherpriority than others. For that reason, Libevent supports strict priorityqueues. Active events with a lower priority are always processed beforeevents with a higher priority.The number of different priorities can be set initially with theevent_base_priority_init() function. This function should be calledbefore the first call to event_base_dispatch(). Theevent_priority_set() function can be used to assign a priority to anevent. By default, Libevent assigns the middle priority to all eventsunless their priority is explicitly set.Note that urgent-priority events can starve less-urgent events: afterrunning all urgent-priority callbacks, Libevent checks for more urgentevents again, before running less-urgent events. Less-urgent eventswill not have their callbacks run until there are no events more urgentthan them that want to be active.@param eb the event_base structure returned by event_base_new()@param npriorities the maximum number of priorities@return 0 if successful, or -1 if an error occurred@see event_priority_set()*/ int event_base_priority_init(struct event_base *base, int pri); 功能:設(shè)置base優(yōu)先級(jí) 參數(shù):base event_base對(duì)象pri 這個(gè)數(shù)目至少是1。每個(gè)新的事件可用的優(yōu)先級(jí)將從0(最高)pri-1(最低)。 返回值:成功 0失敗 -1/** Largest number of priorities that Libevent can support. */ #define EVENT_MAX_PRIORITIES 256 常量EVENT_MAX_PRIORITIES表示pri的上限。調(diào)用這個(gè)函數(shù)時(shí)為pri給出更大的值是錯(cuò)誤的。注意:
必須在任何事件激活之前調(diào)用這個(gè)函數(shù),最好在創(chuàng)建event_base后立刻調(diào)用。
關(guān)于示例,請(qǐng)看event_priority_set的文檔。
默認(rèn)情況下,與event_base相關(guān)聯(lián)的事件將被初始化為具有優(yōu)先級(jí)pri/ 2。event_base_priority_init()函數(shù)定義在<event2/event.h>中,從libevent 1.0版就可用了。
07. fork之后重新初始化base
不是所有事件后端都在調(diào)用fork()之后可以正確工作。所以,如果在使用fork()或者其他相關(guān)系統(tǒng)調(diào)用啟動(dòng)新進(jìn)程之后,希望在新進(jìn)程中繼續(xù)使用event_base,就需要進(jìn)行重新初始化。
event_reinit函數(shù)
/**Reinitialize the event base after a forkSome event mechanisms do not survive across fork. The event base needsto be reinitialized with the event_reinit() function.@param base the event base that needs to be re-initialized@return 0 if successful, or -1 if some events could not be re-added.@see event_base_new() */ int event_reinit(struct event_base *base); 功能:重新初始化base 參數(shù):base event_base對(duì)象 返回值:成功 0失敗 -1官方參考示例
struct event_base *base = event_base_new();/* ... add some events to the event_base ... */if (fork()) {/* In parent */continue_running_parent(base); /*...*/ } else {/* In child */event_reinit(base);continue_running_child(base); /*...*/ }event_reinit()定義在*<event2/event.h>中,在libevent 1.4.3-alpha*版中首次可用。
08. 參考
相關(guān)書(shū)籍: http://www.wangafu.net/~nickm/libevent-book/Ref2_eventbase.html
官方參考網(wǎng)站: https://www.monkey.org/~provos/libevent/doxygen-2.0.1/index.html
總結(jié)
以上是生活随笔為你收集整理的【Libevent】Libevent学习笔记(二):创建event_base的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【Linux系统编程】进程常用调度算法
- 下一篇: 程序员智力面试题(一)