1. 程式人生 > >nginx原始碼分析—記憶體池結構ngx_pool_t及記憶體管理

nginx原始碼分析—記憶體池結構ngx_pool_t及記憶體管理

本部落格(http://blog.csdn.net/livelylittlefish)貼出作者(阿波)相關研究、學習內容所做的筆記,歡迎廣大朋友指正!

Content

0.

1. 記憶體池結構

1.1 ngx_pool_t結構

1.2 其他相關結構

1.3 ngx_pool_t的邏輯結構

2. 記憶體池操作

2.1 建立記憶體池

2.2 銷燬記憶體池

2.3 重置記憶體池

2.4 分配記憶體

2.4.1 ngx_palloc()函式分析

2.4.2 ngx_palloc_block()函式分析

2.5 釋放記憶體

2.6 註冊cleanup

2.7 記憶體池的物理結構

3. 一個例子

3.1 程式碼

3.2 如何編譯

3.3 執行結果

4. 小結

5.

致謝

0.

nginx對記憶體的管理由其自己實現的記憶體池結構ngx_pool_t來完成,本文重點敘述nginx的記憶體管理。

nginx記憶體管理相關檔案:

(1) ./src/os/unix/ngx_alloc.h/.c

  • 記憶體相關的操作,封裝了最基本的記憶體分配函式
  • free/malloc/memalign/posix_memalign,分別被封裝為ngx_freengx_alloc/ngx_calloc, ngx_memalign
    • ngx_alloc:封裝malloc分配記憶體
    • ngx_calloc:封裝malloc分配記憶體,並初始化空間內容為0
    • ngx_memalign:返回基於一個指定alignment的大小為
      size的記憶體空間,且其地址為alignment的整數倍,alignment2的冪。

(2) ./src/core/ngx_palloc.h/.c

  • 封裝建立/銷燬記憶體池,從記憶體池分配空間等函式

.表示nginx-1.0.4程式碼目錄,本文為/usr/src/nginx-1.0.4

1. 記憶體池結構

nginx對記憶體的管理均統一完成,例如,在特定的生命週期統一建立記憶體池(main函式系統啟動初期即分配1024B大小的記憶體池),需要記憶體時統一分配記憶體池中的記憶體,在適當的時候釋放記憶體池的記憶體(如關閉http連結時呼叫ngx_destroy_pool進行銷燬)

因此,開發者只需在需要記憶體時進行申請即可,不用過多考慮記憶體的釋放等問題,大大提高了開發的效率。先看一下記憶體池結構。

1.1 ngx_pool_t結構

此處統一一下概念,記憶體池的資料塊:即分配記憶體在這些資料塊中進行,一個記憶體池可以有多一個記憶體池資料塊。nginx的記憶體池結構如下。 

00048: typedef struct {
00049:   u_char      *last;  //當前記憶體池分配到此處,即下一次分配從此處開始
00050:   u_char      *end;   //記憶體池結束位置
00051:   ngx_pool_t  *next;  //記憶體池裡面有很多塊記憶體,這些記憶體塊就是通過該指標連成連結串列的
00052:   ngx_uint_t  failed; //記憶體池分配失敗次數
00053: } ngx_pool_data_t;    //記憶體池的資料塊位置資訊
00054:
00055:
00056: struct ngx_pool_s{    //記憶體池頭部結構
00057:    ngx_pool_data_t     d;       //記憶體池的資料塊
00058:    size_t              max;     //記憶體池資料塊的最大值
00059:    ngx_pool_t         *current; //指向當前記憶體池
00060:    ngx_chain_t        *chain;   //該指標掛接一個ngx_chain_t結構
00061:    ngx_pool_large_t   *large;   //大塊記憶體連結串列,即分配空間超過max的記憶體
00062:    ngx_pool_cleanup_t *cleanup; //釋放記憶體池的callback
00063:    ngx_log_t          *log;     //日誌資訊
00064: };

其中,sizeof(ngx_pool_data_t)=16Bsizeof(ngx_pool_t)=40B
nginx將幾乎所有的結構體放在ngx_core.h檔案中重新進行了申明,如下。

typedef struct ngx_module_s      ngx_module_t;
typedef struct ngx_conf_s        ngx_conf_t;
typedef struct ngx_cycle_s       ngx_cycle_t;
typedef struct ngx_pool_s        ngx_pool_t;
typedef struct ngx_chain_s       ngx_chain_t;
typedef struct ngx_log_s         ngx_log_t;
typedef struct ngx_array_s       ngx_array_t;
typedef struct ngx_open_file_s   ngx_open_file_t;
typedef struct ngx_command_s     ngx_command_t;
typedef struct ngx_file_s        ngx_file_t;
typedef struct ngx_event_s       ngx_event_t;
typedef struct ngx_event_aio_s   ngx_event_aio_t;
typedef struct ngx_connection_s  ngx_connection_t;

1.2 其他相關結構

其他與記憶體池相干的資料結構,如清除資源的cleanup連結串列,分配的大塊記憶體連結串列等,如下。

00015: /*
00016: * NGX_MAX_ALLOC_FROM_POOL should be (ngx_pagesize - 1), i.e. 4095 on x86.
00017: * On Windows NT it decreases a number of locked pages in a kernel.
00018: */
00019: #define NGX_MAX_ALLOC_FROM_POOL (ngx_pagesize - 1)  //在x86體系結構下,該值一般為4096B,即4K
00020:
00021: #define NGX_DEFAULT_POOL_SIZE    (16* 1024)
00022:
00023: #define NGX_POOL_ALIGNMENT    16
00024: #define NGX_MIN_POOL_SIZE    \
00025:    ngx_align((sizeof(ngx_pool_t) + 2 * sizeof(ngx_pool_large_t)),    \
00026:    NGX_POOL_ALIGNMENT)
00027:
00028:
00029: typedef void (*ngx_pool_cleanup_pt)(void *data);    //cleanup的callback型別
00030:
00031: typedef struct ngx_pool_cleanup_s ngx_pool_cleanup_t;
00032:
00033: struct ngx_pool_cleanup_s{
00034:    ngx_pool_cleanup_pt handler;
00035:    void    *data;              //指向要清除的資料
00036:    ngx_pool_cleanup_t *next;   //下一個cleanup callback
00037: };
00038:
00039:
00040: typedef struct ngx_pool_large_s ngx_pool_large_t;
00041:
00042: struct ngx_pool_large_s{
00043:    ngx_pool_large_t  *next;    //指向下一塊大塊記憶體
00044:    void    *alloc;             //指向分配的大塊記憶體
00045: };
...
...
00067: typedef struct {
00068:    ngx_fd_t   fd;
00069:    u_char    *name;
00070:    ngx_log_t *log;
00071: } ngx_pool_cleanup_file_t;
00072:

(gdb) p getpagesize()

$18 = 4096

全域性變數ngx_pagesize的初始化是在如下函式中完成的。./src/os/unix/ngx_posix_init.c

ngx_int_t
ngx_os_init(ngx_log_t *log)
{
    ngx_uint_t  n;

#if (NGX_HAVE_OS_SPECIFIC_INIT)
    if (ngx_os_specific_init(log) != NGX_OK) {
        return NGX_ERROR;
    }
#endif

    ngx_init_setproctitle(log);

    /** 該函式為glibc的庫函式,由系統呼叫實現,返回核心中的PAGE_SIZE,該值依賴體系結構*/
    ngx_pagesize = getpagesize();      
    ngx_cacheline_size = NGX_CPU_CACHE_LINE;
    ...
}

這些資料結構之間的關係,請參考後面的圖。

1.3 ngx_pool_t的邏輯結構

這些資料結構邏輯結構圖如下。注:本文采用UML的方式畫出該圖。

2. 記憶體池操作

2.1 建立記憶體池

建立記憶體池有ngx_create_pool()函式完成,程式碼如下。

00015: ngx_pool_t *
00016: ngx_create_pool(size_t size, ngx_log_t *log)
00017: {
00018:    ngx_pool_t *p;
00019:
00020:    p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);
00021:    if (p == NULL) {
00022:       return NULL;
00023:    }
00024:
00025:    p->d.last = (u_char *) p + sizeof(ngx_pool_t);  //last指向ngx_pool_t結構體之後資料取起始位置
00026:    p->d.end = (u_char *) p + size;  //end指向分配的整個size大小的記憶體的末尾
00027:    p->d.next = NULL;
00028:    p->d.failed = 0;
00029:
00030:    size = size - sizeof(ngx_pool_t);
00031:    p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;  //最大不超過4095B
00032:
00033:    p->current = p;
00034:    p->chain = NULL;
00035:    p->large = NULL;
00036:    p->cleanup = NULL;
00037:    p->log = log;
00038:
00039:    return p;
00040: }

例如,呼叫ngx_create_pool(1024, 0x80d1c4c)後,建立的記憶體池物理結構如下圖。

2.2 銷燬記憶體池

銷燬記憶體池由如下函式完成。

void ngx_destroy_pool(ngx_pool_t *pool)

該函式將遍歷記憶體池連結串列,所有釋放記憶體,如果註冊了clenup(也是一個連結串列結構)亦將遍歷該cleanup連結串列結構依次呼叫clenuphandler清理。同時,還將遍歷large連結串列,釋放大塊記憶體。

2.3 重置記憶體池

重置記憶體池由下面的函式完成。

void ngx_reset_pool(ngx_pool_t *pool);

該函式將釋放所有large記憶體,並且將d->last指標重新指向ngx_pool_t結構之後資料區的開始位置,同剛建立後的位置相同。

2.4 分配記憶體

記憶體分配的函式如下。

void *ngx_palloc(ngx_pool_t *pool, size_t size);

void *ngx_pnalloc(ngx_pool_t *pool, size_t size);

void *ngx_pcalloc(ngx_pool_t *pool, size_t size);

void *ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment);

返回值為分配的記憶體起始地址。選擇其中的兩個函式進行分析,其他的也很好理解,省略。

2.4.1 ngx_palloc()函式分析

ngx_palloc()程式碼如下,分析請參考筆者所加的註釋。

00115: void *
00116: ngx_palloc(ngx_pool_t *pool, size_t size)
00117: {
00118:    u_char    *m;
00119:    ngx_pool_t *p;
00120:
00121:    if (size <= pool->max) {//判斷待分配記憶體與max值
00122:
00123:       p = pool->current;   //小於max值,則從current節點開始遍歷pool連結串列
00124:
00125:       do {
00126:          m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);
00127:
00128:          if ((size_t) (p->d.end - m) >= size) {
00129:             p->d.last = m + size;  //在該節點指向的記憶體塊中分配size大小的記憶體
00130:
00131:             return m;
00132:          }
00133:
00134:          p = p->d.next;
00135:
00136:       } while (p);
00137:
00138:       return ngx_palloc_block(pool, size); //連結串列裡沒有能分配size大小記憶體的節點,則生成一個新的節點並在其中分配記憶體
00139:    }
00140:
00141:    return ngx_palloc_large(pool, size);  //大於max值,則在large連結串列裡分配記憶體
00142: }

例如,在2.1節中建立的記憶體池中分配200B的記憶體,呼叫ngx_palloc(pool, 200)後,該記憶體池物理結構如下圖。

2.4.2 ngx_palloc_block()函式分析

ngx_palloc_block函式程式碼如下,分析請參考筆者所加的註釋。

00175: static void *
00176: ngx_palloc_block(ngx_pool_t *pool, size_t size)
00177: {
00178:    u_char    *m;
00179:    size_t    psize;
00180:    ngx_pool_t *p, *new, *current;
00181:
00182:    psize = (size_t) (pool->d.end - (u_char *) pool);      //計算pool的大小
00183:
00184:    m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log);//分配一塊與pool大小相同的記憶體
00185:    if (m == NULL) {
00186:       return NULL;
00187:    }
00188:
00189:    new = (ngx_pool_t *) m;
00190:
00191:    new->d.end = m + psize; //設定end指標
00192:    new->d.next = NULL;
00193:    new->d.failed = 0;
00194:
00195:    m += sizeof(ngx_pool_data_t); //讓m指向該塊記憶體ngx_pool_data_t結構體之後資料區起始位置
00196:    m = ngx_align_ptr(m, NGX_ALIGNMENT); //按4位元組對齊
00197:    new->d.last = m + size;       //在資料區分配size大小的記憶體並設定last指標
00198:
00199:    current = pool->current;
00200:
00201:    for (p = current; p->d.next; p = p->d.next) {
00202:       if (p->d.failed++ > 4) {   //failed的值只在此處被修改
00203:          current = p->d.next;    //失敗4次以上移動current指標
00204:       }
00205:    }
00206:
00207:    p->d.next = new;  //將這次分配的記憶體塊new加入該記憶體池
00208:
00209:    pool->current = current ? current : new;
00210:
00211:    return m;
00212: }

注意:該函式分配一塊記憶體後,last指標指向的是ngx_pool_data_t結構體(大小16B)之後資料區的起始位置。而建立記憶體池時時,last指標指向的是ngx_pool_t結構體(大小40B)之後資料區的起始位置。

結合2.7節的記憶體池的物理結構,更容易理解。

2.5釋放記憶體

請參考如下函式,不再贅述。 

ngx_int_tngx_pfree(ngx_pool_t *pool, void *p)

需要注意的是該函式只釋放large連結串列中註冊的記憶體,普通記憶體在ngx_destroy_pool中統一釋放。

2.6 註冊cleanup

請參考如下函式,該函式實現也很簡單,此處不再贅述。

ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size)

2.7 記憶體池的物理結構

針對本文第3節的例子,畫出的記憶體池的物理結構如下圖。

  

從該圖也能看出2.4節的結論,即記憶體池第一塊記憶體前40位元組為ngx_pool_t結構,後續加入的記憶體塊前16個位元組為ngx_pool_data_t結構,這兩個結構之後便是真正可以分配記憶體區域。

因此,本文Reference中的記憶體分配相關中的圖是有一點點小問題的,並不是每一個節點的前面都是ngx_pool_t結構。

3. 一個例子

理解並掌握開源軟體的最好方式莫過於自己寫一些測試程式碼,或者改寫軟體本身,並進行除錯來進一步理解開源軟體的原理和設計方法。本節給出一個建立記憶體池並從中分配記憶體的簡單例子。

3.1程式碼

/**
 * ngx_pool_t test, to test ngx_palloc, ngx_palloc_block, ngx_palloc_large
 */

#include <stdio.h>
#include "ngx_config.h"
#include "ngx_conf_file.h"
#include "nginx.h"
#include "ngx_core.h"
#include "ngx_string.h"
#include "ngx_palloc.h"

volatile ngx_cycle_t  *ngx_cycle;

void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
            const char *fmt, ...)
{
}

void dump_pool(ngx_pool_t* pool)
{
    while (pool)
    {
        printf("pool = 0x%x\n", pool);
        printf("  .d\n");
        printf("    .last = 0x%x\n", pool->d.last);
        printf("    .end = 0x%x\n", pool->d.end);
        printf("    .next = 0x%x\n", pool->d.next);
        printf("    .failed = %d\n", pool->d.failed);
        printf("  .max = %d\n", pool->max);
        printf("  .current = 0x%x\n", pool->current);
        printf("  .chain = 0x%x\n", pool->chain);
        printf("  .large = 0x%x\n", pool->large);
        printf("  .cleanup = 0x%x\n", pool->cleanup);
        printf("  .log = 0x%x\n", pool->log);
        printf("available pool memory = %d\n\n", pool->d.end - pool->d.last);
        pool = pool->d.next;
    }
}

int main()
{
    ngx_pool_t *pool;

    printf("--------------------------------\n");
    printf("create a new pool:\n");
    printf("--------------------------------\n");
    pool = ngx_create_pool(1024, NULL);
    dump_pool(pool);

    printf("--------------------------------\n");
    printf("alloc block 1 from the pool:\n");
    printf("--------------------------------\n");
    ngx_palloc(pool, 512);
    dump_pool(pool);

    printf("--------------------------------\n");
    printf("alloc block 2 from the pool:\n");
    printf("--------------------------------\n");
    ngx_palloc(pool, 512);
    dump_pool(pool);

    printf("--------------------------------\n");
    printf("alloc block 3 from the pool :\n");
    printf("--------------------------------\n");
    ngx_palloc(pool, 512);
    dump_pool(pool);

    ngx_destroy_pool(pool);
    return 0;
}

3.2如何編譯

這個問題是編寫測試程式碼或者改寫軟體本身最迫切需要解決的問題,否則,編寫的程式碼無從編譯或執行,那也無從進行除錯並理解軟體了。

CXX = gcc
CXXFLAGS += -g -Wall -Wextra

NGX_ROOT = /usr/src/nginx-1.0.4

TARGETS = ngx_pool_t_test
TARGETS_C_FILE = $(TARGETS).c

CLEANUP = rm -f $(TARGETS) *.o

all: $(TARGETS)

clean:
	$(CLEANUP)

CORE_INCS = -I. \
	-I$(NGX_ROOT)/src/core \
	-I$(NGX_ROOT)/src/event \
	-I$(NGX_ROOT)/src/event/modules \
	-I$(NGX_ROOT)/src/os/unix \
	-I$(NGX_ROOT)/objs \

NGX_PALLOC = $(NGX_ROOT)/objs/src/core/ngx_palloc.o
NGX_STRING = $(NGX_ROOT)/objs/src/core/ngx_string.o
NGX_ALLOC = $(NGX_ROOT)/objs/src/os/unix/ngx_alloc.o

$(TARGETS): $(TARGETS_C_FILE)
	$(CXX) $(CXXFLAGS) $(CORE_INCS) $(NGX_PALLOC) $(NGX_STRING) $(NGX_ALLOC) $^ -o [email protected]

3.3執行執行結果

# ./ngx_pool_t_test
--------------------------------
create a new pool:
--------------------------------
pool = 0x8922020
  .d
    .last = 0x8922048
    .end = 0x8922420
    .next = 0x0
    .failed = 0
  .max = 984
  .current = 0x8922020
  .chain = 0x0
  .large = 0x0
  .cleanup = 0x0
  .log = 0x0
available pool memory = 984

--------------------------------
alloc block 1 from the pool:
--------------------------------
pool = 0x8922020
  .d
    .last = 0x8922248
    .end = 0x8922420
    .next = 0x0
    .failed = 0
  .max = 984
  .current = 0x8922020
  .chain = 0x0
  .large = 0x0
  .cleanup = 0x0
  .log = 0x0
available pool memory = 472

--------------------------------
alloc block 2 from the pool:
--------------------------------
pool = 0x8922020
  .d
    .last = 0x8922248
    .end = 0x8922420
    .next = 0x8922450
    .failed = 0
  .max = 984
  .current = 0x8922020
  .chain = 0x0
  .large = 0x0
  .cleanup = 0x0
  .log = 0x0
available pool memory = 472

pool = 0x8922450
  .d
    .last = 0x8922660
    .end = 0x8922850
    .next = 0x0
    .failed = 0
  .max = 0
  .current = 0x0
  .chain = 0x0
  .large = 0x0
  .cleanup = 0x0
  .log = 0x0
available pool memory = 496

--------------------------------
alloc block 3 from the pool :
--------------------------------
pool = 0x8922020
  .d
    .last = 0x8922248
    .end = 0x8922420
    .next = 0x8922450
    .failed = 1
  .max = 984
  .current = 0x8922020
  .chain = 0x0
  .large = 0x0
  .cleanup = 0x0
  .log = 0x0
available pool memory = 472

pool = 0x8922450
  .d
    .last = 0x8922660
    .end = 0x8922850
    .next = 0x8922880
    .failed = 0
  .max = 0
  .current = 0x0
  .chain = 0x0
  .large = 0x0
  .cleanup = 0x0
  .log = 0x0
available pool memory = 496

pool = 0x8922880
  .d
    .last = 0x8922a90
    .end = 0x8922c80
    .next = 0x0
    .failed = 0
  .max = 0
  .current = 0x0
  .chain = 0x0
  .large = 0x0
  .cleanup = 0x0
  .log = 0x0
available pool memory = 496

4. 小結

本文針對nginx-1.0.4的記憶體管理進行了較為全面的分析,包括相關記憶體池資料結構,記憶體池的建立、銷燬,以及從記憶體池中分配記憶體等。最後通過一個簡單例子向讀者展示nginx記憶體池的建立和分配操作,同時藉此向讀者展示編譯測試程式碼的方法。

分析完nginx的記憶體管理,你一定驚歎於nginx作者的聰明才智。這種記憶體管理的設計方法小巧、快捷,值得借鑑!

5. 致謝

寫作本文,筆者參考了Reference裡yixiao的Nginx原始碼分析-記憶體池和RainX1982的Nginx程式碼研究計劃。在此給予他們誠摯的感謝!

Reference

man posix_memalign (manual頁)(Allocate aligned memory)

man getpagesize (manual頁)(Get memory page size)

Appendix: posix_memalign

The  function  posix_memalign()  allocates  size  bytes and places theaddress of the allocated memory in*memptr.  The address of the allocated memory will be a multiple of alignment, which must be a  power  oftwo and a multiple of sizeof(void *).

the memory is not zeroed.

posix_memalign() returns zero on success, or one of the error values listed in the next section on  failure.  Note that errno is not set.

相關推薦

nginx原始碼分析記憶體結構ngx_pool_t記憶體管理

本部落格(http://blog.csdn.net/livelylittlefish)貼出作者(阿波)相關研究、學習內容所做的筆記,歡迎廣大朋友指正!Content0. 序1. 記憶體池結構1.1 ngx_pool_t結構1.2 其他相關結構1.3 ngx_pool_t的邏輯

nginx原始碼學習(二) 記憶體結構 ngx_pool_t

1,nginx的記憶體池介紹     為了方便系統模組對記憶體的使用,方便記憶體的管理,nginx自己實現了程序池的機制來進行記憶體的分配和釋放, 首先nginx會在特定的生命週期幫你    統一建立記憶體池,當需要進行記憶體分配的時候統一通過記憶體池中的記憶體進行分配,最

Nginx原始碼分析與實踐---程序間通訊機制(共享記憶體

Nginx有一個master程序和多個worker程序,那麼master程序與worker程序間或worker程序之間是如何通訊的呢,又什麼時候需要程序間通訊呢? 我們知道linux下的程序間通訊方式主要有:管道、FIFO、套接字、訊息佇列、共享記憶體、訊號。那麼nginx的程序間通訊方式採

區塊鏈教程Fabric1.0原始碼分析Peer peer channel命令子命令實現

  區塊鏈教程Fabric1.0原始碼分析Peer peer channel命令及子命令實現,2018年下半年,區塊鏈行業正逐漸褪去發展之初的浮躁、迴歸理性,表面上看相關人才需求與身價似乎正在回落。但事實上,正是初期泡沫的漸退,讓人們更多的關注點放在了區塊鏈真正的技術之上。 Fabric1.0原始碼筆記之P

nginx原始碼分析(5)——監聽socket初始化

在nginx原始碼分析(4)中,看到了nginx的事件模型,但其中沒有介紹監聽socket的初始化。而對於web server來說,需要通過監聽socket來監聽客戶端的連線等。本篇將會具體介紹這方面的內容。還記得在前文介紹ngx_cycle_t結構時,它具有一個listening屬性,是一個數組,

STL原始碼分析之pair結構

前言 前面在分析set, RB-tree都有在insert實現中出現pair, 下節分析map的時候更會經常出現pair, 所以打算在之前先對pair有個認識. pair是一個有兩個變數的結構體, 即誰都可以直接呼叫它的變數, 畢竟struct預設許可權都是public, 將兩個

Mosquitto-1.5.4原始碼分析,PUBLISH的實現函式跳轉關係

客戶端向伺服器傳送資料包(packet)時,首先將資料包放到改傳送佇列中,並不真實發送資料,而是傳送資料就緒訊號,等待loop事件迴圈呼叫的函式db__message_write根據網路連線情況來處理髮送請求;該佇列為單鏈表儲存結構,每次有新資料包需要傳送時,將新資料包插入到連結串列尾部;真正傳

nginx原始碼分析之變數

nginx中的變數在nginx中的使用非常的多,正因為變數的存在,使得nginx在配置上變得非常靈活。 我們知道,在nginx的配置檔案中,配合變數,我們可以動態的得到我們想要的值。最常見的使用是,我們在寫access_log的格式時,需要用到多很多變數。 而這些變數是如何工作的呢?我們可以輸出哪些變數?我

記憶體的原理實現

在軟體開發中,有些物件使用非常頻繁,那麼我們可以預先在堆中例項化一些物件,我們把維護這些物件的結構叫“記憶體池”。在需要用的時候,直接從記憶體池中拿,而不用從新例項化,在要銷燬的時候,不是直接free/delete,而是返還給記憶體池。 把那些常用的物件存在記憶體池中,就不用頻繁的分配/回收記憶體,可以相對

jQuery 2.0.3 原始碼分析 事件體系結構

那麼jQuery事件處理機制能幫我們處理那些問題? 毋容置疑首先要解決瀏覽器事件相容問題 可以在一個事件型別上新增多個事件處理函式,可以一次新增多個事件型別的事件處理函式 提供了常用事件的便捷方法 支援自定義事件 擴充套件了組合事件 提供了統一的事件封裝、繫結、執行、銷燬機制 …… 為

jQuery原始碼分析之jQuery.event.triggerjQuery.Event十問

問題1:jQuery.event.trigger常見呼叫方式有那些? 例項trigger方法 trigger: function( type, data ) { return this.each(function() { jQuery.event.trigger

Nginx原始碼分析與實踐---程序間通訊機制(訊號)

在前面我們分析了nginx程序間通訊機制的共享記憶體和套接字。這次我們分析剩下一種程序間通訊機制---訊號。 首先要區分訊號和訊號量:訊號是用於程序間通訊的機制,而訊號量是用於保證共享資源不被併發訪問的機制,如可使用訊號量作為互斥鎖實現多程序下對共享資源的同步。 1.nginx中什

Nginx原始碼分析與實踐---程序間通訊機制(套接字)

在上一篇中,我們看到了nginx共享記憶體方式的程序間通訊。這次我們看下nginx使用套接字的程序間通訊方式。 同樣的幾個問題: 1.什麼時候需要使用套接字方式的程序間通訊機制呢? 舉個栗子:我們知道nginx有master程序和worker程序,那麼master程序是如何向w

Nginx原始碼分析與實踐---ngx_command_t

從上一節瞭解到配置項的相關屬性是由ngx_command_t這個結構體設定的,下面就來看其原始碼,分析一下。 .../src/core/ngx_core.h : typedef struct ngx_command_s ngx_command_t;由上可知,以s結尾的和以t

Nginx原始碼分析與實踐---(一)編寫一個簡單的Http模組

在上一節中,我們通過修改配置檔案,便能讓nginx去訪問我們寫的html檔案,並返回給瀏覽器。問題是:nginx是如何檢測到我們寫的配置項的?檢測到後,nginx又是如何知道該進行什麼操作的? 本節通過親自實踐,寫一個經典的Hello World模組來了解相應的流程是如何進行的。我們採用自上

Android Camera 系統架構原始碼分析(4)---->Camera的資料來源Camera的管理

Camera的資料來源及Camera的管理  我們接著第3篇,再返回Cam1DeviceBase::startPreview()的(4) mpCamAdapter->startPreview()。在講(4)前我們先來看看(1)onStartPreview(

nginx原始碼分析(7)——請求處理

        在建立連線過程中,對於nginx監聽到的每個客戶端連線,都會將它的讀事件的handler設定為ngx_http_init_request函式,這個函式就是請求處理的入口。在處理請求時,主要就是要解析http請求,比如:uri,請求行等,然後再根據請求生成響應

Tor原始碼分析二 -- 目錄結構

  Tor由於經過了長年的開發,版本到現在已經有很多。筆者選用的是tor-0.2.3.25版本。關於版本變遷和更新說明,請大家自行檢視: 1. 原始碼目錄關係圖   Tor的原始碼目錄中包括doc, contrib, src等一些列很莫名的檔案。其實,在這些所有的檔案

InnoDB原始碼分析--緩衝(二)

      轉載請附原文連結:http://blog.csdn.net/uncle_six/article/details/51648972      上一篇中我簡單的分析了一下InnoDB緩衝池LRU演算法的相關原始碼,其實說不上是分析,應該是自己的筆記,不過我還是發

nginx原始碼分析

生成的Makefile分析 變數賦值 CC,CFLAGS,CPP,LINK($CC),ALL_INCS(-I...),CORE_DEPS, CORE_INCS, HTTP_DEPS, HTTP_INCS 目標 build:  binary modules manpage b