实现4K大小的临时存储空间的字符设备驱动

这篇文章介绍如何实现一个简单的linux字符设备驱动,在这里实现的字符设备驱动包括mydev_temp.h文件和mydev_temp.c文件,其中mydev_temp.h文件内容如下:

#ifndef _MYDEV_TEMP_H_
#define _MYDEV_TEMP_H_

#ifndef MEMDEV_MAJOR
#define MEMDEV_MAJOR 250
#endif

#ifndef MEMDEV_NR_DEVS
#define MEMDEV_NR_DEVS 2
#endif

#ifndef MEMDEV_SIZE
#define MEMDEV_SIZE 4096
#endif

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

#endif
这个头文件主要定义了字符设备驱动的主设备号,字符设备个数以及每个字符设备的大小,并且定义了字符设备结构体。而mydev_temp.c文件内如如下:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/slab.h>

#include <linux/uaccess.h>
#include "mydev_temp.h"
#ifdef CONFIG_MODVERSIONS
#define MODVERSIONS
#include <linux/version.h>
#endif

static int mem_major = MEMDEV_MAJOR;
module_param(mem_major, int, S_IRUGO);
struct mem_dev *mem_devp;
struct cdev cdev;

static int mydev_temp_open(struct inode *inode, struct file *filp);
static int mydev_temp_release(struct inode *inode, struct file* filp);
static loff_t mydev_temp_llseek(struct file *filp, loff_t offset,int whence);
static ssize_t mydev_temp_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos);
static ssize_t mydev_temp_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos);

static const struct file_operations mydev_temp_fops = {
	.owner = THIS_MODULE,
	.llseek = mydev_temp_llseek,
	.read = mydev_temp_read,
	.write = mydev_temp_write,
	.open = mydev_temp_open,
	.release = mydev_temp_release, 
};

static int mydev_temp_open(struct inode *inode, struct file *filp)
{	
	struct mem_dev *dev;
	int num = MINOR(inode->i_rdev);
	if(num >= MEMDEV_NR_DEVS)
		return -ENODEV;
	
	dev = &mem_devp[num];
	filp->private_data = dev;
	return 0;
}

static ssize_t mydev_temp_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
	unsigned long p = *ppos;
	unsigned int count = size;
	int ret = 0;
	struct mem_dev *dev = filp->private_data;
	printk("p=%lu\n",p);
	if(p >= MEMDEV_SIZE)
		return 0;
	if(count > MEMDEV_SIZE-p)
		count = MEMDEV_SIZE-p;
	if(copy_to_user(buf,(void *)(dev->data+p),count)){
		ret = -EFAULT;
	}else{
		*ppos += count;
		ret = count;
		printk(KERN_INFO "read %u byte(s) from %lu\n",count,p);
	}
	return ret;
}

static ssize_t mydev_temp_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
	unsigned long p = *ppos;
	unsigned int count = size;
	int ret = 0;
	struct mem_dev *dev= filp->private_data;
	printk("p=%lu\n",p);
	if(p >= MEMDEV_SIZE)
		return 0;
	if(count > MEMDEV_SIZE-p)
		count = MEMDEV_SIZE-p;
	if(copy_from_user(dev->data+p,buf,count)){
		return -EFAULT;
	}else{
		*ppos += count;
		ret = count;
		printk(KERN_INFO"written %u byte(s) from %lu\n",count,p);
	}
	return ret;
}

static loff_t mydev_temp_llseek(struct file *filp, loff_t offset,int whence)
{
	loff_t newpos;
	switch(whence){
		case 0: /*SEEK_SET*/
			newpos = offset;
			break;
		case 1: /*SEEK_CUR*/
			newpos = filp->f_pos + offset;
			break;
		case 2: /*SEEK_END*/
			newpos = MEMDEV_SIZE+offset;
			break;
		default:
			return -EINVAL;
	}
	if(newpos < 0 || newpos>MEMDEV_SIZE)
		return -EINVAL;
	filp->f_pos = newpos;
	printk("filp->f_pos=%llu\n",filp->f_pos);
	return newpos;
}

static int mydev_temp_release(struct inode *inode, struct file* filp)
{
	printk("The device is released!\n");
	return 0;
}

static int __init mydev_temp_init(void)
{
	int result;
	int i;
	dev_t devno = MKDEV(mem_major,0);
	if(mem_major){
		result = register_chrdev_region(devno,2,"mydev_temp");
	}else{
		result = alloc_chrdev_region(&devno,0,2,"mydev_temp");
		mem_major = MAJOR(devno);
	}
	if(result < 0)
		return result;
	
	cdev_init(&cdev,&mydev_temp_fops);
	cdev.owner = THIS_MODULE;
	cdev.ops = &mydev_temp_fops;
	
	cdev_add(&cdev,MKDEV(mem_major,0),MEMDEV_NR_DEVS);
	mem_devp = kmalloc(MEMDEV_NR_DEVS*sizeof(struct mem_dev),GFP_KERNEL);
	if(!mem_devp){
		result = -ENOMEM;
		unregister_chrdev_region(devno, 1);
		return result;
	}
	memset(mem_devp,0,sizeof(struct mem_dev));
	
	for(i=0;i<MEMDEV_NR_DEVS;++i){
		mem_devp[i].size = MEMDEV_SIZE;
		mem_devp[i].data = kmalloc(MEMDEV_SIZE,GFP_KERNEL);
		memset(mem_devp[i].data,0,MEMDEV_SIZE);
	}
	return 0;
}

static void __exit mydev_temp_exit(void)
{
	printk(KERN_ALERT "Unloading...\n");
	cdev_del(&cdev);
	kfree(mem_devp);
	unregister_chrdev_region(MKDEV(mem_major,0), 2);;
	printk("unregister success!\n");
}

MODULE_AUTHOR("Fang Xieyun");
MODULE_LICENSE("GPL");

module_init(mydev_temp_init);
module_exit(mydev_temp_exit);



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值