一 記憶體池的代碼結構
/*****************************************************************
* * Managing free storage blocks... *from os.c in apache v1.3.34 */ union align { /* Types which are likely to have the longest RELEVANT alignment * restrictions... */ char *cp; void (*f) (void); long l; FILE *fp; double d;}; union block_hdr { union align a; /* Actual header... */ struct { char *endp; union block_hdr *next; char *first_avail;#ifdef POOL_DEBUG union block_hdr *global_next; struct pool *owning_pool;#endif } h;}; struct pool { union block_hdr *first; union block_hdr *last; struct cleanup *cleanups; struct process_chain *subprocesses; struct pool *sub_pools; struct pool *sub_next; struct pool *sub_prev; struct pool *parent; char *free_first_avail;#ifdef ALLOC_USE_MALLOC void *allocation_list;#endif#ifdef POOL_DEBUG struct pool *joined;#endif}; //複雜的鏈表結構,支援嵌套定義//從記憶體池裡擷取記憶體pool * ap_get_shared_mem_pool(size_t size){ pool *new_pool; union block_hdr *blok; blok = (union block_hdr *) ap_tpf_get_shared_mem(size); /* if shm fails, it will exit blok will be valid here */ memset((char *) blok, '/0', size); blok->h.next = NULL; blok->h.first_avail = (char *) (blok + 1); blok->h.endp = size + blok->h.first_avail; new_pool = (pool *) blok->h.first_avail; blok->h.first_avail += POOL_HDR_BYTES; new_pool->free_first_avail = blok->h.first_avail; new_pool->first = new_pool->last = blok; return new_pool;} /***************************************************************** * *from http_main.c in apache v1.3.34 */static pool *pglobal; /* Global pool */static pool *pconf; /* Pool for config stuff */static pool *plog; /* Pool for error-logging files */static pool *ptrans; /* Pool for per-transaction stuff */static pool *pchild; /* Pool for httpd child stuff */static pool *pmutex; /* Pool for accept mutex in child */static pool *pcommands; /* Pool for -C and -c switches */
二 文檔說明
這種工作方式是這樣:用於處理特定請求而分配的記憶體、開啟的檔案 與一個為該請求分配的資源集區綁定。池是一個自身跟蹤問題資源的資料結構。
然而,使用它有兩個好處: 分配到池中的記憶體永遠不會泄漏(即使你分配了一個臨時串又忘了釋放它); 以及,對於記憶體配置,ap_palloc通常比malloc快。
池中的記憶體配置
調用
ap_palloc把記憶體配置到池中,它有兩個參數, 一個是指向資源集區資料結構的指標,另一個是要分配的記憶體數量(按
char計算)。 在要求處理常式內部,得到資源集區指標的最普通的方式是察看相關的
request_rec結構的
pool槽; 因此模組代碼中常見下列程式段重複出現:
int my_handler(request_rec *r)
{
struct my_structure *foo;
...
foo = (foo *)ap_palloc (r->pool, sizeof(my_structure));
} 注意沒有ap_pfree函數 --- ap_palloc分配的記憶體只在相關聯的資源集區清空時被釋放。這意味著ap_palloc不必做像malloc()那樣多的計算; 典型情況下它要做的就是對齊分配大小,產生塊指標,再做一個範圍檢查。(也存在ap_palloc的重負載使用導致一個服務進程變得過份龐大的可能性。有兩個解決辦法;簡單地,你可以用malloc並確信所有分配的記憶體都顯式地用 free釋放了,或者你可以在主資源集區裡分配一個子資源集區, 在子資源集區裡分配記憶體並周期性地清空它。後一個技術在下面關於子資源集區的章節裡有討論,,在列目錄的代碼中有實際使用,主要是為了對數以千計的檔案列目錄時避免過多的儲存分配。)。注釋:ap_palloc ap_pcalloc from allow.c分配初始化的記憶體有幾個函數用於分配初始化的記憶體,使用很頻繁。 函數ap_pcalloc與ap_palloc有同樣的介面,但是會在返回之前清零所分配記憶體。 函數ap_pstrdup以一個資源集區和一個char *為參數,為指標指向的字串的拷貝分配記憶體並返回拷貝的指標。 最後ap_pstrcat是個參數表可變的函數,它的參數有一個資源集區指標和至少兩個以NULL結尾的char *。它要為每個字串的拷貝的合并分配足夠的記憶體。例如:ap_pstrcat (r->pool, "foo", "/", "bar", NULL); 返回一個指向包含8個位元組、已被初始化為"foo/bar"的一塊記憶體的指標。