代码:编写一个简单的字符设备驱动(自动创建设备文件)
来源:互联网 发布:淘宝上怎么买qq号 编辑:程序博客网 时间:2024/05/19 16:22
说明:
(1)该篇在上篇的基础上实现了自动创建设备文件的功能;
(2)自动创建文件主要用到了class_create()、device_create()两个函数,声明在inclue/linux/device.h里;
(3)设备文件的创建和销毁放在模块加载和卸载函数中;
#include <linux/module.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/cdev.h>#include <linux/slab.h>#include <linux/uaccess.h>#include <linux/device.h>#define MAX_SIZE 0x1000#define MEM_CLEAR 0x1static struct class *class;static struct device *dev;struct virtdev_dev{ struct cdev cdev; unsigned char mem[MAX_SIZE];};struct virtdev_dev *devp;dev_t devno;static int virtdev_open(struct inode *inode, struct file *filp){ filp->private_data = devp; return 0;}static int virtdev_release(struct inode *inode, struct file *filp){ return 0;}static long virtdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){ struct virtdev_dev *dev = filp->private_data; switch (cmd) { case MEM_CLEAR: memset(dev->mem, 0, MAX_SIZE); printk(KERN_INFO "virtdev is set to zero\n"); break; default: return -EINVAL; } return 0;}static ssize_t virtdev_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 virtdev_dev *dev = filp->private_data; if (p >= MAX_SIZE) return -EINVAL; if (count > MAX_SIZE - p) count = MAX_SIZE - p; if (copy_to_user(buf, dev->mem + p, count)) ret = -EINVAL; else { *ppos += count; ret = count; printk(KERN_INFO "read %u byte(s) from %lu\n", count, p); } return ret;}static ssize_t virtdev_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 virtdev_dev *dev = filp->private_data; if (p >= MAX_SIZE) return -EINVAL; if (count > MAX_SIZE - p) count = MAX_SIZE - p; if (copy_from_user(dev->mem + p, buf, count)) ret = -EINVAL; else { *ppos += count; ret = count; printk(KERN_INFO "write %u byte(s) from %lu\n", count, p); } return ret;}static loff_t virtdev_llseek(struct file *filp, loff_t offset, int orig){ loff_t ret = 0; switch (orig) { case 0: if (offset < 0) { ret = -EINVAL; break; } if (offset > MAX_SIZE) { ret = -EINVAL; break; } filp->f_pos = offset; ret = filp->f_pos; break; case 1: if ((filp->f_pos + offset) < 0 ) { ret = -EINVAL; break; } if ((filp->f_pos + offset) > MAX_SIZE) { ret = -EINVAL; break; } filp->f_pos += offset; ret = filp->f_pos; break; default: ret = -EINVAL; break; } return ret;}static const struct file_operations virtdev_fops ={ .owner = THIS_MODULE, .llseek = virtdev_llseek, .read = virtdev_read, .write = virtdev_write, .unlocked_ioctl = virtdev_ioctl, .open = virtdev_open, .release = virtdev_release,};static char *chardev_devnode(struct device *dev, umode_t *mode){ if (mode) *mode = 0666; return NULL;}static int __init virtdev_init(void){ int ret; int err; ret = alloc_chrdev_region(&devno, 0, 1, "virtdev"); if (ret < 0) return ret; devp = kzalloc(sizeof(struct virtdev_dev), GFP_KERNEL); if (!devp) { ret = -ENOMEM; goto fail_malloc; } class = class_create(NULL, "virtdev"); if (IS_ERR(class)) { ret = PTR_ERR(class); printk(KERN_ERR "class create error %d\n", ret); goto fail_malloc; } class->devnode = chardev_devnode; dev = device_create(class, NULL, devno, NULL, "virtdev"); if (IS_ERR(class)) { ret = PTR_ERR(dev); printk(KERN_ERR "device create error %d\n", ret); goto bad_device_create; } cdev_init(&devp->cdev, &virtdev_fops); devp->cdev.owner = THIS_MODULE; err = cdev_add(&devp->cdev, devno, 1); if (err) printk(KERN_NOTICE "Error %d adding virtdev", err); return 0; bad_device_create: class_destroy(class);fail_malloc: unregister_chrdev_region(devno, 1); return ret;}static void __exit virtdev_exit(void){ device_destroy(class, devno); class_destroy(class); cdev_del(&devp->cdev); kfree(devp); unregister_chrdev_region(devno, 1);}module_init(virtdev_init);module_exit(virtdev_exit);MODULE_AUTHOR("lql");MODULE_LICENSE("GPL");
相关Makefile文件:
obj-m := test.oKDIR := /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)all:make -C $(KDIR) M=$(PWD) modulesclean:rm -rf *.o *.ko *.mod.o *.mod.c *.symvers *.order
运行结果如下:
allen-lql dev # echo "hello everyone!" > virtdev allen-lql dev # cat virtdev hello everyone!
0 0
- 代码:编写一个简单的字符设备驱动(自动创建设备文件)
- 代码:编写一个简单的字符设备驱动——创建多个同类型设备
- 代码:编写一个简单的字符设备驱动
- 简单字符设备驱动和自动创建设备文件
- 简单字符设备驱动和自动创建设备文件
- 字符设备驱动高级篇3——自动创建字符设备驱动的设备文件
- 字符设备驱动高级篇4——设备类(自动创建和删除设备文件的作用)相关代码分析
- 学习笔记:创建一个简单字符设备驱动的过程
- 高级字符设备驱动-自动创建设备文件笔记
- 简单字符设备驱动的编写
- 编写简单字符设备驱动
- linux字符设备驱动之设备节点的自动创建
- 简单的一个字符设备驱动
- 一个简单的字符设备驱动
- 一个简单的字符设备驱动
- 创建一个字符设备驱动
- Linux 设备驱动--- 自动创建设备文件
- Linux 设备驱动--- 自动创建设备文件
- Python - 编码转换
- MFC Doc/View结构实现ActiveX控件
- 2016春季练习——水题
- mysql checksum table golang
- java常用容器总结
- 代码:编写一个简单的字符设备驱动(自动创建设备文件)
- 按之字形顺序打印二叉树
- Android TouchEvent事件传递机制
- BSP-Apache HAMA-Graph运行(2)
- Selenium Grid.
- html5 网页全屏显示
- Multisim12.0 安装、破解教程详细图解____本人备注
- C语言字符串反转函数
- Unity RectTransform