<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ### 內存池的作用: 直接使用系統調用malloc會有如下弊端: - 頻繁分配內存時會產生大量內存碎片 - 頻繁分配內存增加系統調用開銷 - 容易造成內存泄漏 > 內存池是預先申請一定數量的,大小相等的內存塊作為預備使用;當需要時向內存池分出一部分內存,若內存塊不夠使用時再向系統申請新的內存塊,下面就swoole的swMemoryGlobal內存池作為分析例子 ### swoole swMemoryPool 數據結構設計 swMemoryGlobal是swoole內存池實現一種方式,學習內存池主要是要掌握其數據結構的設計,memoryGlobal實現如下: ```c // src/memory/MemoryGlobal.c typedef struct _swMemoryPool { void *object; // 指向swMemoryGlobal指針 void* (*alloc)(struct _swMemoryPool *pool, uint32_t size); // 分配內存函數指針 void (*free)(struct _swMemoryPool *pool, void *ptr); // 是否內存函數指針 void (*destroy)(struct _swMemoryPool *pool); // 銷毀內存函數指針 } swMemoryPool; typedef struct _swMemoryGlobal { uint8_t shared; uint32_t pagesize; // 指定每個swMemoryGlobal_page需要申請內存大小 swLock lock; // 互斥鎖 swMemoryGlobal_page *root_page; // 指向第一個swMemoryGlobal_page指針,有頭指針可以銷毀內存池 swMemoryGlobal_page *current_page; // 指向當前swMemoryGlobal_page指針 uint32_t current_offset; } swMemoryGlobal; typedef struct _swMemoryGlobal_page { struct _swMemoryGlobal_page *next; // 指向下一個節點 char memory[0]; // 這是一個柔性數組,用于記錄申請內存后的內存地址 } swMemoryGlobal_page; ``` 這三者之間的關系如下: ![](https://box.kancloud.cn/cd0e46d4c653a680f6e548d002529744_858x392.png) ### swMemoryPool swMemoryPool可以看做是一個類,它提過了alloc,free,destory方法,以及object屬性,object實際上是指向swMemoryGlobal的指針,而alloc,free,destory 則是對object操作,即通過alloc,free,destory操作swMemoryGlobal上的內容,例如: ```c // src/core/base.c //init global shared memory SwooleG.memory_pool = swMemoryGlobal_new(SW_GLOBAL_MEMORY_PAGESIZE, 1); SwooleGS = SwooleG.memory_pool->alloc(SwooleG.memory_pool, sizeof(SwooleGS_t)); ``` 以上代碼是分配sizeof(SwooleGS_t)大小內存 ### swMemoryGlobal swMemoryGlobal維護著一個鏈表,每個節點即swMemoryGlobal_page,root_page指向第一個節點,current_page指向當前節點,pagesize指為一個節點申請 內存大小,current_offset則表示一個節點已被使用內存 ### swMemoryGlobal_page swoole根據swMemoryGlobal.pagesize申請指定大小的內存,如下: ```c // src/memory/MemoryGlobal.c swMemoryGlobal_page *page = swMemoryGlobal_new_page(&gm); ``` 上面說過swMemoryGlobal_page是一個鏈表節點,這里需要說明的是第一個節點,第一個節點的current_offset為sizeof(swMemoryGlobal) + sizeof(swMemoryPool); 而并非為0;如下代碼,當為第一個swMemoryGlobal_page申請內存后,立馬就為swMemoryPool和swMemoryGlobal分配內存 ```c // src/memory/MemoryGlobal.c gm.pagesize = pagesize; // 系統申請一個pagesize大小內存 swMemoryGlobal_page *page = swMemoryGlobal_new_page(&gm); if (page == NULL) { return NULL; } if (swMutex_create(&gm.lock, shared) < 0) { return NULL; } gm.root_page = page; // page->memory為空閑內存 gm_ptr = (swMemoryGlobal *) page->memory; gm.current_offset += sizeof(swMemoryGlobal); // swMemoryPool指向空閑內存偏移地址,占用sizeof(swMemoryPool)內存 swMemoryPool *allocator = (swMemoryPool *) (page->memory + gm.current_offset); gm.current_offset += sizeof(swMemoryPool); allocator->object = gm_ptr; allocator->alloc = swMemoryGlobal_alloc; allocator->destroy = swMemoryGlobal_destroy; allocator->free = swMemoryGlobal_free; // 將gm寫入到gm_ptr,即空閑內存前sizeof(gm)用于swMemoryGlobal memcpy(gm_ptr, &gm, sizeof(gm)); ``` ### 分配內存 分配內存由swMemoryGlobal_alloc方法執行;該方法為swMemoryPool一個函數指針,如下 ```c allocator->alloc = swMemoryGlobal_alloc; // 分配方法 ``` ```c // src/core/base.c //init global shared memory SwooleG.memory_pool = swMemoryGlobal_new(SW_GLOBAL_MEMORY_PAGESIZE, 1); SwooleGS = SwooleG.memory_pool->alloc(SwooleG.memory_pool, sizeof(SwooleGS_t)); // src/memory/MemoryGlobal.c static void *swMemoryGlobal_alloc(swMemoryPool *pool, uint32_t size) { swMemoryGlobal *gm = pool->object; gm->lock.lock(&gm->lock); if (size > gm->pagesize - sizeof(swMemoryGlobal_page)) // sizeof(swMemoryGlobal_page)為swMemoryGlobal_page類型的指針大小 { swWarn("failed to alloc %d bytes, exceed the maximum size[%d].", size, gm->pagesize - (int) sizeof(swMemoryGlobal_page)); gm->lock.unlock(&gm->lock); return NULL; } // 如果一個節點不夠分配內存,則重新申請一個新節點,并設置當前節點current_page為新節點 if (gm->current_offset + size > gm->pagesize - sizeof(swMemoryGlobal_page)) { swMemoryGlobal_page *page = swMemoryGlobal_new_page(gm); if (page == NULL) { swWarn("swMemoryGlobal_alloc alloc memory error."); gm->lock.unlock(&gm->lock); return NULL; } gm->current_page = page; } void *mem = gm->current_page->memory + gm->current_offset; gm->current_offset += size; gm->lock.unlock(&gm->lock); // 結果返回空閑內存的偏移地址 return mem; } ``` ### 柔性數組 柔性數組(0長度數組)作用: 為了滿足需要變長度的結構體(結構體是可變長的) - 數組名不占用空間,分配的內存是連續的 - 不會像定長數組一樣浪費空間 - 不會像指針一樣需要分別分配內存,分別釋放內存 定長數組使用方便, 但是卻浪費空間, 指針形式只多使用了一個指針的空間, 不會造成 [柔性數組參考](http://www.360doc.com/content/17/1119/10/9200790_705214752.shtml)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看