字符设备(2)面向设备对象

来源:互联网 发布:现在最火的网络自制剧 编辑:程序博客网 时间:2024/04/29 05:36
/*改进:从设备读写*//*对设备属性进行了封装,读写时重要的改变*/#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/cdev.h>#include <linux/fs.h>#include <asm/uaccess.h>#include <linux/errno.h>#include <linux/slab.h>#define P_DEBUG(fmt, args...) printk("<kernel>[%s]"fmt, __FUNCTION__, ##args)#define DEVSIZE 512//将设备属性封装成一个结构体,表示一个字符设备struct test_dev_t {char kbuf[DEVSIZE];int curr_size;int major;int minor;dev_t devno;struct cdev test_cdev;}*dev;/*static dev_t devno;static int major = 0;static int minor = 0;struct cdev test_cdev;*///设备驱动的操作方法static int test_open(struct inode *,struct file *);static int test_close(struct inode *,struct file *);static ssize_t test_read(struct file *, char __user *, size_t , loff_t *);static ssize_t test_write(struct file *, const char __user *, size_t, loff_t *);struct file_operations test_fops = {.open = test_open,.release = test_close,.read = test_read,.write = test_write,};//打开设备static int test_open(struct inode *inode,struct file *filp){P_DEBUG("dev open!\n");//***重要改变,打开设备时将设备属性结构体赋值给打开设备文件的似有数据struct test_dev_t *dev;//驱动程序获取设备的通用方法dev = container_of(inode->i_cdev,struct test_dev_t,test_cdev);filp->private_data = dev;//利用设备文件的私有数据结构,保存设备相关的数据结构return 0;}//释放设备static int test_close(struct inode *inode,struct file *filp){P_DEBUG("dev close!\n");return 0;}//从设备读取static ssize_t test_read(struct file *filp, char __user *buf, size_t count, loff_t *offset){int ret;//***重要改变,现在从设备读取struct test_dev_t *dev = filp->private_data; if (!dev->curr_size)//字符设备没有数据return 0;if (copy_to_user(buf,dev->kbuf,count)) {//安全性检查return -EFAULT;}else {ret = count;//修改设备文件当前偏移量dev->curr_size -= count;P_DEBUG("buf is [%s]\n", buf);}return ret; } //写入设备static ssize_t test_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset){int ret; //***重要改变,现在写到设备struct test_dev_t *dev = filp->private_data;P_DEBUG("dev->curr_size[%d]\n",dev->curr_size);if (copy_from_user(dev->kbuf,buf,count)) {return -EFAULT;}else {ret = count;//修改设备文件当前偏移量dev->curr_size += count;P_DEBUG("dev->curr_size[%d]\n",dev->curr_size); P_DEBUG("kbuf is [%s]\n", dev->kbuf); } return ret; }//初始化设备属性static struct test_dev_t* dev_init(struct test_dev_t *dev){dev = kmalloc(sizeof(struct test_dev_t), GFP_KERNEL);memset(dev->kbuf,0,DEVSIZE);dev->curr_size = 0;dev->major = 0;dev->minor = 0;return dev;}static int __init test_init(void){int ret;//很重要的部分,定义并初始化一个设备dev = dev_init(dev);//申请字符设备号if (dev->major) {dev->devno = MKDEV(dev->major,dev->minor);ret = register_chrdev_region(dev->devno,1,"test_dev");}else {//动态分配ret = alloc_chrdev_region(&dev->devno,dev->minor,1,"test_dev");dev->major = MAJOR(dev->devno);dev->minor = MINOR(dev->devno);}if (ret < 0) {P_DEBUG("register chrdev devno err!\n");goto err_regDevno;}printk("major[%d] minor[%d]\n",dev->major,dev->minor);//注册设备cdev_init(&dev->test_cdev,&test_fops);//初始化cdev结构体dev->test_cdev.owner = THIS_MODULE;ret = cdev_add(&dev->test_cdev,dev->devno,1);//将设备加到字符设备数据库if (ret < 0) {P_DEBUG("add cdev error!\n");goto err_addCdev;}return 0;err_addCdev:unregister_chrdev_region(dev->devno,1);err_regDevno:return ret;}static int __exit test_exit(void){cdev_del(&dev->test_cdev);//从字符设备数据库删除cdevunregister_chrdev_region(dev->devno,1);//释放设备号return 0;}module_init(test_init);module_exit(test_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("LL");MODULE_VERSION("1.2");


0 0
原创粉丝点击