SCULL的内存使用

392 阅读2分钟

scull内存使用

scull使用的内存区域这里也称为设备,写的越多就越长,更短的文件以覆盖的方式写设备时会变短

scull驱动程序引入了Linux内核中用于内存管理的两个核心函数:

void*kmalloc(size_t size,int flags);  

对这个函数的调用将试图分配size个字节的大小的内存,其返回值返回指向该内存的指针,分配失败时返回NULL;flag用来描述内存的分配的方法,目前为止我们始终用GFP_KERNEL(其他参数以后学到再去研究)

void kfree(void *ptr); 

1、scull 中内存的分配方式:

在scull中每个设备都是一个指针链表,其中每个指针都指向一个scull_qset结构体如下:

struct scull_qset {
	void **data;
	struct scull_qset *next;
};

2、如何保存数据

在scull内部,它通过structscull_dev的结构来表示每个设备的信息,该结构体定义如下

struct scull_dev {
	struct scull_qset *data;  /* Pointer to first quantum set */
	int quantum;              /* the current quantum size */
	int qset;                 /* the current array size */
	unsigned long size;       /* amount of data stored here */
	unsigned int access_key;  /* used by sculluid and scullpriv */
	struct semaphore sem;     /* mutual exclusion semaphore     */
	struct cdev cdev;	  /* Char device structure		*/
};

3、以下代码说明了是如何利用scull_qset和scull_dev来保存数据,**scull_trim函数负责释放整个内存区(注释是自己对这个逻辑的理解)

(学会这种存储数据的方式以及锻炼这种思维能力才是最重要的)

#include "scull.h"


int scull_quantum = SCULL_QUANTUM;
int scull_qset = SCULL_QSET;
/* 
scull_trim 负责释放整个数据区
scull_dev *dev 表示每个设备
scull_dev 中 *data指向一个scull_qset的链表,链表中的s
 
*/
int scull_trim(struct scull_dev *dev){
	struct scull_qset *next,*dptr;
	int qset = dev->qset;//量子集中量子的个数
	int i;
	//dptr = dev->data 第一次运行指向的是第一个链表项
	//scull_qset 表示量子集,由next链接到下一个链表项即下一个量子集
	//注意 dptr也是一个指针变量
	//理解此函数主要理解两个for循环
	for(dptr = dev->data;dptr;dptr = next){
		/* 
		dptr->data 表示当前量子内的数据
		
		*/
	if(dptr ->data){
		for(i = 0;i <qset;i++ )//释放一个量子集的空间
		    //每次循环都释放一个量子的空间,一个量子集共有qset个量子
			//data 是一个二级指针变量,kfree参数是一个指针变量
			//data[i] data是一个二级指针,表明它指向的单元存放的是一个指针,这个指针指向的地址才存放着真正的数据(量子)
			kfree(dptr->data[i])
		kfree(dptr->data)
		dptr->data = NULL;
	}
    next = dptr->next;
    kfree(dptr);//释放当前列表项所有量子集的空间
	}
	dev->size = 0;
	dev->quantum = scull_quantum;//量子的大小。量子:表示申请内存的最小单位
	dev->qset = scull_qset;
	dev->data = NULL;
	return 0;
}