- 论坛徽章:
- 0
|
/*
* main.c -- the bare scull char module
*
* Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
* Copyright (C) 2001 O'Reilly & Associates
*
* The source code in this file can be freely used, adapted,
* and redistributed in source or binary form, so long as an
* acknowledgment appears in derived source files. The citation
* should list that the code comes from the book "Linux Device
* Drivers" by Alessandro Rubini and Jonathan Corbet, published
* by O'Reilly & Associates. No warranty is attached;
* we cannot take responsibility for errors or fitness for use.
*
*/
/*#include */
#include linux/module.h>
#include linux/moduleparam.h>
#include linux/init.h>
#include linux/kernel.h> /* printk() */
#include linux/slab.h> /* kmalloc() */
#include linux/fs.h> /* everything... */
#include linux/errno.h> /* error codes */
#include linux/types.h> /* size_t */
#include linux/proc_fs.h>
#include linux/fcntl.h> /* O_ACCMODE */
#include linux/seq_file.h>
#include linux/cdev.h>
#include asm/system.h> /* cli(), *_flags */
#include asm/uaccess.h> /* copy_*_user */
#include "scull.h" /* local definitions */
/*
* Our parameters which can be set at load time.
*/
int scull_major = SCULL_MAJOR; /*全局主设备号,为了动态分配,初始化为SCULL_MAJOR*/
int scull_minor = 0; /*全局次设备号*/
int scull_nr_devs = SCULL_NR_DEVS; /*全局的设备个数*/
int scull_quantum = SCULL_QUANTUM; /*全局量子数目*/
int scull_qset = SCULL_QSET; /*全局量子集数目*/
module_param(scull_major, int, S_IRUGO);
module_param(scull_minor, int, S_IRUGO);
module_param(scull_nr_devs, int, S_IRUGO);
module_param(scull_quantum, int, S_IRUGO);
module_param(scull_qset, int, S_IRUGO);
/*模块参数声明,允许在insmod或modprobe装载模块时对参数进行赋值*/
MODULE_AUTHOR("Alessandro Rubini, Jonathan Corbet");
MODULE_LICENSE("Dual BSD/GPL");
struct scull_dev *scull_devices; /* 指向设备结构的全局指针,在scull_init_module中才分配空间 */
/*
* Empty out the scull device; must be called with the device
* semaphore held.
释放整个数据区,并且以写入方式打开时由scull_open调用,在模块清除函数中也会被调用。
*/
int scull_trim(struct scull_dev *dev)
{
struct scull_qset *next, *dptr;
int qset = dev->qset; /* "dev" is not-null */
int i;
for (dptr = dev->data; dptr; dptr = next) { /* 遍历链表,释放内存 */
if (dptr->data) {
for (i = 0; i qset; i++) /*释放量子*/
kfree(dptr->data);
kfree(dptr->data);
dptr->data = NULL;
}
next = dptr->next;
kfree(dptr);
}
dev->size = 0; /*重设scull_devices*/
dev->quantum = scull_quantum;
dev->qset = scull_qset;
dev->data = NULL;
return 0;
}
/*
scull_trim的实现相当于遍历了链表,先用dptr指针作为游标,指向每一个scull_qset,再通过量子集的大小dev->qset,在for循环中对dptr->data中的每一个量子进行释放。dptr->data是一个指针数组,所以kfree的参数为dptr->data。把量子集释放后再释放dptr->data.接着通过next指针移动游标,再释放当前的dptr。完整的内存释放后再对scull_devices初始化。
*/
以下是scull_trim函数的图解
![]()
待续....
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/75473/showart_1274224.html |
|