linux驱动开发 字符设备驱动框架(自动创建设备节点)
Posted 陌鉎こ城sHi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux驱动开发 字符设备驱动框架(自动创建设备节点)相关的知识,希望对你有一定的参考价值。
代码如下
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/cdev.h> #include <linux/fs.h> #include <linux/device.h> int demo_major = 250; int demo_minor = 0; int demo_count = 1; struct cdev cdev; static struct class *demo_class; static struct device *demo_device; int demo_open(struct inode *inodep, struct file * filep) // 打开设备 { printk("%s,%d\\n", __func__, __LINE__); return 0; } int demo_release(struct inode * inodep, struct file * filep) // 关闭设备 { printk("%s,%d\\n", __func__, __LINE__); return 0; } struct file_operations fops = { .owner = THIS_MODULE, .open = demo_open, .release = demo_release, }; static int __init demo_init(void) { int ret = 0; dev_t devno; printk("%s,%d\\n", __func__, __LINE__); //使用下列宏则可以通过主设备号和次设备号生成 dev_t devno = MKDEV(demo_major, demo_minor); printk("devno:%d\\n", devno); printk("demo_major:%d\\n", demo_major); /**在调用 cdev_add()函数向系统注册字符设备之前, *应首先调用 register_chrdev_region()或alloc_chrdev_region()函数向系统申请设备号 **/ if (demo_major) {
//使用cat /proc/devices | grep demo 来查询 ret = register_chrdev_region(devno, 1, "demo"); } else { ret = alloc_chrdev_region(&devno, demo_minor, 1, "demo"); } if(ret) { printk("Failed to register_chrdev_region.\\n"); return ret; } //cdev_init()函数用于初始化 cdev 的成员,并建立 cdev 和 file_operations 之间的连接 cdev_init(&cdev, &fops); cdev.owner = THIS_MODULE; //系统添加一个 cdev,完成字符设备的注册。 ret = cdev_add(&cdev, devno, demo_count); if(ret) { printk(KERN_NOTICE " Failed to cdev_add [Error] %d adding demo%d", ret, demo_minor); goto failure_cdev_add; } /*自动创建设备节点文件*/ //1.注册设备类 /sys/class/demo的文件夹
//使用 ls /sys/class/demo demo_class = class_create(THIS_MODULE, "demo"); if( IS_ERR(demo_class)) { printk("class_create failed!\\n"); ret = PTR_ERR("demo_class"); goto failure_class_create; } //2.注册设备 /sys/class/demo/demo0 /dev/demo0 demo_device = device_create(demo_class, NULL, MKDEV(demo_major, demo_minor), NULL, "demo%d", demo_minor); if(IS_ERR(demo_device)){ printk("device_create failed!\\n"); ret = PTR_ERR("demo_device"); goto failure_device_create; } return 0; failure_device_create: class_destroy(demo_class); failure_class_create: cdev_del(&cdev); failure_cdev_add: unregister_chrdev_region(devno, demo_count); failure_register_chrdev: return ret; } static void __exit demo_exit(void) { printk("%s,%d\\n", __func__, __LINE__); /*逆序消除*/ //从内核中删除设备 device_destroy(demo_class,MKDEV(demo_major, demo_minor)); //从内核中删除设备类 class_destroy(demo_class); //删除一个 cdev,完成字符设备的注销。 cdev_del(&cdev); //在调用cdev_del()函数从系统注销字符设备之后,unregister_chrdev_region()应该被调用以释放原先申请的设备号 unregister_chrdev_region( MKDEV(demo_major, demo_minor), demo_count ); } module_init(demo_init); module_exit(demo_exit); MODULE_AUTHOR(" libra13179 "); MODULE_LICENSE("GPL v2");
KVERS = $(shell uname -r) # Kernel modules obj-m += demo.o # Specify flags for the module compilation. #EXTRA_CFLAGS=-g -O0 build: kernel_modules kernel_modules: make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules # @echo $(KVERS) clean: make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> int main(int argc, const char *argv[]) { int fd; int val = 1; fd = open("/dev/demo0", O_RDWR); if (fd < 0) { printf("can\'t open!\\n"); return -1; } else { printf("open success.\\n"); } getchar(); close(fd); return 0; }
主要使用到函数
class_create
device_create
device_destroy
class_destroy
小技巧:
类似
http://lxr.free-electrons.com/
http://lxr.oss.org.cn/
这样的网站提供了Linux内核源代码的交叉索引,
在其中输入Linux内核中的函数、数据结构或变量的名称就可以直接得到以超链接形式给出的定义和引用它的所有位置。
还有一些网站也提供了Linux内核中函数、变量和数据结构的搜索功能,
在google中搜索“linux identifier search”可得。
以上是关于linux驱动开发 字符设备驱动框架(自动创建设备节点)的主要内容,如果未能解决你的问题,请参考以下文章
Linux——Linux驱动之字符类设备驱动编写实践,从0到1手把手教你字符类设备如何申请设备号,如何注册设备,如何自动创建设备节点