加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

linux 后备缓存

发布时间:2020-12-13 23:12:39 所属栏目:Linux 来源:网络整理
导读:一个设备驱动常常以反复分配许多相同大小的对象而结束. 如果内核已经维护了一套相同 大小对象的内存池,为什么不增加一些特殊的内存池给这些高容量的对象? 实际上,内核 确实实现了一个设施来创建这类内存池,它常常被称为一个后备缓存. 设备驱动常常不展 示这

一个设备驱动常常以反复分配许多相同大小的对象而结束. 如果内核已经维护了一套相同 大小对象的内存池,为什么不增加一些特殊的内存池给这些高容量的对象? 实际上,内核 确实实现了一个设施来创建这类内存池,它常常被称为一个后备缓存. 设备驱动常常不展 示这类的内存行为,它们证明使用一个后备缓存是对的,但是,有例外; 在 Linux 2.6 中 USB 和 SCSI 驱动使用缓存.

?

Linux 内核的缓存管理者有时称为" slab 分配器". 因此,它的功能和类型在

<linux/slab.h> 中声明. slab 分配器实现有一个 kmem_cache_t 类型的缓存; 使用一个 对 kmem_cache_create 的调用来创建它们:

?

kmem_cache_t *kmem_cache_create(const char *name,size_t size,size_t offset,

unsigned long flags,

void (*constructor)(void *,kmem_cache_t *,

unsigned long flags),void (*destructor)(void *,unsigned long flags));

?

这个函数创建一个新的可以驻留任意数目全部同样大小的内存区的缓存对象,大小由 size 参数指定. name 参数和这个缓存关联并且作为一个在追踪问题时有用的管理信息; 通常,它被设置为被缓存的结构类型的名子. 这个缓存保留一个指向 name 的指针,而不 是拷贝它,因此驱动应当传递一个指向在静态存储中的名子的指针(常常这个名子只是一 个文字字串). 这个名子不能包含空格.

?

?

offset 是页内的第一个对象的偏移; 它可被用来确保一个对被分配的对象的特殊对齐,但是你最可能会使用 0 来请求缺省值. flags 控制如何进行分配并且是下列标志的一个 位掩码:

?

SLAB_NO_REAP

?

设置这个标志保护缓存在系统查找内存时被削减. 设置这个标志通常是个坏主意; 重要的是避免不必要地限制内存分配器的行动自由.

?

SLAB_HWCACHE_ALIGN

?

这个标志需要每个数据对象被对齐到一个缓存行; 实际对齐依赖主机平台的缓存分 布. 这个选项可以是一个好的选择,如果在 SMP 机器上你的缓存包含频繁存取的 项. 但是,用来获得缓存行对齐的填充可以浪费可观的内存量.

?

SLAB_CACHE_DMA

?

这个标志要求每个数据对象在 DMA 内存区分配.

?

还有一套标志用来调试缓存分配; 详情见 mm/slab.c. 但是,常常地,在用来开发的系统 中,这些标志通过一个内核配置选项被全局性地设置

?

函数的 constructor 和 destructor 参数是可选函数( 但是可能没有 destructor,如果 没有 constructor ); 前者可以用来初始化新分配的对象,后者可以用来"清理"对象在它 们的内存被作为一个整体释放回给系统之前.

?

构造函数和析构函数会有用,但是有几个限制你必须记住. 一个构造函数在分配一系列对 象的内存时被调用; 因为内存可能持有几个对象,构造函数可能被多次调用. 你不能假设 构造函数作为分配一个对象的一个立即的结果而被调用. 同样地,析构函数可能在以后某 个未知的时间中调用,不是立刻在一个对象被释放后. 析构函数和构造函数可能或不可能 被允许睡眠,根据它们是否被传递 SLAB_CTOR_ATOMIC 标志(这里 CTOR 是 constructor 的缩写).

?

为方便,一个程序员可以使用相同的函数给析构函数和构造函数; slab 分配器常常传递 SLAB_CTOR_CONSTRUCTOR 标志当被调用者是一个构造函数.

?

一旦一个对象的缓存被创建,你可以通过调用 kmem_cache_alloc 从它分配对象. void *kmem_cache_alloc(kmem_cache_t *cache,int flags);

这里,cache 参数是你之前已经创建的缓存; flags 是你会传递给 kmalloc 的相同,并 且被参考如果 kmem_cache_alloc 需要出去并分配更多内存.

?

为释放一个对象,使用 kmem_cache_free:

?

void kmem_cache_free(kmem_cache_t *cache,const void *obj); 当驱动代码用完这个缓存,典型地当模块被卸载,它应当如下释放它的缓存:

?

?

int kmem_cache_destroy(kmem_cache_t *cache);

?

这个销毁操作只在从这个缓存中分配的所有的对象都已返回给它时才成功. 因此,一个模 块应当检查从 kmem_cache_destroy 的返回值; 一个失败指示某类在模块中的内存泄漏 (因为某些对象已被丢失.)

?

使用后备缓存的一方面益处是内核维护缓冲使用的统计. 这些统计可从 /proc/slabinfo 获得.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读