- 1、本文档共5页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
8.2. 后备缓存
8.2. 后备缓存
8.2. 后备缓存
⼀个设备驱动常常以反复分配许多相同⼤⼩的对象⽽结束. 如果内核已经维 了⼀套
相同⼤⼩对象的内存池, 为什么不增加⼀些特殊的内存池给这些⾼容量的对象? 实际
上, 内核确实实现了⼀个设施来创建这类内存池, 它常常被称为⼀个后备缓存. 设备驱
动常常不展⽰这类的内存⾏为, 它们证明使⽤⼀个后备缓存是对的, 但是, 有例外; 在
Linux 2.6 中 USB 和 SCSI 驱动使⽤缓存.
Linux 内核的缓存管理者有时称为 slab 分配器. 因此, 它的功能和类型在
linux/slab .h 中声明. slab 分配器实现有⼀个 kmem_cache_ 类型的缓存; 使⽤⼀个对
kmem_cache_crea e 的调⽤来创建它们:
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 *, kmem_cache_t *,
这个函数创建⼀个新的可以驻留任意数⽬全部同样⼤⼩的内存区的缓存对象, ⼤⼩由
size 参数指定. name 参数和这个缓存关联并且作为⼀个在追踪问题时有⽤的管理信息;
通常, 它被设置为被缓存的结构类型的名⼦. 这个缓存保留⼀个指向 name 的指针, ⽽不
是拷贝它, 因此驱动应当传递⼀个指向在静态存储中的名⼦的指针(常常这个名⼦只是
⼀个⽂字字串) . 这个名⼦不能包含空格.
offse 是页内的第⼀个对象的偏移; 它可被⽤来确保⼀个对被分配的对象的特殊对齐,
但是你最可能会使⽤ 0 来请求缺省值. flags 控制如何进⾏分配并且是下列标志的⼀个
位掩码:
SLAB_NO_REAP
设置这个标志保 缓存在系统查找内存时被削减. 设置这个标志通常是个坏主意; 重要
的是避免不必要地限制内存分配器的⾏动⾃由.
SLAB_HWCACHE_ALIGN
这个标志需要每个数据对象被对齐到⼀个缓存⾏; 实际对齐依赖主机平台的缓存分布.
这个选项可以是⼀个好的选择, 如果在 SMP 机器上你的缓存包含频繁存取的项. 但是,
⽤来获得缓存⾏对齐的填充可以浪费可观的内存量.
SLAB_CACHE_DMA
这个标志要求每个数据对象在 DMA 内存区分配.
还有⼀套标志⽤来调试缓存分配; 详情见 mm/slab .c . 但是, 常常地, 在⽤来开发的系统
中, 这些标志通过⼀个内核配置选项被全局性地设置
函数的 cons ruc or 和 des ruc or 参数是可选函数( 但是可能没有 des ruc or , 如果没有
cons ruc or ); 前者可以⽤来初始化新分配的对象, 后者可以⽤来清理对象在它们的内
存被作为⼀个整体释放回给系统之前.
构造函数和析构函数会有⽤, 但是有⼏个限制你必须记住. ⼀个构造函数在分配⼀系列
对象的内存时被调⽤; 因为内存可能持有⼏个对象, 构造函数可能被多次调⽤. 你不能
假设构造函数作为分配⼀个对象的⼀个⽴即的结果⽽被调⽤. 同样地, 析构函数可能在
以后某个未知的时间中调⽤, 不是⽴刻在⼀个对象被释放后. 析构函数和构造函数可能
或不可能被允许睡眠, 根据它们是否被传递 SLAB_CTOR_ATOMIC 标志(这⾥ CTOR
是 cons ruc or 的缩写) .
为⽅便, ⼀个程序员可以使⽤相同的函数给析构函数和构造函数; 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);
当驱动代码⽤完这个缓存,
文档评论(0)