• <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>

            大城小魔

            天下難事,必作于易;天下大事,必作于細

              C++博客 ::  :: 聯系 :: 聚合  :: 管理

            公告


            最新評論

             

            閑來無事對jabberd2服務器閱讀了下,每次讀C++代碼,都首先花費一些額外的時間領會代碼作者的抽象世界概念堆砌當中,C則不同,直入主題,心理上不會有任何負擔,不用徒勞輾轉在不同的世界理解和哲思之中,又一次拜倒在C的簡潔明了之下
            ^^廢話不多說了開始我們的內容:
            內存池實現相當的簡單,由兩個個主要部分組成 pheap,pfree,pool_struct,以及基本的內存池API

            pheap:         內存塊,它由pfree組織管理
            pfree:          由pheap構成鏈表,它作為內存池實體單元
            pool_struct: 內存池結構體
             

            //pool.h文件
            //=========================================================================
            //于內存池中的實體(內存塊)關聯的回調函數,當實體釋放時調用
            typedef void (*pool_cleanup_t)(void *arg);
            //單獨內存分塊
            struct pheap
            {
            void *block; //實際的數據內存塊
            int size,used; //實際大小,使用大小
            };
            //帶有釋放內存毀掉函數的內存分塊鏈表結點(內存池實體)
            struct pfree

            pool_cleanup_t f; 
            //內存釋放毀掉函數
            void *arg; 
            struct pheap *heap; //單獨內存分塊
            struct pfree *next; //下一個單獨內存分塊
            };

            //內存池--基于內存池實體。管理一個由內存池實體(pfree)組成的鏈表。
            typedef struct pool_struct
            {
            int size; //內存池大小
            struct pfree *cleanup; //鏈表首結點
            struct pfree *cleanup_tail; //鏈表尾結點
            struct pheap *heap; 
            #ifdef POOL_DEBUG 
            //調試信息
            char name[8], zone[32];
            int lsize;
            #endif
            } _pool, 
            *pool_t;

            #ifdef POOL_DEBUG 
            //調式調用函數版本定義宏
            # define pool_new() _pool_new(__FILE__,__LINE__) 
            # define pool_heap(i) _pool_new_heap(i,__FILE__,__LINE__) 
            #else
            # define pool_heap(i) _pool_new_heap(i,NULL,
            0
            # define pool_new() _pool_new(NULL,
            0)
            #endif

            //jabberd2內存池API函數定義
            JABBERD2_API pool_t _pool_new(char *file, int line); //構建一個新的內存池
            JABBERD2_API pool_t _pool_new_heap(int size, char *file, int line); //構建一個指定初始內存區塊大小的內存池
            JABBERD2_API void *pmalloc(pool_t, int size);//封裝 malloc函數,內存從內存池中進行分配,自動完成釋放
            JABBERD2_API void *pmalloc_x(pool_t p, int size, char c); /* Wrapper around pmalloc which prefils buffer with c */
            JABBERD2_API 
            void *pmalloco(pool_t p, int size); /* YAPW for zeroing the block */
            JABBERD2_API 
            char *pstrdup(pool_t p, const char *src); /* wrapper around strdup, gains mem from pool */
            JABBERD2_API 
            char *pstrdupx(pool_t p, const char *src, int len); /* use given len */
            JABBERD2_API 
            void pool_stat(int full); /* print to stderr the changed pools and reset */
            JABBERD2_API 
            void pool_cleanup(pool_t p, pool_cleanup_t fn, void *arg); /* calls f(arg) before the pool is freed during cleanup */
            JABBERD2_API 
            void pool_free(pool_t p);//調用所有的內存釋放回調函數,釋放所有內存池中的數據,刪除內存池本身
            JABBERD2_API int pool_size(pool_t p); //返回內存中已分配的總字節數

             

            //pool.c文件
            //=========================================================================

            //構建一個新的空內存池
            pool_t _pool_new(char *zone, int line)
            {
            pool_t p; 
            while((p = _pool__malloc(sizeof(_pool))) == NULL) sleep(1);
            p
            ->cleanup = NULL; //初始空鏈表
            p->heap = NULL; //同上
            p->size = 0

            #ifdef POOL_DEBUG
            p
            ->lsize = -1;
            p
            ->zone[0= '\0';
            snprintf(p
            ->zone, sizeof(p->zone), "%s:%i", zone, line);
            sprintf(p
            ->name,"%X",(int)p);

            if(pool__disturbed == NULL)
            {
            pool__disturbed 
            = (xht)1/* reentrancy flag! */
            pool__disturbed 
            = xhash_new(POOL_NUM);
            }
            if(pool__disturbed != (xht)1)
            xhash_put(pool__disturbed,p
            ->name,p);
            #endif

            return p;
            }

            //釋放一個內存分塊
            static void _pool_heap_free(void *arg)
            {
            struct pheap *= (struct pheap *)arg;

            _pool__free(h
            ->block); //free數據內存塊
            _pool__free(h); //free pheap結構體自身
            }

            //向內存池中添加內存池實體pfree
            static void _pool_cleanup_append(pool_t p, struct pfree *pf)
            {
            struct pfree *cur;

            if(p->cleanup == NULL)//空內存池時
            {
            p
            ->cleanup = pf;
            p
            ->cleanup_tail = pf;
            return;
            }

            //鏈表末尾添加新實體
            cur = p->cleanup_tail; 
            cur
            ->next = pf;
            p
            ->cleanup_tail = pf;
            }

            //創建一個內存池實體
            static struct pfree *_pool_free(pool_t p, pool_cleanup_t f, void *arg)
            {
            struct pfree *ret;

            //為內存池實體分配內存
            while((ret = _pool__malloc(sizeof(struct pfree))) == NULL) sleep(1);
            ret
            ->= f; //內存塊釋放回調函數
            ret->arg = arg; //回調函數參數
            ret->next = NULL;

            return ret;
            }
            //創建一個內存塊,并為其設置內存釋放回調函數
            static struct pheap *_pool_heap(pool_t p, int size)
            {
            struct pheap *ret; //數據內存塊結構體
            struct pfree *clean; //內存池實體

            //分配內存數據塊結構體內存
            while((ret = _pool__malloc(sizeof(struct pheap))) == NULL) sleep(1); 
            //分配數據內存塊內存
            while((ret->block = _pool__malloc(size)) == NULL) sleep(1);
            ret
            ->size = size; //指定數據內存塊大小
            p->size += size; //更新內存池總字節數
            ret->used = 0

            //生成對應的內存池實體,_pool_heap_free為靜態函數地址,ret為其調用參數
            clean = _pool_free(p, _pool_heap_free, (void *)ret);
            clean
            ->heap = ret; /* for future use in finding used mem for pstrdup */
            _pool_cleanup_append(p, clean);
            //將內存池實體,添加到內存池實體鏈表中

            return ret;
            }

            //內存池內存請求函數
            void *pmalloc(pool_t p, int size)
            {
            void *block;

            if(p == NULL)
            {
            fprintf(stderr,
            "Memory Leak! [pmalloc received NULL pool, unable to track allocation, exiting]\n");
            abort();
            }

            //如果內存池中沒有可用內存,或者申請的內存過大時,直接從進程堆中申請內存
            if(p->heap == NULL || size > (p->heap->size / 2))

            while((block = _pool__malloc(size)) == NULL) sleep(1); //直接從進程內存堆上分配
            p->size += size; //遞增內存池總字節數
            _pool_cleanup_append(p, _pool_free(p, _pool__free, block));//生成相應的內存池實體,并添加到內存池實體鏈表中
            return block;
            }

            /* we have to preserve boundaries, long story :) */
            if(size >= 4)
            while(p->heap->used&7) p->heap->used++;

            /* if we don't fit in the old heap, replace it */
            // 如果在現有內存塊中沒有足夠的內存,重新申請一塊
            if(size > (p->heap->size - p->heap->used))
            p
            ->heap = _pool_heap(p, p->heap->size);

            //當前內存塊有剩余空間
            block = (char *)p->heap->block + p->heap->used; //返回內存區塊有效地址
            p->heap->used += size; //更新內存區塊使用情況
            return block;

            }

            //對pmalloc進行封裝并使用參數c的內容預填充新內存塊
            void *pmalloc_x(pool_t p, int size, char c)
            {
            void* result = pmalloc(p, size);
            if (result != NULL)
            memset(result, c, size);
            return result;



            //方便,安全(為結構體申請空白內存等)
            void *pmalloco(pool_t p, int size)
            {
            void *block = pmalloc(p, size);
            memset(block, 
            0, size);
            return block;
            }


             

             

             

             

            posted on 2008-11-13 23:40 momor 閱讀(1545) 評論(3)  編輯 收藏 引用 所屬分類: C++/C

            Feedback

            # re: jabberd2的內存池 2008-11-14 10:45 zuhd
            這個池能否實現分配不等大小的內存,能否對碎片進行整理?否則和boost沒有什么區別  回復  更多評論
              

            # re: jabberd2的內存池 2008-11-14 11:04 momor
            老實說,本人也認為這個內存池還是很弱,它主要針對保證對內存泄露的控制,預先分配的大內存塊,也可以保證內存碎片的產生,一定程度提高了內存塊分配的速度,它可以實現不等大小內存的分配。
            我個人還是傾向SGI內存池的實現,它根據所需分配的不同內存大小的索引表進行空閑內存鏈表的管理。邏輯上和功能實現上都比較清晰  回復  更多評論
              

            # re: jabberd2的內存池 2008-11-19 13:29 xto
            這種內存池可能主要用于效率和性能比較高的地方,例如通信服務端接受數據時用以裝載數據的內存區域。如果頻繁的新建和釋放內存,必然可能會產生內存碎片,更常見的則是cpu在創建和釋放內存時性能的損耗。因此才會創建內存池對數據進行處理。其實很多通信服務端常用的線程池,內存池都有這個原理在里面  回復  更多評論
              

            99久久精品国产一区二区三区| 久久久久久久综合综合狠狠| 久久久久婷婷| 四虎影视久久久免费观看| 国产精品毛片久久久久久久| 大香伊人久久精品一区二区| 久久久久久亚洲精品成人| 99久久精品久久久久久清纯| 久久综合一区二区无码| 久久久精品久久久久久 | 伊人久久大香线蕉AV色婷婷色| 国产福利电影一区二区三区久久久久成人精品综合 | 久久精品免费网站网| 久久人人爽人人爽人人片av高请| 久久久无码精品亚洲日韩蜜臀浪潮 | 欧美国产精品久久高清| 国产99精品久久| 亚洲伊人久久综合影院| 一本色综合网久久| 99久久婷婷国产一区二区| 久久久久久a亚洲欧洲aⅴ | 久久香蕉国产线看观看乱码| 久久综合综合久久综合| 99精品国产免费久久久久久下载 | 国产美女久久久| 99久久777色| 日韩亚洲国产综合久久久| 久久国产成人亚洲精品影院| 亚洲国产成人久久一区久久| 日本精品久久久久中文字幕| 91精品国产乱码久久久久久| 香蕉久久夜色精品升级完成| 久久久久综合网久久| 精品一区二区久久久久久久网站| 久久夜色精品国产噜噜麻豆 | 狠狠色丁香久久综合五月| 久久91精品国产91久久小草| 久久青青草原国产精品免费| 国产成人精品综合久久久| 日韩影院久久| 国产亚洲精久久久久久无码77777 国产亚洲精品久久久久秋霞 |