歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux Slob分配器(一)--概述

Linux Slob分配器(一)--概述

日期:2017/3/1 10:18:27   编辑:Linux編程

Slob分配器相較Slab和Slub分配器而言,最大的特點就是簡潔,其總共的實現代碼大概就600多行,因此其適用於嵌入式系統。不同於Slab和Slub,Slob分配器沒有引入本地CPU高速緩存和本地節點的概念。Slob分配器同樣使用鏈表來管理slob,不過總共只存在三個全局partial_free鏈表,這三個鏈表是按對象大小來劃分的。

相關閱讀:
Linux Slob分配器(二)--分配對象 http://www.linuxidc.com/Linux/2012-07/64108.htm
Linux Slob分配器(三)--釋放對象 http://www.linuxidc.com/Linux/2012-07/64109.htm

  1. #define SLOB_BREAK1 256
  2. #define SLOB_BREAK2 1024
  3. static LIST_HEAD(free_slob_small);
  4. static LIST_HEAD(free_slob_medium);
  5. static LIST_HEAD(free_slob_large);

對於小於256字節的對象,將從free_slob_small鏈表中尋找slob進行分配

對於小於1024字節的對象,將從free_slob_medium鏈表中尋找slob進行分配

對於大於1024字節的對象,將從free_slob_large鏈表中尋找slob進行分配

對於大於PAGE_SIZE的對象,將直接通過伙伴系統分配,不經手Slob分配器

那麼總共只有三個鏈表,Slob分配器的各類緩存怎麼管理自己的空閒對象呢?實際上,所謂的不同類別的緩存都只是偽緩存,因為它們並沒有專屬自己的內存。當你在Slob分配器中創建一個緩存時,只是聲明了該緩存的對象的大小size、對齊值align等,那麼當要從該緩存分配對象時,將會根據size定位到相應的鏈表,尋求分配。因此專用緩存分配對象(kmem_cache_alloc())和普通緩存分配對象(kmalloc())並無太多區別,它們的對象都來源於這三個鏈表,只不過內核欺騙性的保留了這些接口而已。由此可以想象,struct kmem_cache這個結構在Slob分配器中是很簡潔的

  1. struct kmem_cache {
  2. unsigned int size, align; //對象大小,對齊值
  3. unsigned long flags; //屬性標識
  4. const char *name; //緩存名
  5. void (*ctor)(void *); //分配對象時的構造函數
  6. };

接下來的一個問題就是Slob分配器是如何描述slob的。在Slob分配器中,一個slob永遠都是占用一個頁框的大小,所以對於大於PAGE_SIZE的對象,會選擇直接通過伙伴系統分配。Slob分配器將所有的slob組織在三個全局鏈表中,不過,這些slob的描述結構都不需要進行額外的分配。Slob分配器將描述slob的變量打包成一個結構,然後和頁描述符struct page一起組成一個聯合體,這樣就可以直接利用頁描述符已占有的空間,將頁描述符中無關緊要的字段填充為slob的有效描述字段,這樣便可以省下一筆內存了!

  1. struct slob_page {
  2. union {
  3. struct {
  4. unsigned long flags;/* 填充用,為了不覆蓋page->flags */
  5. atomic_t _count; /* 填充用,為了不覆蓋page->_count */
  6. slobidx_t units; /* slob的空閒單元數 */
  7. unsigned long pad[2];
  8. slob_t *free; /* 指向第一個空閒塊 */
  9. struct list_head list; /* 用於鏈入slob全局鏈表 */
  10. };
  11. struct page page;
  12. };
  13. };

我們可以看到,實際上真正用於slob管理的項只有三個,即units,free和list.

free和list的意義已經很清楚明了了,現在來解釋下slobidx_t units這個玩意。unit是slob的粒度,也就是說當你分配內存時,必須分配出去N個unit,所有的管理都是基於unit的。unit的大小根據PAGE_SIZE的不同而不同,通常情況下為2個字節,關於unit大小的定義:

  1. #if PAGE_SIZE <= (32767 * 2)
  2. typedef s16 slobidx_t;
  3. #else
  4. typedef s32 slobidx_t;
  5. #endif

既然slob的管理是基於unit的,那麼units字段的含義也就很容易理解了,它表示的是slob中當前還剩余的空閒單元數目。

Copyright © Linux教程網 All Rights Reserved