libevent C 事件通知介面函式庫

工程師WWW發表於2013-11-20

今天在研究memcached軟體時,接觸到了libevent - 事件通知介面函式庫,發現了它對高效能,高併發,可移植等諸多方面提供了相當多的便利。心裡甚是歡喜,因此,這裡就想把這個好傢伙介紹給大家,共同分享分享。

    說在前邊,恕小弟無知,其實libevent軟體包早在2000年11月14號就釋出了0.1版本,已經發展了11個年頭了。如今才被窩發現,真是羞愧難當啊:-< 不過還好,發現了總歸是好事。那接下來,就該抓緊時間補習功課了。

    1. 介紹

    libevent是一個用來開發可擴充套件的網路伺服器的事件通知函式庫。當一個檔案描述符上的特定事件發生或是一個超時時間到達後,libevent API提供一種執行回撥函式的機制。而且,libevent還支援基於訊號或定期超時的回撥功能。

    libevent旨在替換原有事件驅動網路伺服器事件迴圈而設計的。應用程式僅僅需要呼叫event_dispatch(),然後動態地新增或是移除事件就可以了,而不需要改變原有的事件迴圈。

    目前,libevent支援/dev/poll,kqueue(2),select(2),poll(2)和epoll(4)等高併發網路程式設計模型。而它對實時訊號的支援正處於實驗性階段。內部的事件處理機制是完全獨立於暴露出來的API的,並且新功能的加入並不需要重新設計應用程式,而是僅僅需要做一個簡單的libevent更新即可。因此,lievent允許可移植性的應用程式開發,並且能夠提供適合特定作業系統的最具可擴充套件性的事件通知機制。libevent同時也可用於多執行緒程式設計環境,更多說明請看Steven Grimm的說明。libevent可以在Linux,*BSD,Mac OS X,Solaris和Windows系統上編譯。

    2. 標準用法

    每一個使用libevent的程式,都需要包含<event.h>標頭檔案,並且需要傳遞-levent標誌給聯結器linker。在使用任何庫函式之前,需要先呼叫event_init()或者event_base_new()函式制執行一次libevent庫的初始化。

    3. 事件通知

    對於每一個你想監視的檔案描述符,你必須宣告一個事件結構並且呼叫event_set()去初始化結構中的成員。為了啟用通知,你需要通過呼叫event_add()將該結構新增到監視事件列表。只要是該事件存活,那麼就需要保持該已allocated的事件結構,因此該事件結構需要在堆(heap)上申請。最後,需要呼叫event_dispatch()函式迴圈和排程事件。

    4. I/O緩衝區

    libevent提供了一個定期回撥事件頂層的抽象。該抽象被稱為緩衝事件(buffered event)。緩衝事件提供自動地填充和流掉(drained)的輸入和輸出緩衝區。緩衝時間的使用者不再需要直接操作I/O,取而待之的是僅僅從輸入緩衝區讀,向輸出緩衝區寫就可以了。

    一旦通過bufferevent_new()進行了初始化,bufferevent結構就可以通過bufferevent_enable()和bufferevent_disable()重複地使用了。作為替代,對一個套介面的讀寫需要通過呼叫bufferevent_read()和bufferevent_write()函式來完成。

    當由於讀事件而啟用bufferevent時,那麼後續將會自動回撥讀函式從該檔案描述符讀取資料。寫函式將會被回撥,無論何時這個輸出緩衝區空間被耗盡到低於寫的下水位(low watemark),通常該值預設為0。

    5. 定時器

    libevent通過建立一個定時器來參與到一個經過一定超時時間後的回撥事件中。evtimer_set()函式將準備(分配)一個事件結構被用於作為一個定時器。為了啟用定時器,需要呼叫evtimer_add()函式。相反,需要呼叫evtimer_del()函式。

    6. 超時

    除了簡單的定時器,libevent可以為檔案描述符指定一個超時事件,用於觸發經過一段時間後而沒有被啟用的檔案描述符執行相應的操作。timeout_set()函式可以為一個超時時間初始化一個事件結構。一旦被初始化成功,那麼這個事件必須通過timeout_add()函式啟用。為了取消一個超時事件,可以呼叫timeout_del()函式。

    7. 非同步DNS解析

    libevent提供了一個非同步DNS解析器,可用於代替標準的DNS解析器。這些函式可以通過在程式中包含<evdns.h>標頭檔案而將其匯入。在使用任何解析器函式之前,你必須呼叫evdns_init()函式初始化函式庫。為轉化一個域名到IP地址,可以呼叫evdns_resolve_ipv4()函式。為了執行一個反向查詢,你可以呼叫evdns_resolve_reverse()函式。所有的這些函式,在查詢時都會使用回撥的方式而避免阻塞的發生。

    8. 事件驅動的HTTP伺服器

    libevent提供了一個簡單的可以嵌入到你的程式中的並能處理HTTP請求的事件驅動HTTP伺服器。

    為了使用這種能力,你應該在你的程式中包含<evhttp.h>標頭檔案。你可以通過呼叫evhttp_new()函式來建立一個伺服器。通過evhttp_bind_socket()函式新增用於監聽的地址和埠。然後,你可以註冊一個或多個對到來請求的處理控制程式碼。對於每一個URI可以通過evhttp_set_cb()函式指定一個回撥。通常,一個回撥函式也可以通過evhttp_set_gencb()函式完成註冊;如果沒有其他的回撥已經被註冊得到該URI,那麼這個回撥將會與其關聯。

    9. RPC伺服器和客戶端框架

    libevent提供了一個建立RPC伺服器和客戶端的程式設計框架。它將託管所有的編組和解組的資料結構。




libevent事件通知機制

Libevent 是一個基於事件通知機制的網路庫,用來開發可擴充套件性的多執行緒的網路伺服器。
Libevent提供了一種機制,可以在指定某個檔案描述符或者某個超時事件到達時,執行一個回撥函式。應用程式只需要呼叫event_dispatch(),然後動態增加或移除事件,而不用修改事件迴圈。

Libevent目前支援/dev/poll, kqueue(2), select(2), poll(2), epoll(4), and evports。

Libevent的內部事件機制和暴露的外部介面完全獨立,因此當Libevent需要更新時,可以保證外部介面不變,中影響已經開發完成的應用程式。因此,Libevent提供了跨平臺的開發能力。

Libevent可以在Linux, *BSD, Mac OS X, Solaris and, Windows編譯。

每個使用Libevent的程式必須包含<event2/event.h>,傳遞引數-levent給編譯連結程式。 

在你呼叫Libevent的函式前,你需要安裝這個庫。如果你要在多執行緒程式中使用Libevent,你需要初始化多執行緒支援--呼叫evthread_use_pthreads() or evthread_use_windows_threads()。詳情請檢視 <event2/thread.h>

可以替換Libevent的記憶體管理函式,通過event_set_mem_functions函式,用event_enable_debug_mode()開啟debug模式。

 

為了使用libevent,你需要完成以下步驟:

1、使用event_base_new() or event_base_new_with_config(),建立一個event_base 結構,event_base用來管理哪些事件被監測,哪些事件被啟用。每個event只能和一個event_base相聯絡。

2、對於每個你要監視的檔案描述符,你必須用event_new建立一個event結構體。你也可以宣告一個event結構體然後用event_assign初始化結構體。

3、要使通知生效,你要用event_add把該結構體加入監控列表。event結構體必須在他活躍狀態一直存在,因此一般需要在堆上分配。

4、最後,你可以使用event_base_dispatch去迴圈處理事件。你也可以使用event_base_loop() 去做更靈活的控制,比如用非阻塞的方式去呼叫loop。

注意:一個event_base在同一時間只能被一個執行緒dispatching。如果你想在多個執行緒使用events,你可以給每個執行緒建立一個event_base物件。



相關文章