国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Nginx 源碼分析第三篇之 ngx_queue 隊列

frontoldman / 1926人閱讀

摘要:相關系列前面分析了數組,現在看一下隊列和哈希表的實現。隊列是一個雙向鏈表,實現了一個隊列的操作邏輯。它們都將鏈表節點塞入數據結構。對于常用的解決沖突的方法有線性探測二次探測和開鏈法等。

  

相關系列:http://www.codefrom.com/p/nginx

前面分析了ngx_array_t數組,現在看一下ngx_queue隊列和ngx_hash哈希表的實現。

ngx_queue 隊列

ngx_queue_t是一個雙向鏈表,實現了一個隊列的操作邏輯。但是它的結構只行指針的操作,因而在定義自己的節點時,需要自己定義數據結構和分配空間,并包含一個ngx_queue_t類型的成員。

typedef struct ngx_queue_s ngx_queue_t;

struct ngx_queue_s {
    ngx_queue_t  *prev;
    ngx_queue_t  *next;
};

這和Linux內核的數據結構很像。它們都將鏈表節點塞入數據結構。Linux內核的鏈表這樣定義:

struct list_head
{
    struct list_head *next;
    struct list_head *prev;
}

使用的時候

struct fox
{
    unsigned long tail_length;
    unsigned long weight;
    bool  is_fantastic;
    struct list_head list;
}

結構如圖所示:

所以它用fox.list.next指向下一個節點,用fox.list.prev指向上一個節點。那我們如何從list_head找到fox的地址呢。內核提供了一個container_of()宏可以從鏈表指針找到父結構中包含的任何變量。

#define container_of(ptr, type, member) ({  
    const typeof( ((type *)0)->member ) *__mptr = (ptr); 
(type *)( (char *)__mptr - offsetof(type,member) );)

而在Nginx也是效仿采用一樣的宏獲取父結構地址。

#define ngx_queue_data(q, type, link)   
    (type *) ((u_char *) q - offsetof(type, link))
用法

它的API定義了初始化,插入,排序,找中位節點等一系列操作。

用法如下:

typedef struct yahoo_s {
    ngx_queue_t   queue;
} yahoo_t;

typedef struct yahoo_guy_s {
    ngx_uint_t    id;
    u_char*       name;
    ngx_queue_t   queue;
} yahoo_guy_t;

ngx_int_t yahoo_no_cmp(const ngx_queue_t* p, const ngx_queue_t* n)
{
    yahoo_guy_t *pre, *next;
    pre  = (yahoo_guy_t*) ngx_queue_data(p, yahoo_guy_t, queue);
    next = (yahoo_guy_t*) ngx_queue_data(n, yahoo_guy_t, queue);
    return ((pre->id > next->id) ? 1:0);
}

int main()
{
    ngx_pool_t*     pool;
    yahoo_guy_t*    guy;
    ngx_queue_t*    q;
    yahoo_t*        yahoo;
    pool= ngx_create_pool(1024*10, NULL); //初始化內存池
    int i;
    // 構建隊列
    const ngx_str_tnames[] = {
ngx_string("rainx"), ngx_string("xiaozhe"), ngx_string("zhoujian")} ;
    const in ids[] = {4611, 8322, 6111};

    yahoo = ngx_palloc(pool, sizeof(yahoo_t));
    ngx_queue_init(&yahoo->queue); //初始化queue

    for(i = 0; i < 3; i++)
    {
      guy = (yahoo_guy_t*) ngx_palloc(pool, sizeof(yahoo_guy_t));
      guy->id   = ids[i];
      guy->name = (u_char*) ngx_pstrdup(pool, (ngx_str_t*) &(names[i]) );
      ngx_queue_init(&guy->queue);
      // 從頭部進入隊列
      ngx_queue_insert_head(&yahoo->queue, &guy->queue);
    }

    // 從尾部遍歷輸出
    for(q = ngx_queue_last(&yahoo->queue);
        q != ngx_queue_sentinel(&yahoo->queue);
        q = ngx_queue_prev(q) ) {
        guy = ngx_queue_data(q, yahoo_guy_t, queue);
        printf("No. %d guy in yahoo is %s 
", guy->id, guy->name);
    }

    // 排序從頭部輸出
    ngx_queue_sort(&yahoo->queue, yahoo_no_cmp);
    printf("sorting....
");
    for(q = ngx_queue_prev(&yahoo->queue);
        q != ngx_queue_sentinel(&yahoo->queue);
        q = ngx_queue_last(q) ) {
        guy = ngx_queue_data(q, yahoo_guy_t, queue);
        printf("No. %d guy in yahoo is %s 
", guy->id, guy->name);
    }

    ngx_destroy_pool(pool);
    return 0;
}
ngx_hash 哈希表

ngx_hash表所用的hash算法為分桶后線性查找法,因而查找效率同key-value對成反比。對于常用的解決沖突的方法有線性探測、二次探測和開鏈法等。這里使用的是最常用的開鏈法(也是STL中使用的方法)。

哈希表整個結構如圖所示:

哈希表用下列數據結構進行管理

typedef struct {
    ngx_hash_t       *hash;
    ngx_hash_key_pt   key;

    ngx_uint_t        max_size;
    ngx_uint_t        bucket_size;
    char             *name;
    ngx_pool_t       *pool;
    ngx_pool_t       *temp_pool;
} ngx_hash_init_t;

在使用過程中,先會用ngx_hash_init_t實例化(類似于OOP思想,和內核驅動的用法相同)一個hash_init。

然后對這個“對象”賦值。

hash = (ngx_hash_t*)ngx_pcalloc(pool, sizeof(hash));
hash_init.hash = hash;            // hash結構
hash_init.key = &ngx_hash_key_lc; // hash算法函數
hash_init.max_size = 1024*10;     // max_size
hash_init.bucket_size = 64;       //桶的大小
hash_init.name = "yahoo_guy_hash"; 
hash_init.pool = pool;            // 用到的內存池
hash_init.temp_pool = NULL;

第一行分配了ngx_hash_t大小的內存存儲如下hash結構。

typedef struct {
    ngx_hash_elt_t  **buckets;
    ngx_uint_t        size;
} ngx_hash_t;

然后創建一個需要加到hash table中的數組。

ngx_hash_key_t* arr_node; //存儲鍵值對+hash值
elements = ngx_array_create(pool, 32, sizeof(ngx_hash_key_t));
for(i = 0; i < 3; i++) {
    arr_node = (ngx_hash_key_t*) ngx_array_push(elements);
    arr_node->key = (names[i]);
    arr_node->key_hash = ngx_hash_key_lc(arr_node->key.data, 
    arr_node->key.len);
    arr_node->value = (void*)descs[i];
}

ngx_hash_init(&hash_init, (ngx_hash_key_t*) elements->elts, 
elements->nelts)

最后將elements數組放到hash_init結構中,即將數組以hash table形式存儲。

這就是整個hash結構的存儲過程,查找相對簡單,這里不再詳述。

參考

Linux Kernel Development. Page71~72

http://www.embedu.org/Column/Column433.htm


tuzhi / 2015-05-31

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/39169.html

相關文章

  • React Fiber源碼分析 三篇(異步狀態)

    摘要:系列文章源碼分析第一篇源碼分析第二篇同步模式源碼分析第三篇異步狀態源碼分析第四篇歸納總結前言是在版本中的大更新,利用了閑余時間看了一些源碼,做個小記錄流程圖源碼分析調用時,會調用的方法,同時將新的作為參數傳進會先調用獲取一個維護兩個時間一個 系列文章 React Fiber源碼分析 第一篇 React Fiber源碼分析 第二篇(同步模式) React Fiber源碼分析 第三篇(...

    worldligang 評論0 收藏0
  • 計劃在2021年進行響應式開發?但不確定應該選擇哪種技術來快速且低成本的開發應用程序?一文給你解決問

    摘要:與此同時,因新冠疫情的影響使得用戶對移動應用程序的需求激增。調查報告顯示年移動應用程序已經產生了億美元的收入,預計到年將產生億美元的收入。 引言 計劃在2021年進...

    Codeing_ls 評論0 收藏0
  • Flutter是跨平臺開發終極之選嗎?Android開發該如何快速上手Flutter?

    摘要:月日,谷歌正式發布了的。到底能不能成為跨平臺開發終極之選是基于前端誕生的,但是對前端開發來說,的環境配置很麻煩,需要原生的平臺知識,還要擔心遇上網絡問題。現在已經不是曾經的小眾框架,這兩年里它已經逐步成長為主流的跨平臺開發框架之一。 ...

    luckyyulin 評論0 收藏0
  • PHP小知識點

    摘要:那些瑣碎的知識點作者記錄的的很奇特很難記的知識點。易錯知識點整理注意和的區別中和都是輸出的作用,但是兩者之間還是有細微的差別。今天手頭不忙,總結一下,分享過程中掌握的知識點。 深入理解 PHP 之:Nginx 與 FPM 的工作機制 這篇文章從 Nginx 與 FPM 的工作機制出發,探討配置背后的原理,讓我們真正理解 Nginx 與 PHP 是如何協同工作的。 PHP 那些瑣碎的知識...

    hover_lew 評論0 收藏0
  • React Fiber源碼分析 第四篇(歸納總結)

    摘要:為什么網頁性能會變高要回答這個問題,需要回頭看是單線程的知識點。在分析的過程中,發現了的源碼中使用了很多鏈式結構,回調鏈,任務鏈等,這個主要是為了增刪時性能比較高 系列文章 React Fiber源碼分析 第一篇 React Fiber源碼分析 第二篇(同步模式) React Fiber源碼分析 第三篇(異步狀態) React Fiber源碼分析 第四篇(歸納總結) 前言 Rea...

    jsdt 評論0 收藏0

發表評論

0條評論

frontoldman

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<