一: 块设备驱动注册与注销

块设备驱动中的第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 块设备驱动 (三)块设备驱动开发的更多相关文章

  1. raid10 五块硬盘/raid5(三块使用,两块备份)

    raid 10五块硬盘 第一步:在虚拟机中在添加五块硬盘 第二步:使用mdadm命令创建RAID10,名称为“/dev/md0/” -C代表创建操作,-v显示创建过程,-a yes检查RAID名称,- ...

  2. RAID5的创建(5块磁盘,三块做raid,两块做备份)

    RAID5的创建(5块磁盘,三块做raid,两块做备份) 第一步:参考我的上一篇博客,用同样的方法添加5块硬盘.地址如下: https://www.cnblogs.com/Feng-L/p/11735 ...

  3. Raid5(五块磁盘,三块做raid,两块做备份)

    1.在虚拟中再添加五块磁盘.  2.使用mdadm命令创建raid5,名称为“/dev/md5”. -C代表创建操作,-v显示创建过程,-a yes检查RAID名称,-n是用到的硬盘个数,-l是定义R ...

  4. Linux设备驱动--块设备(三)之程序设计

    块设备驱动注册与注销 块设备驱动中的第1个工作通常是注册它们自己到内核,完成这个任务的函数是 register_blkdev(),其原型为:int register_blkdev(unsigned i ...

  5. Linux设备驱动--块设备(三)之程序设计(转)

    http://blog.csdn.net/jianchi88/article/details/7212701 块设备驱动注册与注销 块设备驱动中的第1个工作通常是注册它们自己到内核,完成这个任务的函数 ...

  6. Linux块设备IO子系统(一) _驱动模型

    块设备是Linux三大设备之一,其驱动模型主要针对磁盘,Flash等存储类设备,块设备(blockdevice)是一种具有一定结构的随机存取设备,对这种设备的读写是按块(所以叫块设备)进行的,他使用缓 ...

  7. 乾坤合一~Linux设备驱动之块设备驱动

    1. 题外话 在蜕变成蝶的一系列学习当中,我们已经掌握了大部分Linux驱动的知识,在乾坤合一的分享当中,以综合实例为主要讲解,在一个月的蜕茧成蝶的学习探索当中,觉得数据结构,指针,链表等等占据了代码 ...

  8. FLASH驱动之-块设备驱动系统构架

    一.  块设备是只能以块为单位进行访问的设备,块的大小一般是512个字节的整数倍,常见的块设备包括硬件,SD卡,光盘,flash等.驱动程序是块的整数倍从设备读写得到数据.块设备的最小访单位为块,不同 ...

  9. 深入浅出:Linux设备驱动之字符设备驱

    一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流 ...

  10. 【转】深入浅出:Linux设备驱动之字符设备驱动

    深入浅出:Linux设备驱动之字符设备驱动 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据 ...

随机推荐

  1. java中String初始化的两种方式

    转自:http://www.diybl.com/course/3_program/java/javajs/2007104/75886.html       字符串可能是任何程序语言中都会出现的对象,j ...

  2. 我要好offer之 网络大总结

    1. TCP协议的状态机 TCP一共定义了11种状态,这些状态可以使用 netstat 命令查看 @左耳朵耗子 tcp系列教程: 上篇 下篇 2. TCP建立连接3次握手.释放连接4次握手 TCP包头 ...

  3. 如果dom节点是动态添加进页面的,在页面节点绑定事件如何解决的问题。

    如果dom节点是动态添加进页面,想在节点绑定事件,传统的做法就是遍历节点,但会出现问题,也肯能有其他的办法,突然想到 可以依据事件冒泡,这样就不惧页面后添加节点而不响应事件的问题.比较结实.示例代码如 ...

  4. 切換 java compiler 版本

    有些程式在執行時會顯示需要較新的 java jre 版本, 若系統裝有兩個 java jre 可以使用下列指令切協版本, sudo update-alternatives --config java ...

  5. Android Studio 快捷键整理分享-SadieYu

    文章编辑整理:Android Studio 中文组 - SadieYu Alt+回车 导入包,自动修正 Ctrl+N   查找类 Ctrl+Shift+N 查找文件 Ctrl+Alt+L  格式化代码 ...

  6. 对于drawRect使用,谨慎使用!

    #1.drawRect简介drawRect方法在UIView的使用上起着十分关键的作用.不知道大家注意过没有,每一次创建UIView子类文件时候,会有自动带有已注释的drawRect方法,也许从这一点 ...

  7. 作列表排列时div的table属性应用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. python 之 实现su 到root账号

    简单记录一下如何通过python代码在linux系统下实现自动su - 切换到root账号, 使用到的模块:paramiko 使用到的方法:invoke_shell  功能:在SSH server端创 ...

  9. Spring Boot中实现异步调用之@Async

    一.什么是异步调用 “异步调用”对应的是“同步调用”,同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行:异步调用指程序在顺序执行时,不等待异步调用 的语句返回结果 ...

  10. Java多线程中Lock的使用

    Jdk1.5以后,在java.util.concurrent.locks包下,有一组实现线程同步的接口和类,说到线程的同步,可能大家都会想到synchronized关键字, 这是java内置的关键字, ...