黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

GlusterFS之內(nèi)存池(mem-pool)使用實例分析

系統(tǒng) 2403 0

我的新浪微博: http://weibo.com/freshairbrucewoo

歡迎大家相互交流,共同提高技術。

?

上一篇博客詳細分析了GlusterFS之內(nèi)存池的實現(xiàn)技術,今天我們看看GlusterFS是怎么使用這個技術的。

第一步:分配和初始化:

cli進程在初始化的過程中會涉及到內(nèi)存池的建立和初始化,具體涉及到內(nèi)存池初始化的代碼如下(在cli.c文件中的glusterfs_ctx_defaults_init函數(shù)):

      
         1
      
      
        /*
      
      
         frame_mem_pool size 112 * 64 
      
      
        */
      
      
         2
      
       pool->frame_mem_pool = mem_pool_new (call_frame_t, 
      
        32
      
      );
      
        //
      
      
        為調用針對象分配內(nèi)存池對象,對象類型是call_frame_t,32個這樣的內(nèi)存塊  
      
      
         3
      
      
        if
      
       (!pool->
      
        frame_mem_pool)  


      
      
         4
      
      
        return
      
       -
      
        1
      
      
        ;  


      
      
         5
      
      
         6
      
      
        /*
      
      
         stack_mem_pool size 256 * 128 
      
      
        */
      
      
         7
      
       pool->stack_mem_pool = mem_pool_new (call_stack_t, 
      
        16
      
      );
      
        //
      
      
        為調用堆棧對象分配內(nèi)存池對象,對象類型是call_stack_t,16個這樣的內(nèi)存塊  
      
      
         8
      
      
         9
      
      
        if
      
       (!pool->
      
        stack_mem_pool)  


      
      
        10
      
      
        return
      
       -
      
        1
      
      
        ;  


      
      
        11
      
      
        12
      
       ctx->stub_mem_pool = mem_pool_new (call_stub_t, 
      
        16
      
      
        );  


      
      
        13
      
      
        if
      
       (!ctx->
      
        stub_mem_pool)  


      
      
        14
      
      
        return
      
       -
      
        1
      
      
        ;  


      
      
        15
      
      
        16
      
       ctx->dict_pool = mem_pool_new (dict_t, 
      
        32
      
      
        );  


      
      
        17
      
      
        if
      
       (!ctx->
      
        dict_pool)  


      
      
        18
      
      
        return
      
       -
      
        1
      
      
        ;  


      
      
        19
      
      
        20
      
       ctx->dict_pair_pool = mem_pool_new (data_pair_t, 
      
        512
      
      
        );  


      
      
        21
      
      
        if
      
       (!ctx->
      
        dict_pair_pool)  


      
      
        22
      
      
        return
      
       -
      
        1
      
      
        ;  


      
      
        23
      
      
        24
      
       ctx->dict_data_pool = mem_pool_new (data_t, 
      
        512
      
      
        );  


      
      
        25
      
      
        if
      
       (!ctx->
      
        dict_data_pool)  


      
      
        26
      
      
        return
      
       -
      
        1
      
      ;  
    

?

由上面的代碼可以看出:集合系統(tǒng)中各種結構體對象可能實際會用到的數(shù)量來預先分配好,真正需要為對象內(nèi)存的時候直接從這些內(nèi)存池中取就可以了,用完之后又放回內(nèi)存池,這樣減少了分配和釋放內(nèi)存的額外系統(tǒng)開銷,分配內(nèi)存往往需要從用戶態(tài)到內(nèi)核態(tài)切換,這些都是很耗時間的,當然相同的對象還減少了初始化的時間。

?

代碼分配內(nèi)存調用的函數(shù)是mem_pool_new,而不是在上一篇博客結束的mem_pool_new_fn函數(shù),那是因為mem_pool_new是定義的宏函數(shù),就是調用mem_pool_new_fn函數(shù),函數(shù)參數(shù)分別表示對象所占內(nèi)存大小、數(shù)量和名稱(為分配的內(nèi)存起一個名字,就是對象的名稱);

?

      
        1
      
      
        #define
      
       mem_pool_new(type,count) mem_pool_new_fn (sizeof(type), count, #type)  
    

?

第二步:從內(nèi)存池中取出一個對象內(nèi)存塊:

?

      
        1
      
       call_stub_t *
      
        new
      
       =
      
         NULL;  


      
      
        2
      
      
        3
      
       GF_VALIDATE_OR_GOTO (
      
        "
      
      
        call-stub
      
      
        "
      
      , frame, 
      
        out
      
      
        );  


      
      
        4
      
      
        5
      
      
        new
      
       = mem_get0 (frame->
      
        this
      
      ->ctx->stub_mem_pool);
      
        //
      
      
        從內(nèi)存池中拿出一個對象內(nèi)存塊  
      
    

?

如下面代碼取出一個調用存根的對象內(nèi)存塊(call_stub_t):

?

?

同樣使用的函數(shù)不是我們介紹的mem_get,而是mem_get0函數(shù),mem-get0封裝了mem_get,做參數(shù)判斷并且把需要使用的內(nèi)存初始化為0,代碼如下:

?

      
         1
      
      
        void
      
      *  


      
         2
      
       mem_get0 (
      
        struct
      
       mem_pool *
      
        mem_pool)  


      
      
         3
      
      
        {  


      
      
         4
      
      
        void
      
                   *ptr =
      
         NULL;  


      
      
         5
      
      
         6
      
      
        if
      
       (!
      
        mem_pool) {  


      
      
         7
      
                       gf_log_callingfn (
      
        "
      
      
        mem-pool
      
      
        "
      
      , GF_LOG_ERROR, 
      
        "
      
      
        invalid argument
      
      
        "
      
      
        );  


      
      
         8
      
      
        return
      
      
         NULL;  


      
      
         9
      
      
                }  


      
      
        10
      
      
        11
      
               ptr = mem_get(mem_pool);
      
        //
      
      
        得到一個內(nèi)存對象塊  
      
      
        12
      
      
        13
      
      
        if
      
      
         (ptr)  


      
      
        14
      
                       memset(ptr, 
      
        0
      
      , mem_pool->real_sizeof_type);
      
        //
      
      
        初始化0  
      
      
        15
      
      
        16
      
      
        return
      
      
         ptr;  


      
      
        17
      
       }  
    

?

?

第三步:放回對象內(nèi)存塊到內(nèi)存池中:

當我們使用完一個對象以后就會重新放回內(nèi)存池中,例如還是以調用存根對象(call_stub_t)

?

      
         1
      
      
        void
      
      
         2
      
       call_stub_destroy (call_stub_t *
      
        stub)  


      
      
         3
      
      
        {  


      
      
         4
      
               GF_VALIDATE_OR_GOTO (
      
        "
      
      
        call-stub
      
      
        "
      
      , stub, 
      
        out
      
      
        );  


      
      
         5
      
      
         6
      
      
        if
      
       (stub->
      
        wind) {  


      
      
         7
      
      
                        call_stub_destroy_wind (stub);  


      
      
         8
      
               } 
      
        else
      
      
         {  


      
      
         9
      
      
                        call_stub_destroy_unwind (stub);  


      
      
        10
      
      
                }  


      
      
        11
      
      
        12
      
               stub->stub_mem_pool =
      
         NULL;  


      
      
        13
      
               mem_put (stub);
      
        //
      
      
        放回對象內(nèi)存塊到內(nèi)存池中  
      
      
        14
      
      
        out
      
      
        :  


      
      
        15
      
      
        return
      
      
        ;  


      
      
        16
      
       }  
    

?

第四步:銷毀內(nèi)存池:

如果整個內(nèi)存池對象都不需要了,那么銷毀掉這個內(nèi)存池,實現(xiàn)這個功能的函數(shù)是mem_pool_destroy:

?

      
         1
      
      
        void
      
      
         2
      
       mem_pool_destroy (
      
        struct
      
       mem_pool *
      
        pool)  


      
      
         3
      
      
        {  


      
      
         4
      
      
        if
      
       (!
      
        pool)  


      
      
         5
      
      
        return
      
      
        ;  


      
      
         6
      
      
         7
      
               gf_log (THIS->name, GF_LOG_INFO, 
      
        "
      
      
        size=%lu max=%d total=%
      
      
        "
      
      
        PRIu64,  


      
      
         8
      
                       pool->padded_sizeof_type, pool->max_alloc, pool->
      
        alloc_count);  


      
      
         9
      
      
        10
      
               list_del (&pool->global_list);
      
        //
      
      
        從全局內(nèi)存池對象中拖鏈  
      
      
        11
      
      
        12
      
               LOCK_DESTROY (&pool->
      
        lock
      
      );
      
        //
      
      
        銷毀鎖  
      
      
        13
      
               GF_FREE (pool->name);
      
        //
      
      
        釋放名字占用的內(nèi)存  
      
      
        14
      
               GF_FREE (pool->pool);
      
        //
      
      
        釋放內(nèi)存池分配的內(nèi)存,就是提供給用戶使用的那一段內(nèi)存  
      
      
        15
      
               GF_FREE (pool);
      
        //
      
      
        釋放內(nèi)存池對象占用的內(nèi)存  
      
      
        16
      
      
        17
      
      
        return
      
      
        ;  


      
      
        18
      
       }  
    

?

?

一般情況下內(nèi)存池對象會在程序退出的時候才會釋放和銷毀,還有一種情況是臨時分配的內(nèi)存池也有可能在系統(tǒng)運行期間釋放和銷毀,因為不能保證一個預先分配的內(nèi)存池就能夠滿足整個系統(tǒng)運行期間那個對象所需要的內(nèi)存,可能在每一個階段這個對象使用特別多,以至于把內(nèi)存池預先分配的對象內(nèi)存塊使用完了,這時就需要臨時分配內(nèi)存池對象,過了這一段時間可能這個對象需要的個數(shù)就減少了,這時就需要釋放掉臨時分配的,已還給系統(tǒng)內(nèi)存。

?

OK!內(nèi)存池管理技術是提供內(nèi)存使用率和效率的重要手段,Glusterfs使用的內(nèi)存池技術采用的是linux內(nèi)核管理小內(nèi)存塊的分配算法slab,就是基于對象分配內(nèi)存的技術。可以先去熟悉slab的原理,就能更好的理解Glusterfs的內(nèi)存池技術了!

GlusterFS之內(nèi)存池(mem-pool)使用實例分析


更多文章、技術交流、商務合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!