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;
}