Ngnix 源碼學習(3)----內存池結構

本篇首先把 內存池結構 大概的說一下,具體使用將在下一節細緻描述

 

首先知道內存池的作用

    爲什麼需要內存池?

a. 在大量的小塊內存的申請和釋放的時候,能更快地進行內存分配(對比malloc和free)

b.減少內存碎片,防止內存泄露。

 

內存池的原理

    內存池的原理非常簡單,用申請一塊較大的內存來代替N多的小內存塊,當有需要malloc一塊

比較小的內存是,直接拿這塊大的內存中的地址來用即可。

    當然,這樣處理的缺點也是很明顯的,申請一塊大的內存必然會導致內存空間的浪費,但是

比起頻繁地malloc和free,這樣做的代價是非常小的,這是典型的以空間換時間。

 

 

Ngnix的內存池使用的數據結構是鏈表。

 

首先

typedef struct ngx_pool_s        ngx_pool_t;


我們知道以上定義 其結構體是什麼樣的呢?

struct ngx_pool_s {
    u_char               *last;
    u_char               *end;
    ngx_pool_t           *current;
    ngx_chain_t          *chain;
    ngx_pool_t           *next;
    ngx_pool_large_t     *large;
    ngx_pool_cleanup_t   *cleanup;
    ngx_log_t            *log;
};

 

以上是0。5版本的,1.0版本有些改變



 

struct ngx_pool_s {
    ngx_pool_data_t       d;//表示數據區域
    size_t                       max;//內存池能容納數據的大小
    ngx_pool_t *             current;//當前內存池塊(nginx中的內存池是又一連串的內存池鏈表組成的)
    ngx_chain_t*             chain;//主要爲了將內存池連接起來
    ngx_pool_large_t*      large;//大塊的數據
    ngx_pool_cleanup_t*  cleanup;//清理函數
    ngx_log_t*                 log;//寫log
};


 

typedef struct {
    u_char               *last;
    u_char               *end;
    ngx_pool_t           *next;
    ngx_uint_t            failed;
} ngx_pool_data_t;


但是原理是一樣的,他把兩個地址進行封裝了struct

看了這個結構,我們想知道這個結構到底是什麼樣的,他的每個數據字段什麼用呢?

再把其他的數據結構貼上來。

typedef struct ngx_chain_s       ngx_chain_t;

struct ngx_chain_s {
    ngx_buf_t    *buf;
    ngx_chain_t  *next;
};

這個一個 內存池的鏈表

而其中的

typedef struct ngx_buf_s  ngx_buf_t;
struct ngx_buf_s {
    u_char          *pos;
    u_char          *last;
    off_t            file_pos;
    off_t            file_last;

    u_char          *start;         /* start of buffer */
    u_char          *end;           /* end of buffer */
    ngx_buf_tag_t    tag;
    ngx_file_t      *file;
    ngx_buf_t       *shadow;


    /* the buf's content could be changed */
    unsigned         temporary:1;

    /*
     * the buf's content is in a memory cache or in a read only memory
     * and must not be changed
     */
    unsigned         memory:1;

    /* the buf's content is mmap()ed and must not be changed */
    unsigned         mmap:1;

    unsigned         recycled:1;
    unsigned         in_file:1;
    unsigned         flush:1;
    unsigned         sync:1;
    unsigned         last_buf:1;
    unsigned         last_in_chain:1;

    unsigned         last_shadow:1;
    unsigned         temp_file:1;

    unsigned         zerocopy_busy:1;

    /* STUB */ int   num;
};


 

下面是一個 大數據池,當申請的內存不夠用的時候,就使用大內存。

typedef struct ngx_pool_large_s  ngx_pool_large_t;
struct ngx_pool_large_s {
    ngx_pool_large_t     *next;
    void                 *alloc;
};
typedef struct {
    ngx_fd_t              fd;
    u_char               *name;
    ngx_log_t            *log;
} ngx_pool_cleanup_file_t;

 

struct ngx_log_s {
    ngx_uint_t           log_level;
    ngx_open_file_t     *file;

    ngx_atomic_uint_t    connection;

    ngx_log_handler_pt   handler;
    void                *data;

    /*
     * we declare "action" as "char *" because the actions are usually
     * the static strings and in the "u_char *" case we have to override
     * their types all the time
     */

    char                *action;
};

 

下面的是用來清理內存的。

typedef struct ngx_pool_cleanup_s  ngx_pool_cleanup_t;

struct ngx_pool_cleanup_s {
    ngx_pool_cleanup_pt   handler;
    void                 *data;
    ngx_pool_cleanup_t   *next;
};


以上是起數據元素了,直接用代碼可能看不懂,但是你要畫出來就可能明白了

如下圖所示

 

今天只是簡單介紹了內存的大概結構,下面一篇文章將介紹如何使用內存池

更多文章歡迎訪問:http://blog.csdn.net/wallwind

 

發佈了270 篇原創文章 · 獲贊 96 · 訪問量 232萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章