这次分析的是LDD3中的第一个程序scull
scull设备也是一个内存”设备“
结构图如下,来自LDD3
/*
* Representation of scull quantum sets.
*/
struct scull_qset {
void **data;//指针的指针,(*data)是一个指针变量,指示一片内存空间,这片内存中间内存储的也是地址
struct scull_qset *next;
};
struct scull_dev {
struct scull_qset *data; /* Pointer to first quantum set *///第一个scull_qset的地址
int quantum; /* the current quantum size *///每一个数据块的大小
int qset; /* the current array size *///每个scull_qset包含多少个指针
unsigned long size; /* amount of data stored here *///设备中有多少可用的数据内存,也就是Quantum中的内存数据。
unsigned int access_key; /* used by sculluid and scullpriv */
struct semaphore sem; /* mutual exclusion semaphore *///信号量
struct cdev cdev; /* Char device structure *///字符设备结构
};
//主程序
/*
* 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 <linux/config.h>
#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;
int scull_minor = 0;
int scull_nr_devs = SCULL_NR_DEVS; /* number of bare scull devices */
int scull_quantum = SCULL_QUANTUM; //4000
int scull_qset = SCULL_QSET; //1000
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);
MODULE_AUTHOR("Alessandro Rubini, Jonathan Corbet");
MODULE_LICENSE("Dual BSD/GPL");
struct scull_dev *scull_devices; /* allocated in scull_init_module */
/*
* Empty out the scull device; must be called with the device
* semaphore held.
*///释放数据结构,最后剩下scull_dev结构
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) { /* all the list items */
if (dptr->data) {
for (i = 0; i < qset; i++)//遍历指针数组中的每个元素,释放其所指的空间
kfree(dptr->data[i]);
kfree(dptr->data); //最后释放这个指针数组。
dptr->data = NULL; //置空
}
next = dptr->next;
kfree(dptr); //释放scull_qset结构
}
dev->size = 0; //表示设备拥有的可读写的数据内存
dev->quantum = scull_quantum; //重置各个参数
dev->qset = scull_qset;
dev->data = NULL;
return 0;
}
#ifdef SCULL_DEBUG /* use proc only if debugging */
/*
* The proc filesystem: function to read and entry
*/
int scull_read_procmem(char *buf, char **start, off_t offset,
int count, int *eof, void *data)
{
int i, j,