日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Libevent(1)— 簡(jiǎn)介、編譯、配置

系統(tǒng) 3118 0

轉(zhuǎn)自:http://name5566.com/4190.html

?

參考文獻(xiàn)列表:
http://www.wangafu.net/~nickm/libevent-book/

此文編寫(xiě)的時(shí)候,使用到的 Libevent 為 2.0.21

Libevent 之跨平臺(tái)

在處理大量 SOCKET 連接時(shí),使用 select 并不高效。各個(gè)系統(tǒng)都提供了處理大量 SOCKET 連接時(shí)的解決方案:

  1. Linux 下的 epoll()
  2. BSD 下的 kqueue()
  3. Solaris 下的 evports
  4. Windows 下的 IOCP

由于各個(gè)平臺(tái)使用了不同的接口,那么我們需要編寫(xiě)跨平臺(tái)的高性能異步程序時(shí)就需要做一層跨平臺(tái)封裝。
這個(gè)時(shí)候 Libevent 就成為一個(gè)較好的選擇,其最底層 API(event 和 event_base API)為各個(gè)平臺(tái)實(shí)現(xiàn)高性能異步程序提供了一致的接口。

Libevent 2 提供的 bufferevent 接口,一方面簡(jiǎn)化了編程的難度,另一方面保證了在 Windows 和 Unix 上都很高效。

一些基本的概念

  1. event 會(huì)綁定文件描述符、回調(diào)函數(shù)并表示一個(gè)或者多個(gè)條件(例如,文件描述符可以讀或者寫(xiě)了、發(fā)生了超時(shí)等)。event 表示的條件如果被觸發(fā)了,那么 event 會(huì)變?yōu)榛钴S的,它綁定的回調(diào)函數(shù)就會(huì)被執(zhí)行
  2. event_base 用于持有一組 event 并進(jìn)行事件循環(huán),event_base 會(huì)存在一個(gè)后端(也叫做方法),常見(jiàn)的后端包括 epoll、kqueue 等

Libevent 的結(jié)構(gòu)

組件:

  1. evutil 用于抽象不同的平臺(tái)的網(wǎng)絡(luò)(基礎(chǔ)的)實(shí)現(xiàn)
  2. event、event_base 為 Libevent 的核心,為不同的平臺(tái)下基于事件的非阻塞 I/O 提供了一套抽象的接口
  3. bufferevent 對(duì) Libevent 的基于事件的核心的封裝。應(yīng)用程序的讀寫(xiě)請(qǐng)求是基于緩沖區(qū)的
  4. evbuffer 為 bufferevent 實(shí)現(xiàn)的緩沖區(qū)
  5. evhttp 一個(gè)簡(jiǎn)單的 HTTP client/server 的實(shí)現(xiàn)
  6. evdns 一個(gè)簡(jiǎn)單的 DNS client/server 的實(shí)現(xiàn)
  7. evrpc 一個(gè)簡(jiǎn)單的 RPC 實(shí)現(xiàn)

庫(kù):

  1. libevent_core 包括 util、event_base、evbuffer、bufferevent
  2. libevent_extra 包括 HTTP、DNS、RPC
  3. libevent 此庫(kù)由于歷史原因而存在,不要使用它
  4. libevent_pthreads 此庫(kù)為基于 pthread 的線程和鎖的實(shí)現(xiàn)
  5. libevent_openssl 此庫(kù)通過(guò) openssl 和 bufferevent 提供了加密通訊

頭文件:
所有的公用頭文件位于 event2 目錄中。

編譯 Libevent 庫(kù)

Linux 下編譯的方式為(詳細(xì)見(jiàn) README):

  1. $ ./ configure
  2. $ make

常用的 configure 標(biāo)志有:

  1. -- disable - shared 只編譯靜態(tài)庫(kù)
  2. -- disable - openssl 關(guān)閉 OpenSSL 加密支持

Windows 下編譯的方式為:

  1. nmake / f Makefile . nmake

需要注意的是,雖然官方提供了此 makefile,但是此文件尚未編寫(xiě)完善(詳見(jiàn) Makefile.nmake 的注釋)
編譯完成之后,需要將 WIN32-Code 目錄加入到 VS 的 include paths 中去

設(shè)置 Libevent 庫(kù)

在具體的介紹之前,這里首先需要明確的一點(diǎn)是,我們總是先設(shè)置 Libevent,然后才去使用 Libevent。

關(guān)于輸出日志的設(shè)置

Libevent 的日志信息默認(rèn)被寫(xiě)入 stderr(標(biāo)準(zhǔn)錯(cuò)誤),我們可以提供自己的日志處理函數(shù)給 Libevent:

  1. // 日志的類型
  2. #define EVENT_LOG_DEBUG 0
  3. #define EVENT_LOG_MSG 1
  4. #define EVENT_LOG_WARN 2
  5. #define EVENT_LOG_ERR 3
  6. ?
  7. // 日志處理函數(shù)原型
  8. // severity 參數(shù)對(duì)應(yīng)了上面的各種日志類型
  9. typedef void (* event_log_cb )( int severity , const char * msg );
  10. ?
  11. // 設(shè)置一個(gè)新的日志處理函數(shù)
  12. void event_set_log_callback ( event_log_cb cb );

設(shè)置日志處理函數(shù)的范例:

  1. #include <event2/event.h>
  2. #include <stdio.h>
  3. ?
  4. static void discard_cb ( int severity , const char * msg )
  5. {
  6. // 此函數(shù)不做任何事情
  7. }
  8. ?
  9. static FILE * logfile = NULL ;
  10. static void write_to_file_cb ( int severity , const char * msg )
  11. {
  12. const char * s ;
  13. if (! logfile )
  14. return ;
  15. switch ( severity ) {
  16. case _EVENT_LOG_DEBUG : s = "debug" ; break ;
  17. case _EVENT_LOG_MSG : s = "msg" ; break ;
  18. case _EVENT_LOG_WARN : s = "warn" ; break ;
  19. case _EVENT_LOG_ERR : s = "error" ; break ;
  20. default : s = "?" ; break ; /* never reached */
  21. }
  22. fprintf ( logfile , "[%s] %s\n" , s , msg );
  23. }
  24. ?
  25. // 關(guān)閉 Libevent 的日志信息的輸出
  26. void suppress_logging ( void )
  27. {
  28. event_set_log_callback ( discard_cb );
  29. }
  30. ?
  31. // 設(shè)置 Libevent 的日志信息輸出到特定文件
  32. void set_logfile ( FILE * f )
  33. {
  34. logfile = f ;
  35. event_set_log_callback ( write_to_file_cb );
  36. }

關(guān)于日志的注意事項(xiàng):

  1. 日志處理函數(shù)中不要調(diào)用任何的 Libevent 函數(shù)
  2. Debug 日志信息默認(rèn)不會(huì)被輸出,一般也不需要

Libevent 處理致命錯(cuò)誤的做法是調(diào)用 exit() 或者 abort() 函數(shù),你可以修改此行為(例如,你希望此時(shí)輸出調(diào)用棧信息):

  1. typedef void (* event_fatal_cb )( int err );
  2. void event_set_fatal_callback ( event_fatal_cb cb );

注意事項(xiàng):

  1. 我們定義的 event_fatal_cb 函數(shù)不要將控制權(quán)再返回給 Libevent
  2. 不要在 event_fatal_cb 函數(shù)中調(diào)用任何的 Libevent 函數(shù)
為 Libevent 定義自己的內(nèi)存管理器

默認(rèn)的情況下 Libevent 使用 C 庫(kù)的內(nèi)存管理函數(shù)從堆上分配內(nèi)存。替換 Libevent 默認(rèn)內(nèi)存管理函數(shù)主要有以下幾個(gè)目的:

  1. 更加高效的分配內(nèi)存
  2. 檢測(cè)內(nèi)存泄漏

設(shè)置自己定義的內(nèi)存管理函數(shù):

  1. void event_set_mem_functions ( void *(* malloc_fn )( size_t sz ),
  2. void *(* realloc_fn )( void * ptr , size_t sz ),
  3. void (* free_fn )( void * ptr ));

替換 Libevent 內(nèi)存管理函數(shù)時(shí)需要注意的地方:

  1. 正如前面說(shuō)到的,所有設(shè)置應(yīng)該在 Libevent 被使用之前完成,對(duì)于內(nèi)存管理的配置來(lái)說(shuō)更加是如此,否則可能引起崩潰
  2. 你設(shè)定的內(nèi)存管理函數(shù)必須是線程安全的
  3. 你設(shè)定的 malloc 和 realloc 返回的內(nèi)存地址的對(duì)齊需要和 C 庫(kù)一致
  4. 你設(shè)定的 realloc 需要能夠處理 realloc(NULL, sz)
  5. 你設(shè)定的 realloc 需要能夠處理 realloc(ptr, 0)
關(guān)閉和清理

我們關(guān)閉程序的時(shí)候,需要完成一些清理工作:

  1. void libevent_global_shutdown ( void );

此函數(shù)在 2.1.1-alpha 才被引入。

Libevent 多線程的問(wèn)題

如果你希望 Libevent 函數(shù)分配的結(jié)構(gòu)能夠被多個(gè)線程共享,那么首先需要告知 Libevent 我們使用的鎖定函數(shù)。如果使用 pthreads 庫(kù)或者使用 Windows 線程,可以調(diào)用以下函數(shù)來(lái)進(jìn)行設(shè)置:

  1. // 這兩個(gè)函數(shù)成功返回 0 失敗返回 -1
  2. #ifdef WIN32
  3. int evthread_use_windows_threads ( void );
  4. #define EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED
  5. #endif
  6. #ifdef _EVENT_HAVE_PTHREADS
  7. int evthread_use_pthreads ( void );
  8. #define EVTHREAD_USE_PTHREADS_IMPLEMENTED
  9. #endif

void evthread_enable_lock_debuging(void) 函數(shù)可以讓 Libevent 通過(guò) assert 告知我們關(guān)于鎖的一些錯(cuò)誤信息,主要是告知我們解鎖了一個(gè)未持有的鎖。我們需要在任意一個(gè)鎖被創(chuàng)建或使用之前調(diào)用此函數(shù)。

void event_enable_debug_mode(void) 函數(shù)可以讓 Libevent 檢測(cè) event 使用上的一些錯(cuò)誤:

  1. 認(rèn)為一個(gè)未初始化的 event 已經(jīng)初始化了
  2. 嘗試重新初始化一個(gè) pending event(pending event 為一個(gè)術(shù)語(yǔ),之后的文章會(huì)談到)

注意的是,開(kāi)啟 debug 模式(也就是調(diào)用 event_enable_debug_mode)后,會(huì)有額外的內(nèi)存和 CPU 開(kāi)銷,所以應(yīng)該在真正調(diào)試的時(shí)候再開(kāi)啟。event_enable_debug_mode 函數(shù)需要在任意的 event_base 被創(chuàng)建前調(diào)用。

Libevent(1)— 簡(jiǎn)介、編譯、配置


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 安溪县| 聊城市| 郴州市| 邻水| 河间市| 武威市| 两当县| 秦皇岛市| 松江区| 大同市| 合阳县| 贵港市| 聊城市| 西宁市| 营山县| 霞浦县| 镇沅| 鹰潭市| 沧州市| 建瓯市| 临沧市| 崇义县| 元阳县| 乌兰县| 阿拉善左旗| 通海县| 张北县| 惠安县| 建始县| 赞皇县| 昆山市| 周宁县| 阿尔山市| 岱山县| 顺昌县| 平安县| 柘城县| 双鸭山市| 洮南市| 台北县| 彭山县|