1.5.1 高速缓冲区(memory cache)
内核使用函数kmalloc和kfree来分配和释放内存块。这两个函数的使用语法与用户空间C库函数的malloc和free类似。在内核的各种组件中,经常需要为同一类型数据结构分配多个实例,如存放网络数据包的Socket Buffer。当分配内存空间和释放内存的操作发生得非常频繁时,内核组件的初始化函数通常为自己初始化一个特殊的高速缓冲区来为其数据结构分配内存空间,在数据对象使用结束释放内存时,释放的内存返回给它分配的高速缓冲区。
内核的网络子系统中维护和管理的高速缓冲区包括以下几种。
1.套接字缓冲区描述符
套接字缓冲区描述符(socket buffer descriptor)的高速缓冲区,由skb_init(定义在net/core/sk_buff.c文件中)函数初始化,用于为sk_buff缓冲区描述符分配内存。在网络子系统中,sk_buff数据结构是分配、释放操作最频繁的一个数据结构。在第2章中,我们将详细介绍sk_buff数据结构的各数据域。
2.邻居协议映射高速缓冲区
在网络子系统中的每个邻居协议都使用一个内存高速缓冲区分配内存,来存放网络层至数据链路层(L3到L2)的地址映射关系。我们将在第8章讲解邻居协议的实现。
3.路由表
路由子系统中使用了两个主要数据结构来定义路由,相应的路由子系统初始化了两个内存高速缓冲存储器,为这两个数据结构的实例分配内存。
内核中管理内存高速缓冲区的关键函数有:kmem_cache_create和kmem_cache_destroy,用于创建和释放高速缓冲区。kmem_cache_alloc从高速缓存中分配内存给数据对象,kmem_cache_free释放内存对象,将缓冲区返回给高速缓存。
在内核的各组件中有各自对以上高速缓存管理函数的包装函数,所以在内核组件中,常通过包装函数来为数据对象分配内存和释放数据对象占用的内存空间。例如,释放一个sk_buff缓冲区的实例时,网络子系统调用kfree_skb,kfree_skb在所有进程对的引用都释放,完成所有清除工作后,最终调用kmem_cache_free来将缓冲区释放。