我們都知道buddy分配器是按照頁的單位分配的(buddy系統分配器實現),如果我們需要分配幾十個位元組,幾百個位元組的時候,就需要用到slab分配器。
slab分配器專門是針對小記憶體分配而設計的,比如我們驅動中常見的kmalloc分配器就是通過slab分配器分配的記憶體。
而slab分配器在linux系統中三種具體的實現:slab,slub,slob。目前核心**中預設的slab分配器為slub演算法。至於為啥不用slab大家可以網上看看資料,所以我們重點分析slub分配器的實現。
slub的原理是:
cat /proc/slabinfo節點就可以看見系統中存在的slab資訊
kmalloc-8192 274 304 8192 4 8 : tunables 0 0 0 : slabdata 76 76 0
kmalloc-4096 546 568 4096 8 8 : tunables 0 0 0 : slabdata 71 71 0
kmalloc-2048 1292 1360 2048 16 8 : tunables 0 0 0 : slabdata 85 85 0
kmalloc-1024 2134 2336 1024 32 8 : tunables 0 0 0 : slabdata 73 73 0
kmalloc-512 3648 3648 512 32 4 : tunables 0 0 0 : slabdata 114 114 0
kmalloc-256 2000 2784 256 32 2 : tunables 0 0 0 : slabdata 87 87 0
kmalloc-192 4894 5124 192 21 1 : tunables 0 0 0 : slabdata 244 244 0
kmalloc-128 3360 3360 128 32 1 : tunables 0 0 0 : slabdata 105 105 0
kmalloc-96 24906 24906 96 42 1 : tunables 0 0 0 : slabdata 593 593 0
kmalloc-64 84800 84800 64 64 1 : tunables 0 0 0 : slabdata 1325 1325 0
kmalloc-32 19456 19456 32 128 1 : tunables 0 0 0 : slabdata 152 152 0
kmalloc-16 12544 12544 16 256 1 : tunables 0 0 0 : slabdata 49 49 0
kmalloc-8 11264 11264 8 512 1 : tunables 0 0 0 : slabdata 22 22 0
kmem_cache_node 576 576 64 64 1 : tunables 0 0 0 : slabdata 9 9 0
kmem_cache 294 294 384 21 2 : tunables 0 0 0 : slabdata 14 14 0
我們通過自己建立乙個新的slab,帶大家走進slub。
#include #include #include #include static struct kmem_cache* slub_test;
struct student;
int slub_test_create_kmem(void)
return ret;}
static int __init slub_test_init(void)
static void __exit slub_test_exit(void)
module_init(slub_test_init);
module_exit(slub_test_exit);
此例子申請了乙個名為slub_test的slub,我們編譯為模組了。當我們插入此模組的時候,就會在/proc/slabinfo下生成乙個slub_test的名字的slab
/ # cat /proc/slabinfo | grep "slub_test"
# name : tunables : slabdata slub_test 0 0 8 512 1 : tunables 0 0 0 : slabdata 0 0 0
這個是插入模組後,出來的結果。而上面這些都是什麼意思呢?接著分析各個字段啥意思,我們不按照順序解釋
注意:如果機器開啟的slub_debug選項,有可能都不是整除的,因為乙個object中存在了一些debug除錯區域
#include #include #include #include #include static struct kmem_cache* slub_test;
struct student;
struct student* zhangsan;
int slub_test_create_kmem(void)
zhangsan = kmem_cache_alloc(slub_test, gfp_kernel);
if(zhangsan != null)
return ret;}
static int __init slub_test_init(void)
static void __exit slub_test_exit(void)
module_init(slub_test_init);
module_exit(slub_test_exit);
這時候再次看看/proc/slabinfo下的結果
/proc/slabinfo | grep "slub_test"
# name : tunables : slabdata slub_test 512 512 8 512 1 : tunables 0 0 0 : slabdata 1 1 0
可以看到數值有所變化:
for_each_kmem_cache_node(s, node, n)
sinfo->active_objs = nr_objs - nr_free;
sinfo->num_objs = nr_objs;
sinfo->active_slabs = nr_slabs;
sinfo->num_slabs = nr_slabs;
sinfo->objects_per_slab = oo_objects(s->oo);
sinfo->cache_order = oo_order(s->oo);
active_objects等於nr_objs - nr_free,nr_free的值是通過count_free計算出來的。free代表的意思是總共的object減去使用的inuse的。但是slab剛建立的時候insue等於object的
#ifdef config_slub_debug
static int count_free(struct page *page)
static inline unsigned long node_nr_objs(struct kmem_cache_node *n)
#endif /* config_slub_debug */
page->inuse = page->objects;
page->frozen = 1;
這裡的意思大概是inuse代表已經用完的,那slab肯定會使用完的,所以一開始inuse就等於object的數量的。
原理就是上圖的樣子:slab從buddy拿到乙個order為0的記憶體,也就是一頁,然後把這一頁稱為名為slub_test的slab,然後把這一頁分成很多小的object的。
當我們使用的時候就從slab中獲取乙個object使用,用完了在歸還給slab管理即可。
sprintf舉例說明
最近需要把圖形的座標轉換為字元來檢驗圖形座標的正確與否,所以較多的用到了sprintf 函式。例如 int sign 100 char s1 10 sprintf s1,d sign pdc textout 0,0,s1 這裡就把sprintf 函式的用法總結一下。int sprintf char ...
python argparse舉例說明
目的 想從命令列通過命令來指定是否執行程式中的某個函式 模組 更新關於另乙個例子 這裡只舉例說明 原因是看了很多博文之後,還是沒有解決筆者上面說的那個問題,即如何從命令列決定是否執行某段函式問題 設定乙個引數,名為foreground,簡寫f 即在終端可以輸入 foreground也可以輸入 f。跟...
c 引用 舉例說明
簡介 引用就是某一變數 目標 的乙個別名,對引用的操作與對變數直接操作完全一樣。c 11中新增了 右值引用 我們這裡所說的引用通常指 左值引用 例 int a 10 int rea a rea指向a,是a的另乙個名字 int rerea 錯誤 引用必須被初始化輸出a 和 rea 都是10。需要注意定...