23 mdev与驱动源码实现设备文件创建
2018-02-28 23:44
399 查看
mdev与驱动源码实现设备文件创建
前面设备驱动备加载后,都需要用命令”mknod”来创建出设备文件。其实内核里有接口在驱动源码里实现创建出设备文件。
busybox做的嵌入式文件系统里有提供”mdev”命令。
“mdev –help”命令可以查看相关信息:
mdev -s is to be run during boot to scan /sys and populate /dev. Bare mdev is a kernel hotplug helper. To activate it: echo /sbin/mdev >/proc/sys/kernel/hotplug It uses /etc/mdev.conf with lines [-][ENV=regex;]...DEVNAME UID:GID PERM [>|=PATH]|[!] [@|$|*PROG] ...
“mdev -s”是用于在系统启动时扫描”/sys”目录下的设备信息,在”/dev”目录下产生相应的设备文件。
所以在系统的启动脚本里”/etc/init.d/rcS”里加了”mdev -s”语句。
“echo /sbin/mdev > /proc/sys/kernel/hotplug”用于当系统的设备或设备驱动发生变化(热插拔事件)时,自动调用mdev程序来产生或移除相应的设备文件。
这语句同样的也加在系统启动脚本里加上了。
“/etc/mdev.conf”还可以用于指定什么设备文件产生后,自动执行什么脚本或程序。
如u盘接上后,设备文件为/dev/sda1,想执行脚本”/bin/mysh.sh”,则可以在mdev.conf里设置:”sda1 0:0 0600 =sda1 */bin/mysh.sh”
在内核源码里创建/移除设备,产生热插拔事件的函数有:
#include <linux/device.h> struct class *class_create(owner, name); //在"/sys/class/"目录下创建出名为name的子目录 void class_destroy(struct class *cls); //移除目录 struct device *device_create(struct class *class, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...); //在class目录下创建出设备信息和产生热插拔事件,mdev会根据设备信息创建出相应的设备文件 //class指定在哪个class目录下创建设备信息,parent指定父设备节点(可以为NULL) //devt为设备文件的设备号,drvdata用于设备驱动用的参数(可设为NULL) //"const char *fmt, ..."是用printf的方式来设置设备文件的文件名,如(..., "mydev%d", i):表示设备文件名由mydev与变量i的值组成。 void device_destroy(struct class *class, dev_t devt); //指定在class目录下移除指定设备号的设备信息,mdev就会移除相应的设备文件。
驱动源码实现设备文件创建步骤:
1.包含头文件: #include <linux/device.h> 2.定义全局结构体: struct class *mycls; 3.在"/sys/class/"目录下创建出名为name的子目录: mycls = class_create(THIS_MODULE, "myclass"); 4.在class目录下创建出设备信息和产生热插拔事件,mdev会根据设备信息创建出相应的设备文件: device_create(mycls, NULL, MKDEV(MYMA, MYMI), NULL, "mydev", NULL); 5.在myclass目录里移除设备信息: device_destroy(mycls, MKDEV(MYMA, MYMI)); 6.移除myclass目录: class_destroy(mycls);
一个设备驱支持多个设备文件的例子(test.c):
#include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/slab.h> #include <asm/uaccess.h> #include <linux/device.h> #define MYMA 1234 #define MYMI 5500 #define COUNT 3 //三个设备号,每个设备号对应一个设备文件和一个数据缓冲区 dev_t devid; struct cdev mycdev; u8 *data[COUNT]; //驱动数据缓冲区 int dlen = 1024; //驱动数据缓冲区长度 ssize_t myread(struct file *fl, char __user *buf, size_t len, loff_t *off) { int mi = MINOR(fl->f_path.dentry->d_inode->i_rdev); int len_copy, ret, n; n = mi - MYMI; if (n >= COUNT) return -ENODEV; if ((fl->f_pos + len) > strlen(data )) len_copy = strlen(data ) - fl->f_pos; else len_copy = len; ret = copy_to_user(buf, data +fl->f_pos, len_copy); *off += len_copy - ret; return len_copy - ret; } ssize_t mywrite(struct file *fl, const char __user *buf, size_t len, loff_t *off) { int mi = MINOR(fl->f_path.dentry->d_inode->i_rdev); int len_copy, ret, n; n = mi - MYMI; if (n >= COUNT) return -ENODEV; if ((fl->f_pos + len) > dlen) len_copy = dlen - fl->f_pos; else len_copy = len; ret = copy_from_user(data + fl->f_pos, buf, len_copy); *off += len_copy - ret; return len_copy - ret; } struct file_operations fops = { .owner = THIS_MODULE, .read = myread, .write = mywrite, }; struct class *mycls; static int __init test_init(void) { int ret, i, j; devid = MKDEV(MYMA, MYMI); ret = register_chrdev_region(devid, COUNT, "mydev"); if (ret < 0) goto err0; cdev_init(&mycdev, &fops); mycdev.owner = THIS_MODULE; ret = cdev_add(&mycdev, devid, COUNT); if (ret < 0) goto err1; for (i = 0; i < COUNT; i++) { data[i] = kzalloc(dlen, GFP_KERNEL); for (j = 0; j < 26; j++) data[i][j] = 'A' + j; } mycls = class_create(THIS_MODULE, "myclass"); //在/sys/clas/目录下会出现myclass子目录 for (i = 0; i < COUNT ; i++) device_create(mycls, NULL, MKDEV(MYMA, MYMI+i), NULL, "mydev%d", i); //会在myclass子目录里创建出"mydev0, mydev1, mydev2"设备信息 //mydev0/uevent的内容: //MAJOR=1234 //MINOR=5500 //DEVNAME=mydev0 return 0; err1: unregister_chrdev_region(devid, COUNT); err0: return ret; } static void __exit test_exit(void) { int i; unregister_chrdev_region(devid, COUNT); cdev_del(&mycdev); for (i = 0; i < COUNT; i++) { kfree(data[i]); device_destroy(mycls, MKDEV(MYMA, MYMI+i)); //在myclass目录里移除设备信息 } class_destroy(mycls); //移除myclass目录 } module_init(test_init); module_exit(test_exit); MODULE_LICENSE("GPL");
相关文章推荐
- 25 mdev与驱动源码里创建设备文件的实现
- 25 驱动设备申请及源码实现设备文件创建一体函数(miscdevice)
- 驱动如何实现对mdev的支持(自动创建一个设备)
- 嵌入式Linux系统中利用mdev自动创建设备文件节点
- linux驱动学习——怎么自动创建设备文件
- Linux内核驱动自动创建设备节点文件
- Linux 设备驱动--- 自动创建设备文件
- linux驱动学习——怎么自动创建设备文件
- Linux 设备文件的创建和mdev
- CodeIgniter框架源码笔记(13)——SESSION之文件File驱动实现
- Linux 设备驱动--- 自动创建设备文件
- linux 驱动程序 设备模块 设备号 设备文件创建 设备注册 字符驱动设备分析
- (三)NT驱动基础——创建驱动设备 并 实现驱动与应用程序的通信
- Linux内核驱动自动创建设备节点文件
- 国嵌内核驱动进阶班-7-5(自动创建设备文件)
- Linux 设备驱动 如何自动创建设备文件
- 简单字符设备驱动和自动创建设备文件
- Linux内核驱动之自动创建设备文件
- Linux字符设备驱动(三)-文件操作函数实现
- 设备驱动/dev/驱动文件的创建(写驱动时再详细看可能会比较清楚)