静态申请字符类设备号
来源:互联网 发布:凤凰卫视的立场 知乎 编辑:程序博客网 时间:2024/06/05 11:32
1.设备号
主设备号:用来标识与设备文件相关的驱动程序, ——反应设备类型
次设备号:为内核所用,被驱动程序用来辨别操作那个设备文件 ——区分同类型的具体某个设备
1.1 设备号的内部表达
在内核中,保存设备号(包括主设备号和此设备好)使用类型
dev_t (<linux/types.h>)
这是一个unsigned int 是一个32位的无符号整型。。
主设备号——高12位
次设备号——低20位
我们可以使用宏来取一个设备号(dev)的主设备号和此设备号
定义在 <linux/kdev_t.h> MAJOR(dev_t dev) 取主设备号 MINOR(dev_t dev) 取次设备号 也可以将主次设备号合成一个完整的dev_t类型的设备号 MKDEV(int major, int minor) 将主次设备号转换成dev_t
1.2 分配主次设备号
linux可以采用静态申请和动态申请两种方法来分配主次设备号
静态申请
1. 根据Documentation/devices.txt, 确定一个没有使用的主设备号 2. 使用register_chrdev_region(dev_t first, unsigned int count, char *name) 定义在<linux/fs.h> count 为所请求的连续设备编号个数, 如果count过大,可以会各下一个主设备号重叠。 name 为设备名, 注册后 出现在/proc/devices和sysfs中
动态分配
作为一个新的驱动程序,应该使用动态分配机制获取主设备号 alloc_chrdev_region(dev_t *dev, unsigned int first, unsigned int count, char *name) 不管用何种方法分配, 不用时都要释放掉 void unregister_chrdev_region(dev_t first, unsigned int count);
静态申请与动态申请的优缺点:
静态申请——简单(优); 一旦驱动程序被广泛命使用, 随机选定的主设备号可以造成冲突,使驱动程序无法注册。(劣)
动态申请——简单,易于驱动推广(优);无法在驱动安装前创建设备文件, 因为不能保证分配的主设备号始终一致。(劣)
2.例程
#include <linux/init.h>/*包含初始化宏定义的头文件,代码中的module_init和module_exit在此文件中*/#include <linux/module.h>/*包含初始化加载模块的头文件,代码中的MODULE_LICENSE在此头文件中*//*定义module_param module_param_array的头文件*/#include <linux/moduleparam.h>/*定义module_param module_param_array中perm的头文件*/#include <linux/stat.h>/*三个字符设备函数*/#include <linux/fs.h>/*MKDEV转换设备号数据类型的宏定义*/#include <linux/kdev_t.h>/*定义字符设备的结构体*/#include <linux/cdev.h>#define DEVICE_NAME "sscdev"#define DEVICE_MINOR_NUM 2#define DEV_MAJOR 0#define DEV_MINOR 0MODULE_LICENSE("Dual BSD/GPL");/*声明是开源的,没有内核版本限制*/MODULE_AUTHOR("iTOPEET_dz");/*声明作者*/int numdev_major = DEV_MAJOR;int numdev_minor = DEV_MINOR;/*输入主设备号*/module_param(numdev_major,int,S_IRUSR);/*输入次设备号*/module_param(numdev_minor,int,S_IRUSR);static int scdev_init(void){ int ret = 0; dev_t num_dev; printk(KERN_EMERG "numdev_major is %d!\n",numdev_major); printk(KERN_EMERG "numdev_minor is %d!\n",numdev_minor); if(numdev_major){ num_dev = MKDEV(numdev_major,numdev_minor); ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME); } else{ printk(KERN_EMERG "numdev_major %d is failed!\n",numdev_major); } if(ret<0){ printk(KERN_EMERG "register_chrdev_region req %d is failed!\n",numdev_major); } printk(KERN_EMERG "scdev_init!\n"); /*打印信息,KERN_EMERG表示紧急信息*/ return 0;}static void scdev_exit(void){ printk(KERN_EMERG "scdev_exit!\n"); unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);}module_init(scdev_init);/*初始化函数*/module_exit(scdev_exit);/*卸载函数*/
和上面程序一样
#include <linux/module.h>//与module相关的信息#include <linux/kernel.h> //内核头文件#include <linux/init.h> //与init相关的函数/***********加载驱动传参数头文件**************/#include <linux/moduleparam.h>#include <linux/stat.h>//申明是开源的没有版本限制//linux的设备注册函数头文件#include <linux/fs.h>//字符设备结构体描述函数 包含dev_t 为32位的数据,其中高12位为主设备号,低20位为次设备号dev_t dev;#include <linux/cdev.h>//包含主次设备号的处理函数//MAJOR(dev) MINOR(dev) MKDEV(ma,mi)#include <linux/kdev_t.h>//申请许可证MODULE_LICENSE("Dul BSD/GPL");//作者MODULE_AUTHOR("zhangsan");#define DEV_NAME "sreq_dev" #define DEV_NUM 2#define MAJOR_VALUE 0 #define MANOR_VALUE 0/***********用到的函数说明*****************module_param(name, type, perm); //传递参数函数extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); //动态注册字符类设备函数extern int register_chrdev_region(dev_t, unsigned, const char *);extern void unregister_chrdev_region(dev_t, unsigned);//卸载字符设备*****************************/int major_dev_value=MAJOR_VALUE; // 主设备号默认值int minor_dev_value=MANOR_VALUE; //次设备号的默认值//模块传递参数module_param(major_dev_value, int, S_IRUSR);// 对任意的操作着,均可读可写module_param(minor_dev_value, int, S_IRUSR);//传入主设备号static int hellodriver_init(){ int ret=0; dev_t sreq_dev; //设备结构体 printk(KERN_INFO "parm 1 is %d\n",major_dev_value); //传递的第一个参数 printk(KERN_INFO "parm 2 is %d\n",minor_dev_value); //传递的第二个参数 if(major_dev_value)//如果传递参数不为0,则注册设备 { ret=register_chrdev_region(MKDEV(major_dev_value,minor_dev_value),DEV_NUM, DEV_NAME); } else { //否则动态注册字符设备 ret=alloc_chrdev_region(&sreq_dev,0,DEV_NUM,DEV_NAME); major_dev_value=MAJOR(sreq_dev);//获取主设备号 printk(KERN_INFO "major_dev_value is %d!\n",major_dev_value); } if(ret<0) { printk(KERN_INFO "registe driver failed!\n"); } printk(KERN_INFO "Hello_init\n"); return 0;}static void hellodriver_exit(){ unregister_chrdev_region(MKDEV(major_dev_value,minor_dev_value), DEV_NUM); printk(KERN_INFO "Hello_exit\n");}module_init(hellodriver_init);module_exit(hellodriver_exit);
阅读全文
0 0
- 静态申请字符类设备号
- (七) 字符设备号申请
- 讯为Exynos4412开发板例程及注释——动/静态申请字符类设备号代码及注释
- 设备号的静态申请与动态分配
- 设备号的静态申请与动态分配
- 设备号的静态申请与动态分配
- 《Linux驱动》动态申请字符设备号
- 字符设备号申请与注册
- 字符设备驱动——申请设备号、注册字符设备
- linux驱动开发--字符设备:静态分配设备号
- 设备驱动学习之字符设备驱动内核代码分析(一)——设备号申请接口
- (三)1字符型设备之设备申请
- udev动态申请设备号
- 1. 设备号的申请
- 申请设备号时的“设备名” 与自动创建设备文件时的“设备类名”和“设备文件名”
- linux设备驱动归纳总结(三):1字符型设备之设备申请
- linux设备驱动归纳总结:字符型设备之设备申请
- linux设备驱动归纳总结(三):1字符型设备之设备申请
- 赣南脐橙为什么那么“红”?
- Lombok-很强大的POJO注解器
- 2015携程笔试题
- reactNative中View组件的简单使用(六)
- 似然函数(likelihood)、最大似然函数、最小二乘解
- 静态申请字符类设备号
- hbbtv log control int mtk platform
- 软件测试之配置测试
- HashMap、 HashTable 、Collections.synchronizedMap、 ConcurrentHashMap
- java发展概述
- thinking in java——内部类
- Java 详解 JVM 工作原理和流程
- Antlr学习笔记
- 诗歌七 千字文(天地玄黄,宇宙洪荒)