• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            woaidongmao

            文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
            隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
            數據加載中……

            apr_pool -- 內存池

            這個指南主要介紹如何使用libaprapache portable runtime)。
            版權所有,Copyright (C) 2005 INOUE Seiichiro <inoue&ariel-networks.com>,翻譯:成彥
            原文地址:http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial.html
            轉載時請保留版權信息。

            大多數libaprAPI都依賴于內存池,借助內存池,簡化了內存塊的管理。想像一下沒有內存池系統的情況:你申請一些內存塊就必需逐個釋放它們,例如如果你申請了10個內存塊,你必需釋放10次,否則,你將遭受內存泄露的錯誤。內存池解決了這個令人感到繁瑣的問題,在申請一個內存池之后,你可以從內存池中申請多個內存塊,釋放它們的時候,你所需要做的就是銷毀內存池,這樣你就可以釋放所有的內存塊了。這有兩個優點,第一,它可以預防內存泄露的錯誤;第二,分配內存塊的開銷相對變低了。從某種意義上說,內存池迫使你遵循面向會話編程,一個內存池就是一種會話內容,這樣,處于同一個內存池中的對象就有相同的生命周期,你可以通過控制會話內容來控制對象。在一個會話的開始,你創建了一個內存池,接著,你在內存池中創建了一些對象,你不需要去關心這些對象的生命周期,最后,在會話結束的時候,你只需要將那個內存池銷毀就可以了。

            注:通常,對象生命周期控制是程序開發最困難的部分,因此,針對這個問題還存在有一些技術,例如智能指針,垃圾回收機制等等。需要注意,同時使用這些技術有一定的難度,內存池也是這其中的一項技術,所以你不得不非常小心的使用它們。

            注:在將來,libapr的內存池將變得不再那么重要。參見http://mail-archives.apache.org/mod_mbox/apr-dev/200502.mbox/%3c1f1d9820502241330123f955f@mail.gmail.com%3e.

            下面有三個基本的API函數:
            /*
            摘自 apr_pools.h */
                APR_DECLARE(apr_status_t) apr_pool_create(apr_pool_t **newpool, apr_pool_t *parent);
                APR_DECLARE(void *) apr_palloc(apr_pool_t *p, apr_size_t size);
                APR_DECLARE(void) apr_pool_destroy(apr_pool_t *p);

            我們使用apr_pool_create()函數創建一個內存池,這個內存池將一直存活,直到你調用apr_pool_destroy()函數以后被銷毀。apr_pool_create()的第一個參數是一個結果輸出參數,是一個新創建的apr_pool_t類型的內存池對象。通過調用apr_palloc()來申請指定大小的內存塊,具體使用方法見mp-sample.c

            /*
            摘自 mp-sample.c */
                apr_pool_t *mp;
                /*
            創建內存池 */
                apr_pool_create(&mp, NULL);

                /*
            從內存池中分配內存塊 */
                char *buf1;
                buf1 = apr_palloc(mp, MEM_ALLOC_SIZE);

            簡單地說,我們可以像使用malloc(3)這樣使用apr_palloc(),也可以調用apr_pcalloc(),正如你猜到的,apr_pcalloc類似于calloc(3)apr_pcalloc返回一個被0填充了的內存塊。假如你使用了malloc(3)/calloc(3),你需要調用free(3)來釋放分配了的內存。但是在內存池中,你必不需要釋放每個內存塊,你只需要對該內存池調用apr_poll_destroy()函數從而釋放所有的內存塊。

            注:使用apr_palloc()申請內存,其內存塊的大小沒有限制,然而,在內存池中申請大內存并不是什么好主意。內存池本質上是為了更小的內存塊而設計的,實際上,初始的內存池的大小是8000字節。如果你需要申請超過幾兆字節的內存塊時,那么就不要使用內存池。
            注:默認情況下,內存池管理器從不將申請到的內存歸還給系統。如果程序要運行很長時間,這將是一個問題,推薦像下面的代碼那樣指定一個上限:

            /*
            設置上限,讓內存池管理器釋放內存,將內存返回給系統的示例代碼 */

            #define YOUR_POOL_MAX_FREE_SIZE 32      /* apr_pool max free list size */
            apr_pool_t *mp;
            apr_pool_create(&mp, NULL);
            apr_allocator_t* pa = apr_pool_allocator_get(mp);
            if (pa) {
                apr_allocator_max_free_set(pa, YOUR_POOL_MAX_FREE_SIZE);
            }

            這兒有兩個API函數需要知道,一個是apr_pool_clear(),另一個是apr_pool_cleanup_register()apr_pool_clear()類似于apr_pool_destroy(),不同的是內存池將一直存在。示例代碼如下:
            /*
            使用apr_pool_clear()的例子 */
            apr_pool_t *mp;
            apr_pool_create(&mp, NULL);
            for (i = 0; i < n; ++i) {
                do_operation(..., mp);
                apr_pool_clear(mp);
            }
            apr_pool_destroy(mp);

            do_operation()
            里使用了內存池,分配了一些內存塊。假如在do_operation()之外不需要這些內存塊了,可以調用apr_pool_clear()函數,這樣能縮小內存的使用大小。如果你熟悉系統的棧內存的話,你會覺得內存池與棧內存一樣,調用apr_palloc只是如同移動SP(棧指針),調用apr_pool_clear()如同重置SP,兩者都是輕量級的操作。

            使用apr_pool_cleanup_register()函數,可以在內存池清空/銷毀上設定一個鉤子(回調)函數,在內存池清空或是銷毀后調用這個函數,在這個回調函數中,你可以實現任何在內存池上的結束代碼。

            關于內存池的最后一個主題是子池,每個內存池都可以有一個父內存池,因此,內存池構造了樹。apr_pool_create()的第二個參數表示父內存池,當這個參數為NULL時,新創建的內存池將變為一個根內存池,可以在這個根內存池上創建子內存池。在這個樹中對一個內存池調用apr_pool_destroy()函數,則該內存池的子內存池也將被銷毀;當對該內存池調用apr_pool_clear()函數,則這個內存池存在但是它的子內存池將被銷毀,上面提及到的那些清除函數,在子內存池銷毀時被調用。

            注:當將NULL值做為清除回調函數時將會產生一個bug,你必須像下面的代碼那樣傳入apr_pool_cleanup_null
            /*
            關于內存池典型bug的偽代碼 */
            /* apr_pool_cleanup_register(mp, ANY_CONTEXT_OF_YOUR_CODE, ANY_CALLBACK_OF_YOUR_CODE, NULL);
            這將產生一個bug */
            /*
            修正: */
            apr_pool_cleanup_register(mp, ANY_CONTEXT_OF_YOUR_CODE, ANY_CALLBACK_OF_YOUR_CODE, apr_pool_cleanup_null);

             

            posted on 2011-03-31 13:02 肥仔 閱讀(5354) 評論(0)  編輯 收藏 引用 所屬分類: Windows開發

            久久午夜无码鲁丝片秋霞 | 国产美女久久精品香蕉69| 国产一区二区精品久久凹凸| 久久精品中文字幕无码绿巨人| 久久伊人精品一区二区三区| 久久综合久久综合亚洲| 无码人妻少妇久久中文字幕| 久久久久久久综合综合狠狠| 久久国产午夜精品一区二区三区| 国产激情久久久久影院小草 | 久久国产香蕉视频| 久久精品二区| 久久久久99这里有精品10| 精品久久久久成人码免费动漫| 人妻无码精品久久亚瑟影视 | 91精品国产高清久久久久久91| 99久久无码一区人妻| 久久国产视频99电影| 欧美伊人久久大香线蕉综合| 无码人妻久久一区二区三区 | 久久精品国产只有精品2020| 久久亚洲国产精品一区二区| 久久久精品国产亚洲成人满18免费网站 | 青青青国产精品国产精品久久久久 | 色综合久久中文色婷婷| 久久精品亚洲福利| 一本一本久久A久久综合精品 | 午夜天堂精品久久久久| 亚洲国产精品久久久久| 亚洲国产成人久久笫一页| 亚洲综合熟女久久久30p| 久久国产乱子精品免费女| 四虎影视久久久免费观看| 99久久精品午夜一区二区| 亚洲精品国产自在久久| 国产成人精品免费久久久久| 久久久人妻精品无码一区| 久久久无码一区二区三区| 婷婷久久综合九色综合绿巨人| 精品久久人妻av中文字幕| 伊人色综合久久天天人守人婷 |