Solaris 模块调试器指南

分配器基础知识

内核内存分配器的作用是将虚拟内存中的区域分配给其他内核子系统(它们通常称为客户机)。本节说明了分配器操作的基础知识,并介绍了本指南中稍后使用的一些术语。

缓冲区状态

内核内存分配器的作用域是虚拟内存中组成内核堆的缓冲区集。 这些缓冲区将会分组为具有相同大小和用途的各缓冲区集(称为高速缓存)。 每个高速缓存都包含一组缓冲区。 其中的一些缓冲区当前空闲,这意味着尚未将其分配给分配器的任何客户机。 其余的缓冲区已分配,这意味着已将指向该缓冲区的指针提供给分配器的客户机。 如果分配器的所有客户机中都没有指向已分配的缓冲区的指针,则认为此缓冲区发生了泄漏,因为无法将其释放。 泄漏的缓冲区表明错误的代码正在浪费内核资源。

事务

kmem 事务是指缓冲区在已分配状态和空闲状态之间的转换。 分配器可以在每个事务执行过程中验证缓冲区的状态是否有效。此外,分配器还包含用于记录事务的工具,以便进行事后检查。

休眠分配和非休眠分配

与标准 C 库的 malloc(3C) 函数不同,内核内存分配器可以阻塞(或休眠),一直等到有足够的虚拟内存可用于满足客户机的请求为止。 这一行为由 kmem_alloc(9F) 的 'flag' 参数控制。调用设置了 KM_SLEEP 标志的 kmem_alloc(9F) 决不会失败;它将永远阻塞,等待资源变为可用。

内核内存高速缓存

内核内存分配器会将其管理的内存分为一组高速缓存。 所有分配都是从这些高速缓存(通过 kmem_cache_t 数据结构表示)实现的。每个高速缓存都具有固定的缓冲区大小,表示该高速缓存可提供的最大分配空间。 每个高速缓存都具有一个指明其管理的数据类型的字符串名称。

一些内核内存高速缓存具有特殊用途,并会进行初始化以便仅分配特定种类的数据结构。 "thread_cache" 即是此类高速缓存的一个示例,它仅分配 kthread_t 类型的结构。 这些高速缓存中的内存通过 kmem_cache_alloc() 函数分配给客户机,并且通过 kmem_cache_free() 函数释放。


注意 –

kmem_cache_alloc()kmem_cache_free() 不是公共的 DDI 接口。请勿编写依赖于这些接口的代码,因为将来的 Solaris 发行版中可能会更改或删除这些接口。


名称以 "kmem_alloc_" 开头的高速缓存可实现内核的常规内存分配方案。 这些高速缓存为 kmem_alloc(9F)kmem_zalloc(9F) 的客户机提供内存。 其中的每个高速缓存都满足大小介于此类高速缓存的缓冲区大小和第二小的高速缓存的缓冲区大小之间的请求。 例如,内核具有 kmem_alloc_8kmem_alloc_16 高速缓存。 在这种情况下,kmem_alloc_16 高速缓存可处理大小为 9-16 个字节内存的所有客户端请求。 请记住,无论客户端请求的大小是多少,kmem_alloc_16 高速缓存中每个缓冲区的大小均为 16 个字节。对于大小为 14 个字节的请求,所得到缓冲区中有两个字节是未使用的,因为该请求是从 kmem_alloc_16 高速缓存得到满足的。

最后一组高速缓存是指由内核内存分配器在内部使用以对其自身进行记录的高速缓存。 这包括名称以 "kmem_magazine_" 或 "kmem_va_"、kmem_slab_cachekmem_bufctl_cache 等开头的那些高速缓存。