1. 程式人生 > >LibEvent中文幫助文件--第5章【設定LibEvent庫】

LibEvent中文幫助文件--第5章【設定LibEvent庫】



LiEvent中文幫助文件--第5章【設定LibEvent庫】

返回主目錄

Libevent

快速可移植非阻塞式網路程式設計

修訂歷史

版本

日期

作者

備註

V1.0

2016-11-15

周勇

Libevent程式設計中文幫助文件

文件是2009-2012年由Nick-Mathewson基於Attribution-Noncommercial-Share Alike許可協議3.0建立,未來版本將會使用約束性更低的許可來建立.

此外,本文件的原始碼示例也是基於BSD"3條款""修改"條款.詳情請參考BSD檔案全部條款.本文件最新下載地址

:

英文:http://libevent.org/

請下載並執行"gitclonegit://github.com/nmathewson/libevent- book.git"獲取本文件描述的最新版本原始碼.

5.設定LibEvent

LibEvent在程序中有一些影響整個庫的全域性設定.在你呼叫LibEvent庫中任何一個部分之前都需要進行設定,否則libEvent將會進入不一致的狀態.

5.1LibEvent日誌訊息

LibEvent能記錄內部的錯誤和警告日誌,如果編譯進日誌支援功能,也會記錄除錯資訊.預設情況下這些訊息都是輸出到stderr,你也可以通過提供自己的日誌函式的方法來覆蓋這種行為

.

介面

#define EVENT_LOG_DEBUG 0
#define EVENT_LOG_MSG 1
#define EVENT_LOG_WARN 2
#define EVENT_LOG_ERR 3
/* Deprecated; see note at the end of this section*/
#define _EVENT_LOG_DEBUG EVENT_LOG_DEBUG
#define _EVENT_LOG_MSG EVENT_LOG_MSG
#define _EVENT_LOG_WARN EVENT_LOG_WARN
#define _EVENT_LOG_ERR EVENT_LOG_ERR

typedef void ( * event_log_cb)(int severity, const char* msg);

void event_set_log_callback(event_log_cb cb);

為了覆蓋LibEvent的日誌行為,你需要自己編寫滿足event_log_cb格式的函式,然後將函式作為引數傳入event_set_log_callback().無論什麼時候只要LibEvent需要寫一個日誌,都會進入到你提供的日誌函式.你需要讓LibEvent日誌回到預設功能的時候只需要再次呼叫event_set_log_callback()並且傳一個NULL即可.

例子

#include <event2/event.h>
#include <stdio.h>
static void discard_cb(int severity, const char* msg)
{
	/* This callback does nothing.*/
}
static FILE* logfile = NULL;
static void write_to_file_cb(int severity, const char* msg)
{
	const char* s;
	if (!logfile)
		return;
	switch (severity) 
	{
		case _EVENT_LOG_DEBUG: s = "debug"; break;
		case _EVENT_LOG_MSG: s = "msg"; break;
		case _EVENT_LOG_WARN: s = "warn"; break;
		case _EVENT_LOG_ERR: s = "error"; break;
		default: s = "?"; break; /* never reached*/
	}
	fprintf(logfile, "[%s] %s\n", s, msg);
}
/* Turn off all logging from Libevent.*/
void suppress_logging(void)
{
	event_set_log_callback(discard_cb);
}
/* Redirect all Libevent log messages to the C stdio file ’f’.*/
void set_logfile(FILE* f)
{
	logfile = f;
	event_set_log_callback(write_to_file_cb);
}

注意:在使用者提供的event_log_cb回撥函式中進行LibEvent的函式呼叫是不安全的.如果你想寫一個用bufferevents去傳送告警資訊給一個網路socket的日誌回撥函式,你就可能會遇到非常奇怪和難以診斷的錯誤.在將來的版本中將會為一些函式移除這些限制.

通常除錯日誌都是禁用的,也都不會發送給日誌回撥函式,但是如果libEvent是編譯成支援開啟除錯日誌,你就可以手動開啟除錯日誌.

介面

#define EVENT_DBG_NONE 0
#define EVENT_DBG_ALL 0xffffffffu
void event_enable_debug_logging(ev_uint32_t which);

大多數情況下,除錯日誌都是冗餘、不必要、沒什麼用的.呼叫event_enable_debug_logging()使用EVENT_DBG_NONE得到預設行為,使用EVENT_DBG_ALL開啟所有可支援的除錯日誌,未來會有更多更細的選項支援.

這些函式定義在<event2/event.h>,首先出現是在LibEvent1.0c版本,event_enable_debug_logging()是在LibEvent2.1.1-alpha版本.

LibEvent2.0.19之前相容性需要注意的是EVENT_LOG_*巨集在此前有下面的記錄:_EVENT_LOG_DEBUG, _EVENT_LOG_MSG, _EVENT_LOG_WARN, and _EVENT_LOG_ERR.這些老的命名已經廢棄不用,只會僅僅用於相容LibEvent2.18及之前的版本,這些在將來的版本都會全部移除掉.

5.2處理致命錯誤

LibEvent檢測到一個不可恢復的致命錯誤(比如資料結構損壞),它的預設行為是呼叫exit()abort()來退出當前執行的程序.這意味著有一個錯誤,要麼在你的程式碼中,要麼在LibEvent.

如果你想讓你的程式更從容地應對致命錯誤,你可以為LibEvent提供退出時候應該呼叫的函式,覆蓋預設行為.

介面

typedef void ( * event_fatal_cb)(int err);
void event_set_fatal_callback(event_fatal_cb cb);

要使用這些函式,你首先需要定義一個當LibEvent遇到錯誤時候需要呼叫的函式,並且將它傳到event_set_fata_callback()函式.之後如果LibEvent遇到致命錯誤,它就會呼叫你提供的函式.

你的函式不可以控制返回到LibEvent,因為這樣做可能會導致未定義行為發生,為了避免崩潰,LibEvent還是會退出.一旦你的程式被呼叫了,在你的函式中就不應該再呼叫別的LibEvent的函式.

這些函式被定義在<event2/event.h>,第一次出現在LibEvent2.0.3-alpha版本中.

5.3記憶體管理

預設情況下,LibEvent使用c語言庫中提供的記憶體管理函式在堆上分配記憶體,你也可以替換mallocreallocfree,LibEvent使用別的記憶體管理.你想用一個更有效的記憶體分配器,或者用一個記憶體分配工具來檢查記憶體洩露你都可能會這樣做.

介面

void event_set_mem_functions( void* ( * malloc_fn)(size_t sz),
void* ( * realloc_fn)(void * ptr, size_t sz),
void  ( * free_fn)(void* ptr));


例子

#include <event2/event.h>
#include <sys/types.h>
#include <stdlib.h>
/* This union’s purpose is to be as big as the largest of all the types it contains.*/
union alignment 
{
	size_t sz;
	void
	* ptr;
	double dbl;
};
/* We need to make sure that everything we return is on the right alignment to hold anything, including a double.*/
#define ALIGNMENT sizeof(union alignment)
/* We need to do this cast-to-char * trick on our pointers to adjust them; doing arithmetic on a void * is not standard.*/
#define OUTPTR(ptr) (((char * )ptr)+ALIGNMENT)
#define INPTR(ptr) (((char * )ptr)-ALIGNMENT)
static size_t total_allocated = 0;
static void* replacement_malloc(size_t sz)
{
	void* chunk = malloc(sz + ALIGNMENT);
	if (!chunk) return chunk;
	total_allocated += sz;
	* (size_t * )chunk = sz;
	return OUTPTR(chunk);
}
static void* replacement_realloc(void * ptr, size_t sz)
{
	size_t old_size = 0;
	if (ptr) 
	{
		ptr = INPTR(ptr);
		old_size =
		*(size_t * )ptr;
	}
	ptr = realloc(ptr, sz + ALIGNMENT);
	if (!ptr)	return NULL;
	*(size_t * )ptr = sz;
	total_allocated = total_allocated - old_size + sz;
	return OUTPTR(ptr);
}
static void replacement_free(void* ptr)
{
	ptr = INPTR(ptr);
	total_allocated -=	*(size_t * )ptr;
	free(ptr);
}
void start_counting_bytes(void)
{
	event_set_mem_functions(replacement_malloc,
	replacement_realloc,
	replacement_free);
}

注意:更換記憶體管理函式將會影響LibEvent後續所有呼叫allocateresizefree記憶體的函式.因此你需要確保在LibEvent呼叫其它函式之前替換掉這些函式.否則LibEvent將會呼叫你提供的free函式來釋放從C語言庫版本的malloc分配的記憶體.

  • 你的mallocrealloc函式需要返回和C語言庫相同的記憶體對齊.

  • 你的realloc函式需要正確處理realloc(NULL,sz),也就是說當做(malloc(sz)處理).

  • 你的realloc函式需要正確處理realloc(ptr,0),也就是說當做free(ptr)處理.

  • 你的free函式不必去處理free(NULL).

  • 你的malloc函式不必去處理malloc(0).

  • 如果你不止一個執行緒使用LibEvent,那麼你提供的的記憶體管理替代函式必須是執行緒安全的.

  • LibEvent會使用這些函式分配返回給你的記憶體.

    如果你已經替換了mallocrealloc函式並且想釋放LibEvent分配的記憶體,那麼就需要使用你替換的free函式來釋放.

    event_set_mem_functions()函式在<event2/event.h>中申明,首次出現是在LibEvent2.0.1alpha版本.

    LibEvent可以被編譯為event_set_mem_functions()禁用,如果這樣,event_set_mem_functions()函式不會被編譯和連結到程式.LibEvent2.0.2-alpha版本之後,你可以檢查是否定義了EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED巨集來檢測event_set_mem_functions()函式是否存在.

5.4執行緒和鎖

如果你寫過多執行緒程式,你會知道在多執行緒中同一時間訪問同一個資料通常是不安全的.

LibEvent的結構體在多執行緒一般有三種工作方法:

  • 某些結構體在單執行緒內部是安全的,但在多執行緒中同時訪問不再是安全的.

  • 某些結構體是有可選的鎖的,你需要告知LibEvent是否需要在多執行緒中使用每個物件.

某些結構體是一直鎖住的,如果LibEvent在執行中支援鎖,那麼在多執行緒中用這些結構體是安全的.

為了LibEvent上鎖,你需要告知LibEvent使用的是哪個鎖函式,在呼叫任何LibEvent函式分配一個執行緒間共享的結構之前你就需要這樣做.

如果你用的是pthreads庫或者是windows的執行緒程式碼,那麼你很幸運,那些預定義函式將會幫你把LibEvent設定為正確支援pthreadswindows的函式.

介面

#ifdef WIN32
	int evthread_use_windows_threads(void);
	#define EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED
#endif
#ifdef _EVENT_HAVE_PTHREADS
	int evthread_use_pthreads(void);
	#define EVTHREAD_USE_PTHREADS_IMPLEMENTED
#endif

這兩個函式都是成功返回0失敗返回-1.

如果你需要使用不同的執行緒庫,那麼在此之前還有一些需要做,你需要用你的庫定義函式去實現:

  • 上鎖

  • 解鎖

  • 分配鎖

  • 釋放鎖

  • 條件

  • 建立條件變數

  • 釋放條件變數

  • 等待條件變數

  • 訊號/廣播一個條件變數

  • 執行緒

  • 執行緒ID檢測

使用 evthread_set_lock_callbacksevthread_set_id_callback介面告訴LibEvent這些函式.

介面

#define EVTHREAD_WRITE 0x04
#define EVTHREAD_READ 0x08
#define EVTHREAD_TRY 0x10
#define EVTHREAD_LOCKTYPE_RECURSIVE 1
#define EVTHREAD_LOCKTYPE_READWRITE 2
#define EVTHREAD_LOCK_API_VERSION 1
struct evthread_lock_callbacks 
{
	int lock_api_version;
	unsigned supported_locktypes;
	void* ( * alloc)(unsigned locktype);
	void ( * free)(void* lock, unsigned locktype);
	int ( * lock)(unsigned mode, void* lock);
	int ( * unlock)(unsigned mode, void* lock);
};
int evthread_set_lock_callbacks(const struct evthread_lock_callbacks* );
void evthread_set_id_callback(unsigned long ( * id_fn)(void));
struct evthread_condition_callbacks 
{
	int condition_api_version;
	void* ( * alloc_condition)(unsigned condtype);
	void ( * free_condition)(void* cond);
	int ( * signal_condition)(void* cond, int broadcast);
	int ( * wait_condition)(void* cond, void * lock,const struct timeval* timeout);
};
int evthread_set_condition_callbacks(const struct evthread_condition_callbacks* );

evthread_lock_callbacks結構體描述你的的鎖回撥函式及其能力.對於上述版本lock_api_version欄位必須設定為 EVTHREAD_LOCK_API_VERSION.Supported_locktypes必須設定到一個EVTHREAD_LOCKTYPE*的二進位制掩碼來描述能支援哪種類的鎖(2.0.4-alpha

相關推薦

LibEvent中文幫助--5設定LibEvent

 LiEvent中文幫助文件--第5章【設定LibEvent庫】 返回主目錄 Libevent 快速可移植非阻塞式網路程式設計 修訂歷史 版本 日期 作者 備註 V1.0 2016-11-15 周勇 Libeve

ASP.NET Core 中文 測試(5.2)整合測試

整合測試確保應用程式的元件組裝在一起時正常工作。 ASP.NET Core支援使用單元測試框架和可用於處理沒有網路開銷請求的內建測試的網路主機整合測試。 章節: 整合測試介紹 整合測試驗證應用程式不同的部位是否正確地組裝在一起。不像單元測試,整合測試經常涉及到應用基礎設施,如資料庫,檔案系統,網路資源

ASP.NET Core 中文 MVC(4.5)測試控制器邏輯

ASP.NET MVC 應用程式的控制器應當小巧並專注於使用者介面。涉及了非 UI 事務的大控制器更難於測試和維護。 章節: 為什麼要測試控制器 控制器是所有 ASP.NET Core MVC 應用程式的核心部分。因此,你應當確保它們的行為符合應用的預期。 自動化測試可以為你提供這樣的保障並能夠在進入生

ASP.NET Core 中文 MVC(4.6)Areas(區域)

Areas 是 ASP.NET MVC 用來將相關功能組織成一組單獨名稱空間(路由)和資料夾結構(檢視)的功能。使用 Areas 建立層次結構的路由,是通過新增另一個路由引數 area 到 Controller 和 action。 Areas 提供了一種把大型 ASP.NET Core MVC Web 應用

ASP.NET Core 中文 MVC(4.2)控制器操作的路由

ASP.NET Core MVC 使用路由 中介軟體 來匹配傳入請求的 URL 並對映到具體的操作。路由通過啟動程式碼或者特性定義。路由描述 URL 路徑應該如何匹配到操作。路由也同樣用於生成響應中返回的 URL(用於連結)。 這篇文章將解釋 MVC 和路由之間的相互作用,以及典型的 MVC 應用程式如何使

ASP.NET Core 中文 MVC(4.1)Controllers, Actions 和 Action Results

Action 和 action result 是開發者使用 ASP.NET MVC 構建應用程式的基礎部分。 什麼是 Controller 在 ASP.NET MVC 中, 控制器( Controller  )用於定義和聚合操作(Action)的一個集合。操作( 或操作方法 )是控制器中處理入站請求的一個方

ASP.NET Core 中文 MVC(2.3)格式化響應資料

ASP.NET Core MVC 內建支援對相應資料(response data)的格式化,用來修正格式或生成客戶端指定的格式。 特定格式的操作結果 某些操作結果(Action result)的型別是指定的特定格式,比如 JsonResult 或 ContentResult。Action 可以返回格式化為

ASP.NET Core 中文 MVC(4.4)依賴注入和控制器

ASP.NET Core MVC 控制器應通過它們的構造器明確的請求它們的依賴關係。在某些情況下,單個控制器的操作可能需要一個服務,在控制器級別上的請求可能沒有意義。在這種情況下,你也可以選擇將服務作為 action 方法的引數。 章節: 依賴注入 依賴注入(Dependency injection,

ASP.NET Core 中文 MVC(01)ASP.NET Core MVC 概覽

ASP.NET Core MVC 是使用模型-檢視-控制器(Model-View-Controller)設計模式構建網頁應用與 API 的豐富的框架。 什麼是 MVC 模式? 模型-檢視-控制器(MVC)架構模式將一個應用區分為三部分主要元件:模型、檢視、與控制器。這種模式有助實現關注分離。使用這種模式,使

ASP.NET Core 中文 MVC(4.3)過濾器

ASP.NET MVC 過濾器 可在執行管道的前後特定階段執行程式碼。過濾器可以配置為全域性有效、僅對控制器有效或是僅對 Action 有效。 過濾器如何工作? 不同的過濾器型別會在執行管道的不同階段執行,因此它們各自有一套適用場景。根據你實際要解決的問題以及在請求管道中執行的位置來選擇建立不同的過濾器。

ASP.NET Core 中文 原理(2)中介軟體

章節: 什麼是中介軟體 中介軟體是用於組成應用程式管道來處理請求和響應的元件。管道內的每一個元件都可以選擇是否將請求交給下一個元件、並在管道中呼叫下一個元件之前和之後執行某些操作。請求委託被用來建立請求管道,請求委託處理每一個 HTTP 請求。 請求委託通過使用 IApplicationBuilder

ASP.NET Core 中文 MVC(3.8)檢視中的依賴注入

ASP.NET Core 支援在檢視中使用 依賴注入 。這將有助於提供檢視專用的服務,比如本地化或者僅用於填充檢視元素的資料。你應該儘量保持控制器和檢視間的關注點分離(separation of concerns)。你的檢視所顯示的大部分資料應該從控制器傳入。 章節: 一個簡單的示例 你可以使用 @i

ASP.NET Core 中文 MVC(3.7 )區域性檢視(partial)

ASP.NET Core MVC 支援區域性檢視,當你需要在多個不同檢視間重用同一個頁面部件時會顯得特別有用。 什麼是區域性檢視? 區域性檢視是在其它檢視中被渲染的檢視。區域性檢視執行後生成的 HTML 結果會被渲染到呼叫方檢視或父檢視中。跟檢視檔案一樣,區域性檢視檔案也使用 .cshtml 作為副檔名。

ASP.NET Core 中文 MVC(3.9)檢視元件

章節: 介紹檢視元件 檢視元件是 ASP.NET Core MVC 中的新特性,與區域性檢視相似,但是它們更加的強大。檢視元件不使用模型繫結,只取決於呼叫它時所提供的資料。檢視元件有以下特點: 渲染一個塊,而不是整個響應 在控制器和檢視之間同樣包含了關注點分離和可測試性帶來的好處 可以擁有引數和業務邏

ASP.NET Core 中文 原理(6)全球化與本地化

使用 ASP.NET Core 建立一個多語言版本的網站有助於你吸引到更多的使用者,ASP.NET Core 提供服務和中介軟體來支援本地化語言和文化。 國際化涉及 全球化 和 本地化。全球化是為了應用程式支援不同文化而設計的。全球化增加了對特定地理區域的語言文字的輸入、顯示和輸出的支援。 本地化是針對一個

ASP.NET Core 中文 原理(11)在多個環境中工作

ASP.NET Core 介紹了支援在多個環境中管理應用程式行為的改進,如開發(development),預演(staging)和生產(production)。環境變數用來指示應用程式正在執行的環境,允許應用程式適當地配置。 章節: 開發,預演,生產 ASP.NET Core 引用了一個特定的環境變數

ASP.NET Core 中文 原理(4)路由

路由是用來把請求對映到路由處理程式。應用程式一啟動就配置了路由,並且可以從URL中提取值用於處理請求。它還負責使用 ASP.NET 應用程式中定義的路由來生成連結。 這份文件涵蓋了初級的ASP.NET核心路由。對於 ASP.NET 核心 MVC 路由, 請檢視 Routing to Controller A

ASP.NET Core 中文 原理(13)管理應用程式狀態

在 ASP.NET Core 中,有多種途徑可以對應用程式的狀態進行管理,取決於檢索狀態的時機和方式。本文簡要介紹幾種可選的方式,並著重介紹為 ASP.NET Core 應用程式安裝並配置會話狀態支援。 應用程式狀態的可選方式 應用程式狀態 指的是用於描述應用程式當前狀況的任意資料。包括全域性的和使用者特

ASP.NET Core 中文 原理(1)應用程式啟動

ASP.NET Core 為你的應用程式提供了處理每個請求的完整控制。Startup 類是應用程式的入口(entry point),這個類可以設定配置(configuration)並且將應用程式將要使用的服務連線起來。開發人員可以在 Startup 類中配置請求管道,該管道將用於處理應用程式的所有請求。 章

ASP.NET Core 中文 原理(16).NET開放Web介面(OWIN)

ASP.NET Core 支援 OWIN(即 Open Web Server Interface for .NET 的首字母縮寫),OWIN的目標是用於解耦Web Server和Web Application。此外, OWIN為中介軟體定義了一個標準方法用來處理單個請求以及相關聯的響應。ASP.NET Co