一个测试用的驱动--循环池!
时间:2006-10-15 来源:jiok
test.h
#define MAJOR 126
#define NR 4
#define SIZE 1024
struct test_dev{
char *data;
unsigned int size;
struct semaphore sem;
struct cdev cdev;
};
test.c #include<linux/init.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/types.h>
#include<linux/slab.h>
#include<linux/errno.h>
#include<linux/cdev.h>
#include<asm/uaccess.h>
#include"test.h"
///////////////////////////////////////////
int test_major=MAJOR;
int test_minor=0;
int test_nr=NR;
int test_size=SIZE;
module_param(test_major,int,S_IRUGO);
MODULE_AUTHOR("jiok");
MODULE_DESCRIPTION("This is a test driver");
MODULE_LICENSE("GPL");
/////////////////////////////////////////
struct test_dev *test_device;
/////////////////////////////////////////
void test_clear(struct test_dev *dev)
{
kfree(dev->data);
dev->size=0;
dev->data=NULL;
}
static int test_open(struct inode *inode,struct file *filp)
{
struct test_dev *dev;
dev=container_of(inode->i_cdev,struct test_dev,cdev);
filp->private_data=dev;
if((filp->f_flags & O_ACCMODE)==O_WRONLY){
test_clear(dev);
}
return 0;
}
static int test_release(struct inode *inode,struct file *filp)
{
return 0;
}
static ssize_t test_read(struct file *filp,char __user *buf,size_t count,loff_t *f_pos)
{
struct test_dev *dev=filp->private_data;
int reval=0,pos=0;
if(down_interruptible(&dev->sem))
return -ERESTARTSYS;
pos=(long)*f_pos%test_size;
if(count>dev->size)
count=dev->size;
if(copy_to_user(buf,dev->data+pos,count)){
reval=-EFAULT;
goto fail;
}
*f_pos+=count;
reval=count;
fail:
up(&dev->sem);
return count;
}
static ssize_t test_write(struct file *filp,char __user *buf,size_t count,loff_t *f_pos)
{
struct test_dev *dev=filp->private_data;
char *test_data=NULL;
int pos=0;
int reval=0;
if(down_interruptible(&dev->sem))
return -ERESTARTSYS;
pos=(long)*f_pos%test_size;
if(dev->data==NULL){
test_data=kmalloc(dev->size*sizeof(char),GFP_KERNEL);
dev->data=test_data;
}
if(!test_data){
reval=-ENOMEM;
goto fail;
}
if(pos+count>test_size)
count=test_size-pos;
if(copy_from_user(dev->data+pos,buf,count)){
reval=-EFAULT;
goto fail;
}
dev->size+=count;
*f_pos+=count;
reval=count;
fail:
up(&dev->sem);
return reval;
}
/////////////////////////////////////////
struct file_operations test_fops = {
.owner = THIS_MODULE,
.read = test_read,
.write = test_write,
.open = test_open,
.release = test_release,
};
//////////////////////////////////////////
static int test_init(void)
{
unsigned int result;
dev_t devno;
int i;
if(test_major){
devno=MKDEV(test_major,test_minor);
result=register_chrdev_region(devno,test_nr,"test");
}else{
result=alloc_chrdev_region(&devno,test_minor,test_nr,"test");
// test_major=MAJOR(devno);
}
if(result<0){
printk("test can't get major");
return 0;
}
test_device=kmalloc(test_nr*sizeof(struct test_dev),GFP_KERNEL);
if(!test_device) {
result=-ENOMEM;
goto fail;
}
memset(test_device,0,test_nr*sizeof(struct test_dev));
for(i=0;i<test_nr;i++){
devno=MKDEV(test_major,test_minor+i);
(test_device+i)->size=test_size;
init_MUTEX(&test_device[i].sem);
cdev_init(&test_device[i].cdev,&test_fops);
test_device[i].cdev.owner=THIS_MODULE;
test_device[i].cdev.ops=&test_fops;
if(cdev_add(&test_device[i].cdev,devno,1))
printk("error adding testdevice%d",i);
}
return 0;
fail:
return result;
}
static void test_cleanup(void)
{
dev_t devno=MKDEV(test_major,test_minor);
int i;
for(i=0;i<test_nr;i++){
cdev_del(&test_device[i].cdev);
}
kfree(test_device);
unregister_chrdev_region(devno,test_nr);
}
module_init(test_init);
module_exit(test_cleanup);
#define MAJOR 126
#define NR 4
#define SIZE 1024
struct test_dev{
char *data;
unsigned int size;
struct semaphore sem;
struct cdev cdev;
};
test.c #include<linux/init.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/types.h>
#include<linux/slab.h>
#include<linux/errno.h>
#include<linux/cdev.h>
#include<asm/uaccess.h>
#include"test.h"
///////////////////////////////////////////
int test_major=MAJOR;
int test_minor=0;
int test_nr=NR;
int test_size=SIZE;
module_param(test_major,int,S_IRUGO);
MODULE_AUTHOR("jiok");
MODULE_DESCRIPTION("This is a test driver");
MODULE_LICENSE("GPL");
/////////////////////////////////////////
struct test_dev *test_device;
/////////////////////////////////////////
void test_clear(struct test_dev *dev)
{
kfree(dev->data);
dev->size=0;
dev->data=NULL;
}
static int test_open(struct inode *inode,struct file *filp)
{
struct test_dev *dev;
dev=container_of(inode->i_cdev,struct test_dev,cdev);
filp->private_data=dev;
if((filp->f_flags & O_ACCMODE)==O_WRONLY){
test_clear(dev);
}
return 0;
}
static int test_release(struct inode *inode,struct file *filp)
{
return 0;
}
static ssize_t test_read(struct file *filp,char __user *buf,size_t count,loff_t *f_pos)
{
struct test_dev *dev=filp->private_data;
int reval=0,pos=0;
if(down_interruptible(&dev->sem))
return -ERESTARTSYS;
pos=(long)*f_pos%test_size;
if(count>dev->size)
count=dev->size;
if(copy_to_user(buf,dev->data+pos,count)){
reval=-EFAULT;
goto fail;
}
*f_pos+=count;
reval=count;
fail:
up(&dev->sem);
return count;
}
static ssize_t test_write(struct file *filp,char __user *buf,size_t count,loff_t *f_pos)
{
struct test_dev *dev=filp->private_data;
char *test_data=NULL;
int pos=0;
int reval=0;
if(down_interruptible(&dev->sem))
return -ERESTARTSYS;
pos=(long)*f_pos%test_size;
if(dev->data==NULL){
test_data=kmalloc(dev->size*sizeof(char),GFP_KERNEL);
dev->data=test_data;
}
if(!test_data){
reval=-ENOMEM;
goto fail;
}
if(pos+count>test_size)
count=test_size-pos;
if(copy_from_user(dev->data+pos,buf,count)){
reval=-EFAULT;
goto fail;
}
dev->size+=count;
*f_pos+=count;
reval=count;
fail:
up(&dev->sem);
return reval;
}
/////////////////////////////////////////
struct file_operations test_fops = {
.owner = THIS_MODULE,
.read = test_read,
.write = test_write,
.open = test_open,
.release = test_release,
};
//////////////////////////////////////////
static int test_init(void)
{
unsigned int result;
dev_t devno;
int i;
if(test_major){
devno=MKDEV(test_major,test_minor);
result=register_chrdev_region(devno,test_nr,"test");
}else{
result=alloc_chrdev_region(&devno,test_minor,test_nr,"test");
// test_major=MAJOR(devno);
}
if(result<0){
printk("test can't get major");
return 0;
}
test_device=kmalloc(test_nr*sizeof(struct test_dev),GFP_KERNEL);
if(!test_device) {
result=-ENOMEM;
goto fail;
}
memset(test_device,0,test_nr*sizeof(struct test_dev));
for(i=0;i<test_nr;i++){
devno=MKDEV(test_major,test_minor+i);
(test_device+i)->size=test_size;
init_MUTEX(&test_device[i].sem);
cdev_init(&test_device[i].cdev,&test_fops);
test_device[i].cdev.owner=THIS_MODULE;
test_device[i].cdev.ops=&test_fops;
if(cdev_add(&test_device[i].cdev,devno,1))
printk("error adding testdevice%d",i);
}
return 0;
fail:
return result;
}
static void test_cleanup(void)
{
dev_t devno=MKDEV(test_major,test_minor);
int i;
for(i=0;i<test_nr;i++){
cdev_del(&test_device[i].cdev);
}
kfree(test_device);
unregister_chrdev_region(devno,test_nr);
}
module_init(test_init);
module_exit(test_cleanup);
相关阅读 更多 +