北大linux大作业

发布 2022-09-10 10:10:28 阅读 9658

linux 内核slab 机制。

随着linux 操作系统越来越普及和广泛应用,尤其在嵌入式领域越来越受关注,越来越多的人开始研究linux 内核。linux 是开放源**的,所以在中国更加应该受到关注,对于促进中国开发自主的操作系统具有积极的意义。现在,希望越来越多的人投入到这个热潮中来。

下面介绍linux 分配管理内核中的数据结构(或对象)的方法——slab 缓冲区管理器。

1 为什么选择slab

linux 内核在运行中常常需要动态地分配一些缓冲区。比如当打开一个文件时需要建立与文件磁盘索引节点对应的struct inode 类型的内存索引节点数据结构,还有与磁盘目录项对应的struct dentry 类型的内存目录项数据结构。这些数据结构在运行中根据需要动态建立,不像内核**和内核全局变量既不需要分配,也不需要释放,是静态的。

这些小块存储空间是动态变化的,运行中就会有申请内存与释放内存的问题。

那么小对象存储空间的管理,该用什么方法呢?先考虑下面几种情况。

对于这些小块存储空间,如果按照常规的内存分配方法调用alloc_pages ()整页整页的分配,由于根本用不了这么多空间,这样就造成浪费。对于这种情况,何不在分配的内存页中放几个小对象呢?

每次分配的小对象存储空间一般都要进行初始化(如队列头初始化,因为这些小对象一般都会加入若干队列)。如果这些对象释放后,不释放占用的页面内存,下次分配同类对象时就可以重用这些对象,从而不需初始化,那就可以提高内核效率。

针对小对象存储空间的使用问题,linux采用了一种称为“slab”的缓冲区分配和管理方法。

2 slab 管理器原理。

在 slab 方法中,每种重要的数据结构都有自己的专用缓冲区队列,每种数据结构都有相应的“构造”( constructor )和“析构”( destructor )函数。同时,还借用面向对象程序设计技术中的名词,不再称“结构”而称“对象”( object )。缓冲区队列中的各个对象在建立时用其“构造”函数进行初始化,所以一经分配立即就能使用,而在释放时则恢复成原状。

每个队列中对象的个数是动态变化的,不够时可以增添。同时,又定期地检查,将有富余的队列加以精简。

此外,slab 管理方法还有个特点,每种对象的缓冲区队列并非由各个对象直接构成,而是由一连串的“大块”( slab )构成,而每个slab 块中则包含了若干同种对象。每个这样的一个slab 块由一个slab_t 类型的数据结构描述,而且,这个slab_t 数据结构本身也放在slab 块中(后面将会提到,对于大对象,为了充分利用slab 空间,把slab 描述结构和对象链接数组存放在通用缓冲区中)。图1 就是slab 块结构示意图。

每个 slab 可能由2 的幂次方个(最多32 个)连续的物理页面构成,具体大小因对象大小而异。每个slab 上都有一个slab描述结构,描述它所在的slab,提供slab 的管理信息。用于同一种对象的多个slab 通过slab 描述结构中的list 字段链接在一起。

而这些slab 分成3 截:第1 截是各个slab 上所有对象都已分配使用;第2 截是各个slab 上的对象部分地分配使用;第3 截是各个slab 上的对象全部是空闲对象。每个slab上有一个对象区,这就是对象存放的地方,是对象数据结构的数组。

每个slab 上还有一个对象链接数组,实际上是一个整型数组,用来实现一个空闲对象链,与对象区的对象数组对应。在slab 描述结构中有一个free 整型字段,表明第1 个空闲对象下标。free 字段和对象链接数组就构成了一个空闲对象链。

比如free 为5,则第1 个空闲对象下标为5,如果对象链接数组下标为5 的元素的值为3,则下一个空闲对象就是对象区下标为3 的对象。最后一个空闲对象下标对应的对象链接数组中的元素的值为bufctl(0xffffffff)。slab 最前面是着色区,这是为了使slab 中的每个对象起始地址按高速缓存中的缓冲行大小对齐而留下的空白区。

slab 最后面是着色补偿区。

3 slab 相关数据结构。

下面是 slab 描述结构slab_t 的定义:

typedef struct slab_s

struct list_head list;

unsigned long colouroff;

void *s_mem; /including colour offset */

unsigned int inuse; /num of objs active in slab */

kmem_bufctl_t free;

slab_t;

字段说明:list:每种对象的缓冲区都由若干slab 块构成,这些slab块通过list 字段构成slab 链;

colouroff:着色区大小,实际上包括着色区大小、slab_t描述结构大小和对象链接数组大小,即为第1 个对象距离slab开始地址的距离;

s_mem:指向第1 个对象;

inuse:本slab 中已经分配使用的对象数;

free:第1 个空闲对象在对象区的下标。为每种对象建立的 slab 队列都有个队列头, 其控制结构数据类型为kmem_cache_t 。

该数据结构中除用来维持slab 队列的各种指针外,还记录了适用于队列中每个slab 的各种参数,以及两个函数指针:一个是对象的构造函数,另一个是析构函数。

队列头控制结构对象的数据类型为kmem_cache_t(这个数据结构字段较多,由于篇幅有限,这里就不一一列出,请参考源**文件:mm\如下:

struct kmem_cache_s {

//字段定义请参考源**文件:mm\

typedef struct kmem_cache_s kmem_cache_t;

主要字段说明:

slabs:slab 队列的队列头,每种对象的缓冲区由若干个slab 构成,这些slab 链成一个队列;

firstnotfull:指向第一个含有空闲对象的slab;

objsize:对象大小;

num:每个slab 中的对象数;

gfporder:每个slab 的页面数为2 的gfporder 次方;

slabp_cache:当slab_t 描述数据结构和对象链接数组不在slab 中时,它指向存放slab_t 描述结构和对象链接数组的通用缓冲区队列的队列头;

ctor,dtor:对象的构造和析构函数指针;

colour,colour_off ,colour_next:着色区大小计算的几个字段。

每个这样的队头需要一个 kmem_cache_t 数据结构,可见这个队头也是动态的,对这些队头的管理内核也是通过slab队列来管理的,其队头又是一个kmem_cache_t 数据结构,这个数据结构的内核变量名为cache_cache,是内核中的一个全局变量。

这样,就形成了一种层次式的树形结构:

总根 cache_cache 是一个kmem_cache_t 结构,用来维持第1 层slab 队列,这些slab 上对象都是kmem_cache_t 数据结构。第1 层slab 上的每个对象,即kmem_cache_t 数据结构都是队头,用来维持一个第2 层slab 队列。第2 层slab队列基本上都是某种对象,即数据结构专用的队列。

内核中cache_cache 定义如下:

static kmem_cache_t cache_cache =

slabs: list_head_init(cache_

firstnotfull: &cache_

objsize: sizeof(kmem_cache_t),flags: slab_no_reap,spinlock:

spin_lock_unlocked,colour_off: l1_cache_bytes,name: "kmem_cache",;

总体的组织如图2 所示。

第 1 层是一个kmem_cache_t 控制对象的slab 队列,里面存放的对象是一些kmem_cache_t 对象, 队列头是cache_cache 全局变量,这个变量本身也是一个kmem_cache_t类型的控制对象。第1 层队列中存放的每一个对象kmem_cache_t 是一个第2 层slab 队列的队列头,比如图2 所示kmem_cache_t 类型指针node_cachep 所指向的就是一个第1 层队列中的一个控制对象,而这个对象又是内存索引节点slab 队列的队列头。图中举了一个内核比较常用的对象的缓冲区队列inode_cachep,这就是内存索引节点的缓冲区队列头指针,指向在第1 层slab 队列中分配的索引节点控制结构队列头。

slab 管理方法中对象的分配和**不是以单个对象进行的,而是以slab 为单位进行的。

当内核中分配某个对象的空间时,首先在slab 队列中查找空闲对象,如果没有空闲对象了,就分配队列头控制结构中字段gfporder 指定的2 的gfporder 次方个物理页面,这些页面构成一个slab,初始化这个slab,包括调用队列头中指定的构造函数初始化对象区中的各个对象,并把这个slab 链入slab 队列,以后就可以在这个slab 中分配空闲对象了。

**时,内核在 slab 队列中从后往前(因为空闲slab 在队尾)查看每个队列,如果slab 描述结构中字段inuse 为0,就表明这个slab 是空闲的,可以**占用的物理内存页面,同时还要对slab 中的每个对象调用析构函数,并从slab 队列中脱链。

本文结合 linux,介绍了slab 缓冲区管理器的原理以及在linux 内核中的广泛应用。内核中需要动态分配许多常用或不常用的数据结构,这些数据结构经过分配、使用和**的过程,需要一种高效管理方法,slab 管理器正是这样一种方法。

Linux大作业

linux基础与应用 学生姓名张振东。学号 5011210108 专业计算机科学与技术 班级计算机14 1 所属学院信息工程学院 指导教师范振岐。塔里木大学教务。目录。引言 1 1 实习的目的和意义 1 2实习目标与总体方案 3 2.1 熟悉基本网络命令 3 2.2 配置nfs服务器以及配置samb...

Linux大作业

石家庄学院。课程设计报告。一 题目分析 通过对web服务器的有关配置,深刻理解web服务器的功能,并学会如何配置基于ip,基于端口,基于域名的虚拟主机。二 制作过程 2.1 配置基于ip的虚拟主机 下面介绍在 192.168.0.8 和192.168.0.9 上创建两个基于ip 地址的虚拟主机的配置...

Linux大作业

linux课程 学生姓名张振东 学号 5011210108 专业计算机科学与技术 班级计算机14 1 所属学院信息工程学院 塔里木大学教务处制。引言。linux是一套免费使用和自由传播的类unix操作系统,是一个基于posix和unix的多用户 多任务 支持多线程和多cpu的操作系统。它能运行主要的...