码迷,mamicode.com
首页 > 其他好文 > 详细

驱动笔记 - 字符设备范例

时间:2014-11-19 23:37:39      阅读:200      评论:0      收藏:0      [点我收藏+]

标签:blog   io   ar   os   for   on   div   log   ad   

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/moduleparam.h>
#include <asm/uaccess.h>

struct mem_dev
{
	unsigned long size;
	char *data;
	struct cdev cdev;
};

static int major,minor;
module_param(major,int,S_IRUGO);

struct mem_dev mem_dev[2];

int mem_open(struct inode *inode, struct file *file)
{
	struct mem_dev *dev;
	dev = container_of(inode->i_cdev, struct mem_dev, cdev);
	file->private_data = dev;
	return 0;
}

ssize_t mem_read(struct file *file,char __user *buf,size_t size, loff_t *loff)
{
	loff_t lof = *loff;
	int ret;
	size_t sizet = size;
	struct mem_dev *p;
	if(lof > 4096)
		return 0;
	if(sizet > 4096 - lof)
		sizet = 4096 - lof;
	p = file->private_data;
	if(copy_to_user(buf,(void *)(p->data + lof),sizet))
	{
		ret = -EFAULT;
	}
	else
	{
		loff += sizet;
		ret = sizet;

		printk(KERN_CRIT "read %d byte(s) from mem_dev %d.\n",ret, lof);
	}
	return ret;
}

loff_t mem_llseek(struct file *file,loff_t loff,int whence)
{
	loff_t new;
	switch(whence)
	{
		case 0:
			new = loff;
			break;
		case 1:
			new = file->f_pos + loff;
			break;
		case 2:
			new = 4096-1 + loff;
			break;
		default:
			new = -EINVAL;
			break;
	}
	if(new >= 4096 ||new < 0)
	{
		return new; 
	}
	file->f_pos = new;
	return new;
}

ssize_t mem_write(struct file *file, const char __user *buf, size_t size,loff_t *loff)
{
	loff_t lof = *loff;
	int ret;
	size_t sizet = size;
	struct mem_dev *p;
	if(lof > 4096)
		return 0;
	if(sizet > 4096 - lof)
		sizet = 4096 - lof;
	p = file->private_data;
	if(copy_from_user((void *)(p->data + lof),buf,sizet))
	{
		ret = -EFAULT;
	}
	else
	{
		loff += sizet;
		ret = sizet;

		printk(KERN_CRIT "write %d byte(s) from mem_dev %d.\n",ret, lof);
	}
	return ret;
}

int mem_release(struct inode *inode,struct file *file)
{
	return 0;
}



struct file_operations fops = 
{
	.owner = THIS_MODULE,
	.open = mem_open,
	.read = mem_read,
	.write = mem_write,
	.llseek = mem_llseek,
	.release = mem_release,
};


static void setup_cdev(struct mem_dev *dev,int index)
{
	int err,devno = MKDEV(major,minor + index);
	cdev_init(&dev->cdev,&fops);
	dev->cdev.owner = THIS_MODULE;
	dev->cdev.ops = &fops;

	err = cdev_add(&(dev->cdev),devno,1);
	if(err)
		printk(KERN_NOTICE "Error %d adding cdev%d.\n",err, index);
}

	dev_t dev;
static int mem_init(void)
{
	int result,i;
	if(major)
	{
		dev = MKDEV(major,0);
		result = register_chrdev_region(dev,2,"memdev");
	}
	else
	{
		result = alloc_chrdev_region(&dev,0,2,"memdev");
		major = MAJOR(dev);
	}
	if(result < 0)
		return result;
	
	setup_cdev(&mem_dev[0],0);
	setup_cdev(&mem_dev[1],1);
	
	for(i = 0;i < 2;i++)
	{
		mem_dev[i].size = 4096;
		mem_dev[i].data = kmalloc(mem_dev[i].size,GFP_KERNEL);
		memset(mem_dev[i].data,0,mem_dev[i].size);
	}
	printk(KERN_ALERT "mem_dev setup success.");
	return 0;
}

static void mem_exit(void)
{
	cdev_del(&mem_dev[0].cdev);
	cdev_del(&mem_dev[1].cdev);
	unregister_chrdev_region(dev,2);
}

MODULE_LICENSE("GPL");
module_init(mem_init);
module_exit(mem_exit);

  

驱动笔记 - 字符设备范例

标签:blog   io   ar   os   for   on   div   log   ad   

原文地址:http://www.cnblogs.com/tolimit/p/4109394.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!