/***************************************************************************************************
scull.h
***************************************************************************************************/
#ifndef _SCULL_H_
#define _SCULL_H_
/***************************************************************************************************
常量定义
***************************************************************************************************/
#ifndef SCULL_MAJOR
#define SCULL_MAJOR 0 //dynamic major by default 缺省的主设备号
#endif
#ifndef SCULL_NR_DEVS
#define SCULL_NR_DEVS 4 // scull0 1 2 3
#endif
#ifndef SCULL_QUANTUM //量子大小,单位字节
#define SCULL_QUANTUM 400
#endif
#ifndef SCULL_QSET //量子集大小
#define SCULL_QSET 100
#endif
/***************************************************************************************************
数据结构定义
***************************************************************************************************/
/* scull 数据模型
是一个结构,见下表。
scull_qset是一个链表结构
一个指针指向下一个结构。
一个指针指向一个量子集。
量子集是n=1000个指针的数组,每个指针指向一块内存,此内存有m=4000字节大。一块内存即是以个量子。
两模型如下:*/
struct scull_qset
{
void **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 一个量子的大小, 默认4000
int qset; // the current array size 一个量子集的个数,默认1000
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 设备
};
/***************************************************************************************************
全局变量声明
***************************************************************************************************/
//声明在 scull.c 的全局变量
extern int scull_major;
extern int scull_nr_devs;
extern int scull_quantum;
extern int scull_qset;
/***************************************************************************************************
函数声明
***************************************************************************************************/
//-------------------------------file_operations 操作函数声明---------------------------------------
loff_t scull_llseek(struct file *filp, loff_t off, int whence);
ssize_t scull_read(struct file *filp, char __user *buf, size_t count,loff_t *f_pos);
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos);
int scull_ioctl(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg);
int scull_open(struct inode *inode, struct file *filp);
int scull_release(struct inode *inode, struct file *filp);
//-------------------------------供调用的函数声明-----------------------------------------------
int scull_trim(struct scull_dev *dev);
int scull_p_init(dev_t dev);
void scull_p_cleanup(void);
int scull_access_init(dev_t dev);
void scull_access_cleanup(void);
//**************************************************************************************************
#endif
/***************************************************************************************************
scull.c
***************************************************************************************************/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h> /* everything... */
#include <linux/kernel.h>
#include <asm/uaccess.h> /* copy_*_user */
#include <linux/cdev.h> //cdev
#include <linux/types.h> /* size_t */
#include <linux/slab.h> /* kmalloc() */
#include <linux/device.h> //class_create
//#include <linux/moduleparam.h>
#include <linux/errno.h> /* error codes */
#include <linux/proc_fs.h>
//#include <linux/fcntl.h> /* O_ACCMODE */
//#include <linux/seq_file.h>
//#include <asm/system.h> /* cli(), *_flags */
#include "scull.h"
MODULE_LICENSE("Dual BSD/GPL");
/***************************************************************************************************
全局变量声明
***************************************************************************************************/
int scull_major = SCULL_MAJOR; //主设备号 scull.h #define=0
int scull_minor = 0; //次设备号
int scull_nr_devs = SCULL_NR_DEVS; //设备个数 = 4
int scull_quantum = SCULL_QUANTUM; //量子大小 = 400
int scull_qset = SCULL_QSET; //量子集大小 = 100
struct scull_dev *scull_devices=NULL; //在 scull_init_module 分配的设备存储区
struct class *scull_class0= NULL; //
struct class *scull_class1= NULL; //
struct class *scull_class2= NULL; //
struct class *scull_class3= NULL; //
//初始化设备的file_operations结构体,必须的。 此结构
struct file_operations scull_fops =
{
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release,
};
/***************************************************************************************************
file_operations 函数实现
注:
他们都是 static 函数,应该再前面加 static 关键字的
***************************************************************************************************/
loff_t scull_llseek(struct file *filp, loff_t off, int whence)
{
return 0;
}
ssize_t scull_read(struct file *filp, char __user *buf, size_t count,loff_t *f_pos)
{
return 0;
}
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
{
return 0;
}
int scull_ioctl(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg)
{
return 0;
}
int scull_open(struct inode *inode, struct file *filp)
{
return 0;
}
int scull_release(struct inode *inode, struct file *filp)
{
return 0;
}
//--------------------------------------------------------------------------------------------------
int scull_trim(struct scull_dev *dev)
{
return 0;
}
int scull_p_init(dev_t dev)
{
return 0;
}
void scull_p_cleanup(void)
{
}
int scull_access_init(dev_t dev)
{
return 0;
}
void scull_access_cleanup(void)
{
}
static void scull_setup_cdev(struct scull_dev *dev, int index)
{
int err, devno = MKDEV(scull_major, scull_minor + index);
cdev_init(&dev->cdev, &scull_fops); //
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &scull_fops;
err = cdev_add (&dev->cdev, devno, 1); //
if (err)
{
printk(KERN_ALERT "Error %d adding scull%d \n", err, index);
}else
{
printk(KERN_ALERT "adding successd scull_number = %d \n", devno);
}
}
/***************************************************************************************************
注册和注销模块
***************************************************************************************************/
static void scull_cleanup_module(void);
static int scull_init_module(void);
static int scull_init_module(void)
{
int result, i;
dev_t dev = 0;
//---------------------------注册设备号---------------------------------------------------------
if (scull_major)
{
dev = MKDEV(scull_major, scull_minor);
result = register_chrdev_region(dev, scull_nr_devs, "scull"); //注册设备
}else
{
result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs,"scull"); //自动分配设备号,并注册
scull_major = MAJOR(dev);
}
if (result < 0)
{
printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
return result;
}
//一组实测数据number=264241152,major=252,minor=0
printk(KERN_ALERT "sucll chrdev region successd : \n");
printk(KERN_ALERT "scull scull_number : %d \n",dev);
printk(KERN_ALERT "scull scull_major : %d \n",scull_major);
printk(KERN_ALERT "scull scull_minor : %d \n",scull_minor);
//-----------------------------分配存储---------------------------------------------------------
scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL);
if (!scull_devices)
{
result = -ENOMEM;
goto fail; /* Make this more graceful */
}
memset(scull_devices, 0, scull_nr_devs * sizeof(struct scull_dev));
//-------------------------------建立设备-------------------------------------------------------
//设备建立后,可以使用lsmod 或cat /proc/devices 查看。
for (i = 0; i < scull_nr_devs; i++)
{
scull_devices[i].quantum = scull_quantum;
scull_devices[i].qset = scull_qset;
init_MUTEX(&scull_devices[i].sem);
scull_setup_cdev(&scull_devices[i], i); //
}
//-------------------------------将设备加入到节点-----------------------------------------------
//scull_class0 = class_create(THIS_MODULE, "scull_class0"); //在/sys目录下建立了一个scull_class0的目录
//if (IS_ERR(scull_class0))
//{
// scull_class0 = NULL;
// printk(KERN_INFO "scull_class0 create error \n");
// result = -ENOMEM;
// goto fail;
//}
//printk(KERN_ALERT "scull_class0 create seccse , scull_class0_num = %d \n",dev);
//
//device_create(scull_class0,NULL,dev,NULL,"scull" "%d", MINOR(dev));
printk(KERN_ALERT "gvar create seccse , gvar_num = %d \n",gvar_num);
销毁
//if( NULL != scull_class0)
//{
// device_destroy(scull_class0, devno);
// class_destroy(scull_class0);
//}
//mknod /dev/scull c 20748 0
return 0; // succeed
fail:
scull_cleanup_module();
return result;
}
static void scull_cleanup_module(void)
{
int i;
dev_t devno = MKDEV(scull_major, scull_minor);
//--------------------------------去掉scull_nr_devs个设备------------------------------------------
if (NULL != scull_devices)
{
for (i = 0; i < scull_nr_devs; i++)
{
printk(KERN_ALERT "removd successd scull_number = %d \n", (devno + scull_nr_devs));
}
kfree(scull_devices);
}
//-------------------------------注销设备---------------------------------------------------------
unregister_chrdev_region(devno, scull_nr_devs);
printk(KERN_ALERT "sucll goodbye !\n");
}
module_init(scull_init_module);
module_exit(scull_cleanup_module);