1. 程式人生 > >libevent原始碼淺析: http庫

libevent原始碼淺析: http庫

上一篇文章介紹了libevent下基本的I/O事件,這篇文章將講講libevent對定時器和訊號事件的處理.

Timer事件

反應堆event_base包含了一個最小堆min_heap結構體的例項,以此維護註冊到這個反應堆例項的定時器事件:


1.struct event_base
{

2.//其他成員
3.struct min_heap
timeheap;

4.};

回顧一下最小堆min_heap:


1.typedef struct min_heap
2.{
3.//p指向一個動態分配的陣列,陣列元素是event指標.
4.struct event**
p;

5.unsigned
n, a; // n表示目前儲存了多少元素,a表示p指向的記憶體能夠儲存event指標的個數

6.}
min_heap_t;

可以看到,它包含一個連續的記憶體塊用於儲存定時器事件.針對min_heap的操作主要有:


1.static inline int min_heap_push(min_heap_t*
s, struct event* e);

2.static inline struct event* 
min_heap_pop(min_heap_t* s);

其中,min_heap_push()用於插入節點,min_heap_pop()用於彈出節點.其內部邏輯很簡單,不必描述了.

現在看看libevent處理定時器事件的例子:


01.static void timeout_cb(int fd, short event, void *arg)
{...}

02.
03.int main
(int argc, char **argv)

04.{
05.struct event
timeout;

06.struct timeval
tv;

07.
08.event_init();
09.
10.evtimer_set(&timeout,
timeout_cb, &timeout);

11.
12.evutil_timerclear(&tv);
13.tv.tv_sec
= 2;

14.event_add(&timeout,
&tv);

15.
16.lasttime
= time(NULL);

17.
18.event_dispatch();
19.}

首先,和上篇文章例子一樣的,event_init()初始化一個event_base(反應堆例項),然後由evtimer_set()設定定時器事件的回撥函式,接著event_add()把定時器事件加入反應堆例項中.最後進入event_dispatch()主迴圈.

在這裡,evtimer_set定義如下:


1.#define
evtimer_set(ev, cb, arg)    event_set(ev, -1, 0, cb, arg)

至於event_set(),沒有什麼好說的,就是對一個event結構體做初始化罷了.

上一篇文章已經從I/O事件的角度介紹了event_add(),這裡看看它是如何處理定時器事件的:


01.int event_add(struct event
*ev, const struct timeval *tv)

02.{  
03.struct event_base
*base = ev->ev_base;

04.
05.....//處理IO事件或者訊號事件的邏輯.
06.
07.//如果tv不為0
08.if (tv
!= NULL)

09.{
10.event_queue_insert(base,
ev, EVLIST_TIMEOUT);

11.}
12.}

可以看到,event_add()會把一個定時器事件壓入到其對應的反應堆例項下的定時器最小堆timeheap中(&ev->base.timeheap).

回到event_dispatch(),它會呼叫event_base_loop(),此函式對定時器事件處理如下:


01.//事件主迴圈
02.int
03.event_base_loop(struct event_base
*base, int flags)

04.{  
05....//不必多慮的其他程式碼
06.
07.done
= 0;

08.while (!done)
09.{
10.//檢查heap中的timer
events,將就緒的timer event從heap上刪除,並插入到啟用連結串列中,

11.//這意味著base->event_count_active會增加
12.timeout_process(base);
13.
14.//有就緒事件了
15.if (base->event_count_active)
16.{
17.//處理就緒事件吧.
18.event_process_active(base);
19.}
20.}
21.}

其中,timeout_process()會將已超時的定時器事件插入到反應堆例項下的已就緒事件佇列中,接著由event_process_active()處理已就緒事件.event_process_active()程式碼在上一篇文章中已經介紹過了,這裡看一下timeout_process():


01./時間到~~~
02.//開始處理base裡面的定時器堆裡的事件鳥.
03.//檢查heap中的timer
events,將就緒的timer event從heap上刪除,並插入到啟用連結串列中

04.void timeout_process(struct event_base
*base)

05.{
06.struct timeval
now;

07.struct event
*ev;

08.
09.while ((ev
= min_heap_top(&base->timeheap)))

10.{
11.//ev超時時間的比現在的時間大,也就是說,這個ev還沒有超時,那麼while迴圈結束
12.if (evutil_timercmp(&ev->ev_timeout,
&now, >))

13.break;
14.
15.//else
意味著 evutil_timercmp(&ev->ev_timeout, &now, <=)為真

16.//也就說明定時器最小堆的根超時了
17.
18.//從定時器堆刪除
19.event_del(ev);
20.
21.//把它插到啟用連結串列吧.
22.event_active(ev,
EV_TIMEOUT, 1);

23.}
24.

相關推薦

libevent原始碼淺析: http

上一篇文章介紹了libevent下基本的I/O事件,這篇文章將講講libevent對定時器和訊號事件的處理.Timer事件 反應堆event_base包含了一個最小堆min_heap結構體的例項,以此維護註冊到這個反應堆例項的定時器事件:1.struct event_base {2.//其他成員3.struc

小而美的Promise——promiz原始碼淺析

背景 在上一篇部落格[[譯]前端基礎知識儲備——Promise/A+規範](https://segmentfault.com/a/11...,我們介紹了Promise/A+規範的具體條目。在本文中,我們來選擇了promiz,讓大家來看下一個具體的Promise庫的內部程式碼是如何運作的。 promiz是一

優秀開源SDWebImage原始碼淺析

世人都說閱讀原始碼對於功力的提升是十分顯著的, 但是很多的著名開源框架原始碼動輒上萬行, 複雜度實在太高, 這裡只做基礎的分析。 簡潔的介面 首先來介紹一下這個 SDWebImage 這個著名開源框架吧, 這個開源框架的主要作用就是: Asynchronous image downloader w

Python HTTPrequests中文頁面亂碼解決方案!

獲得 使用 http text odin 抽取 from Coding blog 把html編碼類型賦與獲取到文本 獲取html編碼類型: 1.使用apparent_encoding可以獲得真實編碼 1 >>> response.apparent_enc

淺析muduo中的定時器設施

val read eid 就是 RR 重新 cal using dss 一個設計良好的定時器在服務端的應用程序上至關重要,muduo定時器的實現陳碩大牛在書中已經詳細的談過,筆者嘗試從源碼的角度解讀定時器的實現,如果理解不對,歡迎指正。 在muduo的定時器系統中,一共由四

淺析muduo中的線程設施

%d except a* empty fde returns exceptio HR 參數傳遞 muduo是目前我在學習過程中遇到的最具有學習意義的網絡庫,下文將分析muduo庫中的基礎設施--Thread和ThreadPool. 首先,介紹在多線程編程中不可缺少的同步措施

Axios 是一個基於 promise 的 HTTP

else eve stringify http UNC bracket mil validate white NPM地址:https://www.npmjs.com/package/axios安裝使用 npm:$ npm install axios使用 bower:$ bo

用最簡單的方式實現基於libevent框架的http client客戶端

#include <event2/event_struct.h> #include <event2/event.h> #include <event2/bufferevent.h> #include <event2/http.h> #include

基於libevent框架搭建http伺服器

#include <stdlib.h> #include <stdio.h> #include <string.h> //libevent http server header files #include <event2/http.h> #in

重新去認識HashMap(Java8原始碼淺析

加入新公司後一直忙於專案,瘋狂加班,斷更了N個月,一直沒時間去管理自己所學習的新的知識(說白了就是懶。。。),前些天在頭條上看到了一篇關於jdk5,6,7,8,9的一些區別的文章,雖然有所瞭解,但由於自己的專案中用的依舊還是1.6,因此並沒有很多機會去了解一些新版本的一些特性(說白了還是

Android Hook框架adbi原始碼淺析(二)

二、libbase 其實上面載入完SO庫後,hook的功能我們完全可以自己在動態庫中實現。而adbi作者為了方便我們使用,編寫了一個通用的hook框架工具即libbase庫。libbase依然在解決兩個問題:1.獲取要hook的目標函式地址;2.給函式打二進位制補丁即inline hook。 關於獲取ho

Android Hook框架adbi原始碼淺析(一)

adbi(The Android Dynamic Binary Instrumentation Toolkit)是一個Android平臺通用hook框架,基於動態庫注入與inline hook技術實現。該框架由兩個主要模組構成,1.hijack負責將動態庫注入到目標程序;2.libbase提供動態庫本身,它實

c++常用原始碼以及常用查詢

我平時看程式碼主要是C和C++程式碼為主,Java程式碼也會偶爾看一下。平時除了自己積累一些程式碼之外,也會主動去尋找一些程式碼,比如說, (1)到sourceforge上查詢相關程式碼; (2)到google code上面查詢具體的程式碼; (3)到apache網站上尋找ja

攝像頭程式設計大全 原始碼 c http //tmsoft lsxy com/index php load read i

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

linux kernel(二)原始碼淺析

目錄 kernel(二)原始碼淺析 建立工程 啟動簡析 head.s 入口點 查詢處理器 查詢機器ID 啟動MMU 其他操作 start_kernel 處理命令列

FileProvider使用以及原始碼淺析

1. FileProvider的使用 1.1 AndroidManifest.xml中定義 <provider android:name="android.support.v4.content.FileProvider" a

[JDK1.7]LinkedHashMap原始碼淺析

引言 HashMap 是一個無序的 Map,因為每次根據 key 的 hashcode 對映到 Entry 陣列上,所以遍歷出來的順序並不是寫入的順序。LinkedHashMap 的底層是繼承於 HashMap 實現的,由一個雙向連結串列所構成; 一、初識LinkedH

libevent學習之一:libevent原始碼的特點和結構

1.特點 Libevent是一個用於開發可擴充套件性網路伺服器的基於事件驅動(event-driven)模型的網路庫。Libevent有幾個顯著的特點:  (1)事件驅動(event-driven),高效能; (2)輕量級,專注於網路,不如 ACE 那麼臃腫龐大;  (3)原始碼

Django-Rest-Framework 許可權管理原始碼淺析

許可權管理簡單介紹 在django的views中不論是用類方式還是用裝飾器方式來使用rest框架,django_rest_frame實現許可權管理都需要兩個東西的配合:authentication_classes 和 permission_classes # 方式1: 裝飾器 from rest_fram

併發程式設計:LinkedBlockingQueue原始碼淺析

申明:本文是基於jdk1.8的原始碼 LinkedBlockingQueue類圖結構 LinkedBlockingQueue底層基於單向連結串列實現的阻塞佇列,可以當做無界佇列也可以當做有界佇列來使用。 為什麼可以當做無界佇列? 從第一個無參構造方法可知,在沒有