主设备号--驱动模块与设备节点联系的纽带
一、如何对设备操作
linux中对设备进行操作是通过文件的方式进行的,包括open、read、write。
对于设备文件,一般称其为设备节点,
节点有一个属性是设备号(主设备号、次设备号),其中主设备号将设备文件与驱动模块对应起来
当我们open一个设备节点时,告诉了kernel要操作的是是主设备号为XX的节点,然后kernel会通过过XX来寻找合适的内存模块,进而调用内存模块中定义的open函数
由于操作节点之前kernel就需要有主设备号的信息,因此主设备号的申请、具有该主设备号的字符设备的添加都需要在驱动模块的初始化函数中执行
二、主设备号的申请
建议采用动态申请的主设备号的方式,linux中有很多设备,每一个设备对应着一个主设备号,动态申请是由内核分配一个没用的主
设备号,
动态申请函数为alloc_chrdev_region,相对应的释放函数为unregister_chrdev_region。
申请完后,可以从/proc/devices中读到分配的主设备号,后面建立设备节点时还需要用到
三、向kernle添加字符设备
上一步向内核申请了主设备号,就可以向kernel中添加字符设备了
kennel中一个字符设备对应了一个结构体cdev,这个结构体中定义了对字符设备的操作方式file_operations(包括open、read、write),这些操作方式也需要在驱动模块中事先定义好。
字符设备结构体cdev的添加步骤:
cdev初始化:cdev_init,该函数将file_operations与cdev对应起来
向kernel添加:cdev_add,该函数将主设备号与cdev结构体对应起来
当对open设备节点时,首先通过节点找到主设备号,然后再kernel中搜索与主设备号相对应的字符设备cdev,然后动过cdev中file_operations结构体定义的open方法(这个open是需要自己实现的)
四、3个重要的结构体
一个是file_operations,这里面主要包含了驱动的主要实现方法
一个是inode,这个是节点的信息,包含了主设备号和cdev结构体
一个是file,当节点首次被打开时,就会在内核中创建一个file结构体,file结构其充当了file_operations中方法的纽带,要不然read和wirte方法怎么知道操作的是那个设备的数据。
file中的自定义内容(驱动需要的数据)一般是在open中定义,然后read和write就可以操作自定义的数据了。
下面是一个简单的实例,可以看到驱动是怎样把自定义的open方法和主设备号对应起来的
#include <linux/module.h> /*它定义了模块的 API、类型和宏(MODULE_LICENSE、MODULE_AUTHOR等等),所有的内核模块都必须包含这个头文件。*/
#include <linux/init.h>
#include <linux/fs.h> //设备号相关函数
#include <linux/slab.h> //内存分配相关函数
#include <linux/types.h>
#include <linux/kdev_t.h>//设备号相关函数
#include <linux/cdev.h>//字符设备头文件
#include <linux/module.h>struct char_dev
{int size;char *data;struct cdev cdev;//内核中的字符设备
};int major = 0;
int minor = 0;
struct char_dev char_devices;int char_open(struct inode *inode, struct file *filep)
{int Major = 0;Major = MAJOR(inode->i_rdev);printk("open my_char_dev major: %d\n", Major);return 0;
}struct file_operations char_fops = {.owner = THIS_MODULE,.open = char_open,
};static void char_exit(void) //如果init函数中调用了该函数,则不应有 __exit
{dev_t dev;printk("char device driver exit \n");//释放设备号dev = MKDEV(major, minor);unregister_chrdev_region(dev, 1);printk("release major %d\n", major);//释放内存if(char_devices.data){kfree(char_devices.data);}//从内核中删除字符设备cdev_del(&(char_devices.cdev));
}static int __init char_init(void)//__init一个标记,表明是初始化函数
{//初始化的代码dev_t dev;int result; printk("char device driver init \n");//动态向内核申请设备号 result = alloc_chrdev_region(&dev, 0, 1, "my_char_dev");major = MAJOR(dev);minor = MINOR(dev);printk("alloc major %d\n", major);if (result < 0) {printk(KERN_WARNING "my_char_dev: can't get major %d\n", major);return result;}//为设备分配一块内存char_devices.size = 100;char_devices.data = (char*)kmalloc(char_devices.size, GFP_KERNEL);if (!char_devices.data) {result = -ENOMEM;goto fail; //不能直接退出函数,需要释放设备号}//向内核中添加字符设备cdevcdev_init(&(char_devices.cdev), &char_fops);char_devices.cdev.owner = THIS_MODULE;char_devices.cdev.ops = &char_fops;result = cdev_add(&(char_devices.cdev), dev, 1);if((result < 0)) {printk(KERN_WARNING "Error %d adding my_char_dev\n", result);goto fail;}return 0; //成功
fail:char_exit();return result;
}MODULE_LICENSE("Dual BSD/GPL");
//当模块被加载时,执行moudle_init函数,该函数会调用初始化函数
module_init(char_init);
//模块卸载时,调用,释放资源
module_exit(char_exit);
注:驱动insmod后,通过/proc/devices查看主设备号,然后通过mknod在/dev下创建设备节点,注意保持主设备好的一致,当前的节点只支持open方法,可以在demsg中进行验证。
主设备号--驱动模块与设备节点联系的纽带相关推荐
- [ARM-Linux开发] 主设备号--驱动模块与设备节点联系的纽带
一.如何对设备操作 linux中对设备进行操作是通过文件的方式进行的,包括open.read.write. 对于设备文件,一般称其为设备节点, 节点有一个属性是设备号(主设备号.次设备号),其中主设备 ...
- 一张图说明linux 设备 节点 驱动 主设备号 和次设备号之间的关系
Linux各种设备都以文件的形式存放在/dev目录下,称为设备文件. 应用程序可以打开.关闭和读写这些设备文件,完成对设备的操作,就像操作普通的数据文件一样.为了管理这些设备,系统为设备编了号,每个设 ...
- Linux嵌入式开发_主设备号与次设备号详解
前言 在Linux内核中设备号的作用是用来区分不同的设备类型. 比如: 设备号23,对应的是LED 设备号17,对应的是某个存储设备 等等... 主次设备号 主设备号:对应设备的主号码 次设备号:对应 ...
- linux中的 主设备号与次设备号
linux主设备号和次设备号 Linux的设备管理是和文件系统紧密结合的,各种设备都以文件的形式存放在/dev目录下,称为设备文件.应用程序可以打开.关闭和读写这些设备文件, 完成对设备的操作,就像操 ...
- 主设备号与次设备号以及申请
一个字符设备或者块设备都有一个主设备号和次设备号.主设备号和次设备号统称为设 备号.主设备号用来表示一个特定的驱动程序.次设备号用来表示使用该驱动程序的各 设备.例如一个嵌入式系统,有两个LED指示灯 ...
- 【001 设备驱动】主设备号和次设备号的用途
一.请简述主设备号和次设备号的用途 Linux 中每个设备都有一个设备号,设备号由主设备号和次设备号两部分组成,主设备号表示某一个具体的驱动,次设备号表示使用这个驱动的各个设备. Linux 提供了一 ...
- 主设备号与次设备号代码分析---MAJOR、MINOR
<linux/kdev.h>内容如下: #ifndef _LINUX_KDEV_T_H #define _LINUX_KDEV_T_H #ifdef __KERNEL__ #define ...
- Linux主设备号和次设备号
Linux主设备号用来区分不同硬件设备类型,如串口和USB之间的区别: Linux次设备号用来区分不同硬件设备,如串口1和串口2之间的区别: 可以通过命令ls -l /dev来查看系统的设备号: 现在 ...
- 新字符设备驱动实验(自动分配设备号、自动创建应用层设备节点、新字符设备注册到内核的结构体)
目录 自动分配和释放设备号 示例代码 新的字符设备注册到内核方法 字符设备结构体(前面的设备号也放进来) cdev_init结构体初始化函数 cdev_add 添加到linux内核 cdev_del内 ...
最新文章
- 一行CSS样式去除百度地图版权,去除百度地图右上角平移缩放控件的市县区文字
- MVP模式在Android中的应用(附UML高清大图,使用RecyclerView举例)
- vscode生成vue模板快捷键_VSCode写vue项目一键生成.vue模版,修改定义其他模板的方法...
- JAVA练习55-最小的k个数
- 智能制造数字化车间的实施策略(上)
- 2019年SpringBoot视频教程【全网免费】每周更新
- css3 文字竖排英文及数字竖排文字方向问题文字竖排字间距问题
- C-COT代码运行----Matlab2018a运行matconvnet深度卷积网络
- ubuntu20.04 安装ROS2和ROS1共存
- 关于 kubernetes网络(CNI规范)中Calico,NetworkPolicy(网络策略)方面的一些笔记
- apktool反编译问题
- python批处理文件编写_求大神用python写个批处理程序?
- 新闻发布系统——模糊查询分页与主题分页
- 时序预测 | MATLAB实现PSO-SVM粒子群优化支持向量机时间序列预测
- 股票移动平均线matlab,matlab – 计算移动平均线
- 10款最佳项目管理工具推荐,总有一款适合你
- button/input链接方式全攻略
- 小睿睿的伤害(树上启发式合并)
- python开源项目学习目录
- Abb通过OPC UA 和PLC进行通讯
热门文章
- php字数超出省略号,html文本控制显示字数超出用省略号的方法
- 简笔画花边边框超简单_简单花边边框简笔画图
- 使用python模拟登录
- 小程序苹果6 和 苹果X 手机兼容处理
- 微信小程序-获取不限制的小程序码(二)
- “科技猫”联合创始人古茜:懂科技的女生更性感
- 不如安卓?iPhone 12 的5G速度上演“滑铁卢”
- 《跨境电商 —— 阿里巴巴速卖通实操全攻略》一一1.2 账户的认证流程
- 电脑自带的录屏软件在哪?图文教学,教你如何快速录屏
- 华为手表GT3个个手机支持功能列表