2013年7月23日 星期二

[Linux] kmem_cache

今天對於 f2fs 作GC時,宣告的第一個structure來做探討
static struct kmem_cache *winode_slab;
稍微追了一下winode_slab出現的地方。

先來介紹一下大神上搜到的資訊 在Refs[1]中提到:

在内核编程中,可能经常会有一些数据结构需要反复使用和释放,按照通常的思路,可能是使用kmallockfree来实现。
但是这种方式效率不高,Linux为我们提供了更加高效的方法——Slab高速缓存管理器
通过先使用kmem_cache_create函数创建一个高速缓存的头指针——在内核中是struct kmem_cache结构 (這不就是在f2fs裡面宣告的結構嗎!!),具体用法可以这样:
struct kmem_cache *cachep = NULL;
cachep = kmem_cache_create("cache_name", sizeof(struct yourstruct), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);

 (應該可以在f2fs中也找到類似的東東!!)
果不其然~找到啦~

这样我们就获得了一个可用的cachep头指针。 (在f2fs的話就是 winode_slab啦)

当需要分配一个struct yourstruct的结构体空间时,我们只需要调用kmem_cache_alloc函数,就可以获得一个足够我们使用的空间的指针(为什么我要说足够呢?因为刚才的声明中我使用了一个标志——SLAB_HWCACHE_ALIGN,这个标志会让分配的空间对于硬件来说是对齐的,而不一定恰好等于sizeof(struct yourstruct)的结果)。范例代码如下:
struct yourstruct *bodyp = NULL;

bodyp = (struct yourstruct *) kmem_cache_alloc(cachep, GFP_ATOMIC & ~__GFP_DMA);

这样就可以使用bodyp指针所对应的空间存贮你需要的结构体信息了。
当用完结束后,我们需要释放空间,如何操作呢?代码很简单:
kmem_cache_free(cachep, bodyp);

在這邊我們注意到 f2fs中使用的flag 是 SLAB_RECLAIM_ACCOUNT 並非 SLAB_HWCACHE_ALIGN
 在Refs[2],[3]中提到: 
SLAB_RECLAIM_ACCOUNT:内核检查用户态程序有没有足够内存可用,被标记为这个标志的Slab将作为通缉对象。
SLAB_RECLAIM_ACCOUNT flag set, the page frames assigned to the slabs are accounted for as reclaimable pages when the kernel checks whether there is enough memory to satisfy some User Mode requests.


(應該可以在f2fs中也找到類似的東東!!)
果不其然~又找到啦~
  







ps. 若整個cache都不需要時,在f2fs中是call kmem_cache_destory~


kmem_cache_alloc()中第二個參數的探討,在Refs[4]中提到:

GFP_ATOMIC
用来从中断处理和进程上下文之外的其他代码中分配内存. 从不睡眠.
GFP_KERNEL
内核内存的正常分配. 可能睡眠.
GFP_USER
用来为用户空间页来分配内存; 它可能睡眠.
GFP_HIGHUSER
如同 GFP_USER, 但是从高端内存分配, 如果有. 高端内存在下一个子节描述.
GFP_NOIO
GFP_NOFS
这个标志功能如同 GFP_KERNEL, 但是它们增加限制到内核能做的来满足请求. 一个 GFP_NOFS 分配不允许进行任何文件系统调用, 而 GFP_NOIO 根本不允许任何 I/O 初始化. 它们主要地用在文件系统和虚拟内存代码, 那里允许一个分配睡眠, 但是递归的文件系统调用会是一个坏注意.
上面列出的这些分配标志可以是下列标志的相或来作为参数, 这些标志改变这些分配如何进行:
__GFP_DMA
这个标志要求分配在能够 DMA 的内存区. 确切的含义是平台依赖的并且在下面章节来解释.
__GFP_HIGHMEM
这个标志指示分配的内存可以位于高端内存.
__GFP_COLD
正常地, 内存分配器尽力返回"缓冲热"的页 -- 可能在处理器缓冲中找到的页. 相反, 这个标志请求一个"冷"页, 它在一段时间没被使用. 它对分配页作 DMA 读是有用的, 此时在处理器缓冲中出现是无用的. 一个完整的对如何分配 DMA 缓存的讨论看"直接内存存取"一节在第 1 章.
__GFP_NOWARN
这个很少用到的标志阻止内核来发出警告(使用 printk ), 当一个分配无法满足.
__GFP_HIGH
这个标志标识了一个高优先级请求, 它被允许来消耗甚至被内核保留给紧急状况的最后的内存页.
__GFP_REPEAT
__GFP_NOFAIL
__GFP_NORETRY
这些标志修改分配器如何动作, 当它有困难满足一个分配. __GFP_REPEAT 意思是" 更尽力些尝试" 通过重复尝试 -- 但是分配可能仍然失败. __GFP_NOFAIL 标志告诉分配器不要失败; 它尽最大努力来满足要求. 使用 __GFP_NOFAIL 是强烈不推荐的; 可能从不会有有效的理由在一个设备驱动中使用它. 最后, __GFP_NORETRY 告知分配器立即放弃如果得不到请求的内存.

Refs:
[1] http://blog.csdn.net/leolinux/article/details/6103712
[2] http://blog.csdn.net/tq02h2a/article/details/3628402
[3] http://linux.chinaunix.net/techdoc/net/2008/03/29/987845.shtml
[4] http://oss.org.cn/kernel-book/ldd3/ch08.html

沒有留言:

張貼留言