linux 块设备驱动 (三)块设备驱动开发
一: 块设备驱动注册与注销
块设备驱动中的第1个工作通常是注册它们自己到内核,完成这个任务的函数是 register_blkdev(),其原型为:
int register_blkdev(unsigned int major, const char *name);
与register_blkdev()对应的注销函数是unregister_blkdev(),其原型为:
int unregister_blkdev(unsigned int major, const char *name);
这里,传递给register_blkdev()的参数必须与传递给register_blkdev()的参数匹配,否则这个函数返回-EINVAL。
二: 块设备的请求队列操作
标准的请求处理程序能排序请求,并合并相邻的请求,如果一个块设备希望使用标准的请求处理程序,那它必须调用函数blk_init_queue来初始化请求队列。当处理在队列上的请求时,必须持有队列自旋锁。初始化请求队列
request_queue_t *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock);
该函数的第1个参数是请求处理函数的指针,第2个参数是控制访问队列权限的自旋锁,这个函数会发生内存分配的行为,故它可能会失败,函数调用成
功时,它返回指向初始化请求队列的指针,否则,返回NULL。这个函数一般在块设备驱动的模块加载函数中调用。清除请求队列
void blk_cleanup_queue(request_queue_t * q);
这个函数完成将请求队列返回给系统的任务,一般在块设备驱动模块卸载函数中调用。
提取请求
struct request *elv_next_request(request_queue_t *queue);
上述函数用于返回下一个要处理的请求(由 I/O 调度器决定),如果没有请求则返回NULL。
去除请求
void blkdev_dequeue_request(struct request *req);
上述函数从队列中去除1个请求。如果驱动中同时从同一个队列中操作了多个请求,它必须以这样的方式将它们从队列中去除。
分配“请求队列”
request_queue_t *blk_alloc_queue(int gfp_mask);
对于FLASH、RAM盘等完全随机访问的非机械设备,并不需要进行复杂的I/O调度,这个时候,应该使用上述函数分配1个“请求队列”,并使用如下函数来绑定“请求队列”和“制造请求”函数。
void blk_queue_make_request(request_queue_t * q,
make_request_fn * mfn);
void blk_queue_hardsect_size(request_queue_t *queue,
unsigned short max);
该函数用于告知内核块设备硬件扇区的大小,所有由内核产生的请求都是这个大小的倍数并且被正确对界。但是,内核块设备层和驱动之间的通信还是以512字节扇区为单位进行。
步骤:
在块设备驱动的模块加载函数中通常需要完成如下工作:
① 分配、初始化请求队列,绑定请求队列和请求函数。
② 分配、初始化gendisk,给gendisk的major、fops、queue等成
员赋值,最后添加gendisk。
③ 注册块设备驱动。
在块设备驱动的模块卸载函数中通常需要与模块加载函数相反的工作:
① 清除请求队列。
② 删除gendisk和对gendisk的引用。
③ 删除对块设备的引用,注销块设备驱动。
总结:
块设备的I/O操作方式与字符设备存在较大的不同,因而引入了
request_queue、request、bio等一系列数据结构。在整个块设备的I/O操作中,贯穿于始终的就是“请求”,字符设备的I/O操作则是直接进行不绕弯,
块设备的I/O操作会排队和整合。
驱动的任务是处理请求,对请求的排队和整合由I/O调度算法解决,因此,块设备驱动的核心就是请求处理函数或“制造请求”函数。
尽管在块设备驱动中仍然存在block_device_operations结构体及其成员函数,但其不再包含读写一类的成员函数,而只是包含打开、释放及I/O控制等
与具体读写无关的函数。块设备驱动的结构相当复杂的,但幸运的是,块设备不像字符设备那么包罗万象,它通常就是存储设备,而且驱动的主体已经
由Linux内核提供,针对一个特定的硬件系统,驱动工程师所涉及到的工作往往只是编写少量的与硬件直接交互的代码。
linux 块设备驱动 (三)块设备驱动开发的更多相关文章
- raid10 五块硬盘/raid5(三块使用,两块备份)
raid 10五块硬盘 第一步:在虚拟机中在添加五块硬盘 第二步:使用mdadm命令创建RAID10,名称为“/dev/md0/” -C代表创建操作,-v显示创建过程,-a yes检查RAID名称,- ...
- RAID5的创建(5块磁盘,三块做raid,两块做备份)
RAID5的创建(5块磁盘,三块做raid,两块做备份) 第一步:参考我的上一篇博客,用同样的方法添加5块硬盘.地址如下: https://www.cnblogs.com/Feng-L/p/11735 ...
- Raid5(五块磁盘,三块做raid,两块做备份)
1.在虚拟中再添加五块磁盘. 2.使用mdadm命令创建raid5,名称为“/dev/md5”. -C代表创建操作,-v显示创建过程,-a yes检查RAID名称,-n是用到的硬盘个数,-l是定义R ...
- Linux设备驱动--块设备(三)之程序设计
块设备驱动注册与注销 块设备驱动中的第1个工作通常是注册它们自己到内核,完成这个任务的函数是 register_blkdev(),其原型为:int register_blkdev(unsigned i ...
- Linux设备驱动--块设备(三)之程序设计(转)
http://blog.csdn.net/jianchi88/article/details/7212701 块设备驱动注册与注销 块设备驱动中的第1个工作通常是注册它们自己到内核,完成这个任务的函数 ...
- Linux块设备IO子系统(一) _驱动模型
块设备是Linux三大设备之一,其驱动模型主要针对磁盘,Flash等存储类设备,块设备(blockdevice)是一种具有一定结构的随机存取设备,对这种设备的读写是按块(所以叫块设备)进行的,他使用缓 ...
- 乾坤合一~Linux设备驱动之块设备驱动
1. 题外话 在蜕变成蝶的一系列学习当中,我们已经掌握了大部分Linux驱动的知识,在乾坤合一的分享当中,以综合实例为主要讲解,在一个月的蜕茧成蝶的学习探索当中,觉得数据结构,指针,链表等等占据了代码 ...
- FLASH驱动之-块设备驱动系统构架
一. 块设备是只能以块为单位进行访问的设备,块的大小一般是512个字节的整数倍,常见的块设备包括硬件,SD卡,光盘,flash等.驱动程序是块的整数倍从设备读写得到数据.块设备的最小访单位为块,不同 ...
- 深入浅出:Linux设备驱动之字符设备驱
一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流 ...
- 【转】深入浅出:Linux设备驱动之字符设备驱动
深入浅出:Linux设备驱动之字符设备驱动 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据 ...
随机推荐
- Spark2.1.0之源码分析——事件总线
阅读提示:阅读本文前,最好先阅读<Spark2.1.0之源码分析——事件总线>.<Spark2.1.0事件总线分析——ListenerBus的继承体系>及<Spark2. ...
- Linux rpm 命令参数使用
RPM是RedHat Package Manager(RedHat软件包管理工具)类似Windows里面的“添加/删除程序” rpm 执行安装包二进制包(Binary)以及源代码包(Source)两种 ...
- http client transfer
背景 在平时工作中我偶尔会写一些脚本监控HTTP接口的健康状况,基本上都是发送HTTP GET或HTTP POST请求,然后检测响应内容.但一直用的是WebClient和HttpWebRequest, ...
- 【Dll】Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call
[问题说明]调试动态库导出的函数时遇到的问题 [解决方法]要么加上__stdcall,对应__stdcall:要么去掉__stdcall,对应_cdecl
- win10 升级导致找不到SQL Server配置管理器
1.背景 SQL Server配置管理器可用来管理与SQL Server相关联的服务.配置SQL Server使用的网络协议以及从SQL Server客户端计算机管理网络连接配置.但是win10从17 ...
- 客户端负载均衡Ribbon之源码解析
什么是负载均衡器? 假设有一个分布式系统,该系统由在不同计算机上运行的许多服务组成.但是,当用户数量很大时,通常会为服务创建多个副本.每个副本都在另一台计算机上运行.此时,出现 "Load ...
- ES6 的Object.assign(target, source_1, ···)方法与对象的扩展运算符
一.基本概念 Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target).它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象. Ob ...
- IP分段小记
192.168.0.1 个人电脑:0.2-0.50 硬件开发板:0.51-0.100 机器人工控机:0.101-0.200 激光雷达:192.168.254.51~100 编码器板子:192.168. ...
- 1.搭建maven,eclipse创建maven项目
1.下载maven包,下载地址为:http://maven.apache.org/download.cgi 2.解压zip包 3.eclipse 引入maven: window-Preferences ...
- POJ2104Kth Number
整体二分模板题, 有些细节需要注意 #include<cstdio> #include<cctype> #include<climits> #include< ...