首页 > 代码库 > 驱动笔记 - 字符设备范例

驱动笔记 - 字符设备范例

#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 = http://www.mamicode.com/dev;"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 = http://www.mamicode.com/kmalloc(mem_dev[i].size,GFP_KERNEL);"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);

  

驱动笔记 - 字符设备范例