libevent源码学习-----事件驱动流程分析
生活随笔
收集整理的這篇文章主要介紹了
libevent源码学习-----事件驱动流程分析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
libevent中事件驅動的大體流程如下
/* 創建事件驅動 */ struct event_base* base = event_base_new(); /**創建一個事件*@param base: 事件驅動*@param fd: event對應的文件描述符,通常是通過socket創建的套接字*@param EV_READ: 想要監聽fd的哪些事件,EV_READ表示監聽fd是否可讀,也可以是EV_PERSIST代表這個event是永久事件,在調用一次回調函數后仍然繼續監聽,對應一次性event,調用后不再監聽*@param cb: 當fd對應的事件發生后調用的回調函數,用戶提供*@param arg: 傳給回調函數cb的參數*/ struct event* ev = event_new(base, fd, EV_READ|EV_PERSIST, cb, arg);/* *將event添加到事件驅動中,由base統一管理event,當event對應的fd的事件發生,會自動調用event對應的cb*NULL表示不設置超時時間,如果設置,則在規定時間之內沒有發生事件就會停止監控,刪除event,設置EV_PERSIST時還會重新將event添加到base中*/ event_add(ev, NULL);/* 開始事件驅動主循環 */ event_base_dispatch(base);/* 釋放base */ event_base_free(base);創建事件驅動base時調用的event_base_new主要時用于對base進行初始化,包括初始化
- 用于存放監聽文件描述符的event的map
- 用于存放監聽信號的event的map
- 用于存放具有超時時間的event的最小堆,超時時間為絕對時間,具體可以參考時間管理
- 用于存放已注冊event的隊列
- 用于存放相應事件發生(已激活)event的隊列
- 選擇合適的io多路復用函數,可以參考io多路復用的封裝和使用
創建事件event時調用的event_new主要是對event進行初始化,包括初始化
- 文件描述符/信號值
- 回調函數
- 監聽的事件
- 絕對時間表示的超時時間(如果有的話)
- 在激活隊列中的優先級
- …
總之就是各種初始化,沒有什么特別之處,在設計過程中需要用到什么,就在struct event結構體中添加什么,然后在event_new中初始化什么
event詳解參考event操作
添加event到base時調用的event_add主要是將event注冊到base中,包括
- 添加event到注冊隊列中
- 添加event到io map/signal map中,同時將其添加到io多路復用函數中,信號會單獨處理
- 添加event到最小堆中(如果設置了超時時間的話)
對信號的處理參考統一事件源
第二個參數可以指定超時時長,可以參考時間管理
開啟事件驅動主循環時調用的event_base_dispatch主要就是進入while循環,包括
- 確認io多路復用函數的阻塞時長,方法是選取最小的絕對超時時間(最小堆堆頂)
- 調用io多路復用函數,如果有某事件發生,將其添加到base的激活隊列中,激活原因為事件發生
- 判斷最小堆中的event是否超時,如果超時,方法激活隊列中,激活原因為超時
- 按照優先級順序處理激活隊列中的event,調用對應的回調函數
選擇io多路復用函數的阻塞時長為最小堆堆頂的原因:
- 為了滿足可以監控具有超時時間的event,必須為io函數提供一個阻塞時長,不能是NULL,否則會一直等到有事件發生
- 因為是絕對時間,所以當堆頂的event超時,最小堆其他event不可能已經超時,所以不會影響其他具有超時時間的event,更不會影響沒有超時時間的event
- 綜上選擇堆頂超時時間最為合適
總結
以上是生活随笔為你收集整理的libevent源码学习-----事件驱动流程分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: libevent源码学习-----Rea
- 下一篇: libevent源码学习-----统一事