1. 程式人生 > >Libevent(1)— 簡介、編譯、配置

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

此文編寫的時候,使用到的 Libevent 為 2.0.21

Libevent 之跨平臺

在處理大量 SOCKET 連線時,使用 select 並不高效。各個系統都提供了處理大量 SOCKET 連線時的解決方案:

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

由於各個平臺使用了不同的介面,那麼我們需要編寫跨平臺的高效能非同步程式時就需要做一層跨平臺封裝。
這個時候 Libevent 就成為一個較好的選擇,其最底層 API(event 和 event_base API)為各個平臺實現高效能非同步程式提供了一致的介面。

Libevent 2 提供的 bufferevent 介面,一方面簡化了程式設計的難度,另一方面保證了在 Windows 和 Unix 上都很高效。

一些基本的概念

  1. event 會繫結檔案描述符、回撥函式並表示一個或者多個條件(例如,檔案描述符可以讀或者寫了、發生了超時等)。event 表示的條件如果被觸發了,那麼 event 會變為活躍的,它繫結的回撥函式就會被執行
  2. event_base 用於持有一組 event 並進行事件迴圈,event_base 會存在一個後端(也叫做方法),常見的後端包括 epoll、kqueue 等

Libevent 的結構

元件:

  1. evutil 用於抽象不同的平臺的網路(基礎的)實現
  2. event、event_base 為 Libevent 的核心,為不同的平臺下基於事件的非阻塞 I/O 提供了一套抽象的介面
  3. bufferevent 對 Libevent 的基於事件的核心的封裝。應用程式的讀寫請求是基於緩衝區的
  4. evbuffer 為 bufferevent 實現的緩衝區
  5. evhttp 一個簡單的 HTTP client/server 的實現
  6. evdns 一個簡單的 DNS client/server 的實現
  7. evrpc 一個簡單的 RPC 實現

庫:

  1. libevent_core 包括 util、event_base、evbuffer、bufferevent
  2. libevent_extra 包括 HTTP、DNS、RPC
  3. libevent 此庫由於歷史原因而存在,不要使用它
  4. libevent_pthreads 此庫為基於 pthread 的執行緒和鎖的實現
  5. libevent_openssl 此庫通過 openssl 和 bufferevent 提供了加密通訊

標頭檔案:
所有的公用標頭檔案位於 event2 目錄中。

編譯 Libevent 庫

Linux 下編譯的方式為(詳細見 README):

  1. $ ./configure
  2. $ make

常用的 configure 標誌有:

  1. --disable-shared 只編譯靜態庫
  2. --disable-openssl 關閉OpenSSL加密支援

Windows 下編譯的方式為:

  1. nmake /f Makefile.nmake

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

設定 Libevent 庫

在具體的介紹之前,這裡首先需要明確的一點是,我們總是先設定 Libevent,然後才去使用 Libevent。

關於輸出日誌的設定

Libevent 的日誌資訊預設被寫入 stderr(標準錯誤),我們可以提供自己的日誌處理函式給 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. // severity 引數對應了上面的各種日誌型別
  8. typedefvoid(*event_log_cb)(int severity,constchar*msg);
  9. // 設定一個新的日誌處理函式
  10. void event_set_log_callback(event_log_cb cb);

設定日誌處理函式的範例:

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

關於日誌的注意事項:

  1. 日誌處理函式中不要呼叫任何的 Libevent 函式
  2. Debug 日誌資訊預設不會被輸出,一般也不需要

Libevent 處理致命錯誤的做法是呼叫 exit() 或者 abort() 函式,你可以修改此行為(例如,你希望此時輸出呼叫棧資訊):

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

注意事項:

  1. 我們定義的 event_fatal_cb 函式不要將控制權再返回給 Libevent
  2. 不要在 event_fatal_cb 函式中呼叫任何的 Libevent 函式
為 Libevent 定義自己的記憶體管理器

預設的情況下 Libevent 使用 C 庫的記憶體管理函式從堆上分配記憶體。替換 Libevent 預設記憶體管理函式主要有以下幾個目的:

  1. 更加高效的分配記憶體
  2. 檢測記憶體洩漏

設定自己定義的記憶體管理函式:

  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 記憶體管理函式時需要注意的地方:

  1. 正如前面說到的,所有設定應該在 Libevent 被使用之前完成,對於記憶體管理的配置來說更加是如此,否則可能引起崩潰
  2. 你設定的記憶體管理函式必須是執行緒安全的
  3. 你設定的 malloc 和 realloc 返回的記憶體地址的對齊需要和 C 庫一致
  4. 你設定的 realloc 需要能夠處理 realloc(NULL, sz)
  5. 你設定的 realloc 需要能夠處理 realloc(ptr, 0)
關閉和清理

我們關閉程式的時候,需要完成一些清理工作:

  1. void libevent_global_shutdown(void);

此函式在 2.1.1-alpha 才被引入。

Libevent 多執行緒的問題

如果你希望 Libevent 函式分配的結構能夠被多個執行緒共享,那麼首先需要告知 Libevent 我們使用的鎖定函式。如果使用 pthreads 庫或者使用 Windows 執行緒,可以呼叫以下函式來進行設定:

  1. // 這兩個函式成功返回 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) 函式可以讓 Libevent 通過 assert 告知我們關於鎖的一些錯誤資訊,主要是告知我們解鎖了一個未持有的鎖。我們需要在任意一個鎖被建立或使用之前呼叫此函式。

void event_enable_debug_mode(void) 函式可以讓 Libevent 檢測 event 使用上的一些錯誤:

  1. 認為一個未初始化的 event 已經初始化了
  2. 嘗試重新初始化一個 pending event(pending event 為一個術語,之後的文章會談到)

注意的是,開啟 debug 模式(也就是呼叫 event_enable_debug_mode)後,會有額外的記憶體和 CPU 開銷,所以應該在真正除錯的時候再開啟。event_enable_debug_mode 函式需要在任意的 event_base 被建立前呼叫。

相關推薦

Libevent1簡介編譯配置

此文編寫的時候,使用到的 Libevent 為 2.0.21 Libevent 之跨平臺 在處理大量 SOCKET 連線時,使用 select 並不高效。各個系統都提供了處理大量 SOCKET 連線時的解決方案: Linux 下的 epoll()BSD 下的 kque

大資料基礎之Quartz1簡介原始碼解析

一簡介 官網 http://www.quartz-scheduler.org/ What is the Quartz Job Scheduling Library? Quartz is a richly featured, open source job scheduling libra

大資料基礎之Kafka1簡介安裝及使用

http://kafka.apache.org   一 簡介 Kafka® is used for building real-time data pipelines and streaming apps. It is horizontally scalable,&nb

【原創】運維基礎之Ansible1簡介安裝和使用

ets 安裝 yum ant gem get 結構 ges describe 官方:https://www.ansible.com/ 一 簡介 Ansible is a radically simple IT automation engine that automate

【原創】運維基礎之Nginx1簡介安裝使用

官方:http://nginx.org nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by

【原創】大數據基礎之Kudu1簡介安裝

變化 決策 leader 通用 修改 amp use case 容錯性 stream kudu 1.7 官方:https://kudu.apache.org/ 一 簡介 kudu有很多概念,有分布式文件系統(HDFS),有一致性算法(Zookeeper),有Table

【原創】算法基礎之Anaconda1簡介安裝使用

https orf ati 2.7 容易 ice range gcc x86_64 Anaconda 2 官方:https://www.anaconda.com/ 一 簡介 The Most Popular Python Data Science Platform A

【原創】大數據基礎之Mesos1簡介安裝使用

物理 variable 服務器集群 ast 過程 ould task pos 編譯 Mesos 1.7.1 官方:http://mesos.apache.org/ 一 簡介 Program against your datacenter like it’s a sin

【原創】運維基礎之Redis1簡介安裝使用

lists 腳本 分享 ngs 參考 ports eos 運維基礎 lru redis 5.0.3 官方:https://redis.io/ 一 簡介 Redis is an open source (BSD licensed), in-memory data str

【原創】大數據基礎之Presto1簡介安裝使用

epo embedded mach img ans 公司 mkdir redis running presto 0.217 官方:http://prestodb.github.io/ 一 簡介 Presto is an open source distrib

redis叢集與分片1-redis伺服器叢集客戶端分片 redis叢集與分片1-redis伺服器叢集客戶端分片

redis叢集與分片(1)-redis伺服器叢集、客戶端分片   下面是來自知乎大神的一段說明,個人覺得非常清晰,就收藏了。 為什麼叢集? 通常,為了提高網站響應速度,總是把熱點資料儲存在記憶體中而不是直接從後端 資料庫中

資訊理論複習筆記1:資訊熵條件熵,聯合熵,互資訊交叉熵,相對熵

文章目錄 1.1 資訊和資訊的測量 1.1.1 什麼是資訊 1.1.1 資訊怎麼表示 1.2 資訊熵 1.3 條件熵和聯合熵

Kettle控制元件介紹1:生成記錄自定義常量資料

這邊主要介紹2個控制元件,生成記錄以及自定義常量資料,屬於kettle輸入項裡。 一、生成記錄: 這是生成記錄的轉換圖,生成記錄的具體值如下: 如圖,建立三個欄位,分別為A、B、C,對其定義欄位型別和欄位值。最上面的"限制"是限制展示的數量;如圖,"限制"為5,那就展示5行。 結

設計模式學習總結1簡單工廠模式工廠方法模式抽象工廠模式

設計模式學習 做了幾個專案,發現設計模式的好處還是很多的,這東西就是隻有你真正用到的時候才知道他的好處,否則學了也不知道所以然。所以設計模式學習我認為可以在先進行幾個專案後,再來學習,這樣學習的效果和感受才是最好的。 這次是做一個學習的筆記,內容還是主要以我看的兩本書《大

Opencv入門筆記1:影象載入顯示儲存轉換灰度圖

影象載入、顯示、儲存函式: 1         影象載入函式:imread()   Mat imread(const string& filename, int flags=1);     const string&型別的filename為載入影象的路徑(

python高階——多工協程1迭代器生成器

迭代器 迭代是訪問集合元素的一種方式。迭代器是一個可以記住遍歷的位置的物件。迭代器物件從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會後退。 1. 可迭代物件 我們已經知道可以對list、tuple、str等型別的資料使用for...in...的迴

Redis簡介及安裝測試

一、Redis簡介:   關於關係型資料庫和nosql資料庫   關係型資料庫是基於關係表的資料庫,最終會將資料持久化到磁碟上,而nosql資料 庫是基於特殊的結構,並將資料儲存到記憶體的資料庫。從效能上而言,nosql資料庫 要優於關係型資料庫,從安全性上而言關係型資料庫要優於nosql資料庫,所以在實

pyCUDA教程-系列學習1:GPU結構pyCUDAnumbapro安裝及HelloGPU例子

GPU結構CPU v.s. GPU CPU是被設計用來處理複雜任務的,而GPU只能做好一件事-處理百萬級的低階任務(原來是被用來生成3D圖形中的三角形),而且GPU有上千個ALU(算術邏輯單元),而CPU通常只有8個。而且很多程式大部分時間都花在GPU擅長的簡單運算上了,所

電吉他效果器音訊處理1——失真效果器超載失真效果器移相效果器弗蘭格效果器

#電吉他效果器音訊處理(1)——失真效果器、超載效果器、移相效果器、弗蘭格效果器# 由於最近一個月在實習,所以機器學習方面的文章系列最近暫停了一段時間,實習過後該系列會恢復更新(其實是由於筆者太懶了Orz)。 實習完過後筆者晚上回去沒事就搗鼓搗鼓電吉他,最近沒事就在研究電吉他效果

高等數學:第十章 曲線積分與曲面積分1對弧長座標的曲線積分,格林公式及其應用

§10.1  對弧長的曲線積分 一、概念的引進 假設面內有一段曲線弧具有質量,在上任一點處的線密度為,且在上連續,與分別是弧的端點,現計算弧的質量。 在上任意地插入個分點 將分劃成個小弧段。對於第  個小弧段,由於線密度函式在上連續,當該小弧段的長度充分小時,它的質量近