来自:http://blog.csdn.net/smilefyx/article/details/40402603
简述
本文简述在Linux字符设备驱动编程中自动创建设备节点。以下内容不在本文描述范围内:
1、设备号、驱动等概念性问题;
相关内容请看:http://blog.csdn.net/zjjyliuweijie/article/details/7001383
2、设备号的自动分配和手动指定;
相关内容请看:http://blog.csdn.net/zhuky/article/details/5193675
3、mknode手动创建节点。
相关内容请自行搜索mknode等相关知识。
编码实现
1、核心点
要使的驱动能够在加载时自动完成设备节点的注册,主要流程如下:
驱动加载时完成如下工作:分配设备号-------------注册字符设备------------动态创建设备节点。
驱动卸载时完成如下工作:删除设备节点-------------取消字符设备的注册-----------删除设备号。
2、例子
如下驱动简要介绍一个自动创建设备节点的驱动实例,编译驱动后加载该驱动,将在/dev目录下面生成driver_wrbuff的文件节点(宏DEVICE_NAME指定的名字)。
writebuffer.c
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/fs.h>
- #include <linux/init.h>
- #include <linux/delay.h>
- #include <asm/uaccess.h>
- #include <asm/irq.h>
- #include <asm/io.h>
- #include <mach/gpio.h>
- #include <mach/hardware.h>
- #include <linux/device.h>
- #include <linux/cdev.h>
-
- #define CHRDEV_NAME "driver_wrbuff"
- #define CLASS_NAME "class_wrbuff" //表示在/system/class目录下创建的设备类别目录
- #define DEVICE_NAME "driver_wrbuff" //<span><span class="comment">在/dev/目录和/sys/class/class_wrbuff目录下分别创建设备文件driver_wrbuff</span><span></span></span>
-
- static dev_t devt_wrbuffer;
- static struct cdev* cdev_wrbuffer;
- static struct class* class_wrbuffer;
-
-
- static int wrbuffer_open(struct inode *inode,struct file *file);
- static ssize_t wrbuffer_read(struct file *file, char __user *buf, size_t count, loff_t *offset);
- static ssize_t wrbuffer_write(struct file *file, const char __user *buf, size_t count, loff_t *offset);
-
-
- static struct file_operations fops_wrbuffer = {
- .owner = THIS_MODULE,
- .open = wrbuffer_open,
- .read = wrbuffer_read,
- .write = wrbuffer_write,
- };
-
- static int wrbuffer_open(struct inode *inode,struct file *file) {
- printk("open write and buffer device!");
- return 0;
- }
-
-
- static ssize_t wrbuffer_read(struct file *file, char __user *buf, size_t count, loff_t *offset) {
- printk("write buffer device!");
- return 0;
- }
-
- static ssize_t wrbuffer_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) {
- printk("read buffer device!");
- return 0;
- }
-
-
- static int __init wrbuffer_init(void) {
- int ret;
-
-
- ret = alloc_chrdev_region(&devt_wrbuffer,0,1,CHRDEV_NAME);
- if(ret) {
- printk("alloc char driver error!\n");
- return ret;
- }
-
-
- cdev_wrbuffer = cdev_alloc();
- cdev_init(cdev_wrbuffer,&fops_wrbuffer);
- cdev_wrbuffer->owner = THIS_MODULE;
- ret = cdev_add(cdev_wrbuffer,devt_wrbuffer,1);
- if(ret) {
- printk("cdev create error!\n");
- unregister_chrdev_region(devt_wrbuffer,1);
- return ret;
- }
-
-
- class_wrbuffer = class_create(THIS_MODULE,CLASS_NAME);
- device_create(class_wrbuffer,NULL,devt_wrbuffer,NULL,DEVICE_NAME);
-
- printk("wrbuffer driver init is ok!\n");
-
- return 0;
- }
-
- static void __exit wrbuffer_exit(void) {
-
- device_destroy(class_wrbuffer,devt_wrbuffer);
- class_destroy(class_wrbuffer);
-
-
- cdev_del(cdev_wrbuffer);
-
-
- unregister_chrdev_region(devt_wrbuffer,1);
- }
-
-
- late_initcall(wrbuffer_init);
- module_exit(wrbuffer_exit);
-
- MODULE_AUTHOR("yxtouch520@yeah.net");
- MODULE_DESCRIPTION("allwinner buffer read and write test driver");
- MODULE_LICENSE("GPL");
3、Makefile
使用如下Makefile文件进行驱动模块的编译,请按照自己需要配置内核路径。
- obj-m := sun7i_wrbuffer.o
- sun7i_wrbuffer-objs := writebuffer.o
- KERNELDIR := /home/feiyinxian/workspace/A20/landsem/A20_Android4.4/lichee/linux-3.4
- PWD := $(shell pwd)
-
- modules:
- $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
- .PHONY:clean
- clean:
- rm *.ko *.o
修改内核路径后输入make即可编译生成驱动模块,拷贝编译生成的模块到目标板,使用insmod加载模块,查看/dev/目录下面是否成功创建设备节点。