Linux驱动开发之块设备
目录
前言
块设备概念:块设备是指只能以块为单位进行访问的设备,块的大小一般是512个字节的整数倍。常见的块设备包括硬盘、SD卡、光盘等。
一、块设备驱动的系统架构
1.VFS
VFS是对各种具体文件系统的一种封装,用户程序访问文件提供统一的接口。
1.1.Cache
当用户发起文件访问请求的时候,首先回到Disk Cache中寻址文件是否被缓存了,如果在Cache,则直接从cache中读取。如果数据不在缓存中,就必须要到具体的文件系统中读取数据了。
1.2.Mapping Layer
首先确定文件系统的block size,然后计算所请求的数据包含多少个block。
调用具体文件系统的函数来访问文件的inode结构,确定所请求的数据在磁盘上的地址。
1.3.Generic Block Layer
Linux内核把块设备看做是由若干个扇区组成的数据空间,上层的读写请求在通用块层被构造成一个或多个bio结构。
1.4.I/O Scheduler Layer
I/O调度层负责采用某种算法(如:电梯调度算法)将I/O操作进行排序。
电梯调度算法的基本原则:如果电梯现在朝上运动,如果当前楼层的上方和下方都有请求,则先响应所有上方的请求,然后才向下响应下方的请求;如果电梯向下运动,则刚好相反。
1.5.Block Device Driver
在块系统架构的最底层,由块设备驱动根据排序好的请求,对硬件进行数据访问。
二、块设备驱动流程分析
初始化
- 注册块设备驱动程序——register_blkdev
- 初始化请求队列——blk_init_queue
- 指明扇区大小——blk_queue_logical_block_size
- 为块设备分配gendisk结构——alloc_disk
- 初始化gendisk结构
- major
- first_minor
- fops
- queue
- private_data
- disk_name
- 扇区数——set_capacity
- 注册块设备——add_disk
实现读写请求函数
- 取出一个要处理的请求——blk_fetch_request
- 根据请求里的信息访问硬件,获取数据
- 利用__blk_end_request_curl判断请求队列里是否还有剩余的请求要处理,如果有按照上面两步来处理
三、一个最简单的块设备驱动程序
1.源码
simples_blkdev.c:
#include<linux/module.h>
#include<linux/init.h>
#include<linux/blkdev.h>
#include<linux/bio.h>
#include <linux/sched.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/timer.h>
#include <linux/types.h> /* size_t */
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/hdreg.h> /* HDIO_GETGEO */
#include