首页 > 代码库 > linux驱动开发之块设备学习笔记

linux驱动开发之块设备学习笔记


学习参考:http://www.cnblogs.com/yuanfang/archive/2010/12/24/1916231.html


1、块设备
  块设备将数据按照固定块大小的块中,每个块的大小通常在512字节到32768字节之间,磁盘、SD卡都是常见的块设备。 2、字符设备和块设备的区别: 字符设备 块设备 ---------------------------------------------- 按字节访问   按块进行访问 只能按照数据流访问   随机访问 直接访问设备   挂在文件系统的方式访问 3、Linux块设备处理模型
   |-------------------------------------------------------------|
   |                           VFS                               |
   |-------------------------------------------------------------|
   |     |                                         |             |
   |Disk Caches                                    |             |
   |     |                                         |             |
   |-------------------------------------------------------------|
   |Disk Filesystem  |  Disk Filesystem  |  Block Device File    |
   |-----------------                     -----------------------|
   |                     Mapping Layer                           |
   |-------------------------------------------------------------|
   |                   Generic Block Layer                       |
   |-------------------------------------------------------------|
   |                  I/O Scheduler Layer                        |
   |-------------------------------------------------------------|
   |    Block Device Driver      |      Block Device Driver      |
   |------------------------     |        --------------------   |
   |       Hard Disk             |            Hard Disk          |
   |------------------------------------------------------------—|

  

VFS:虚拟文件系统,VFS是对各种具体文件系统的一种封装,为用户程序提供访问文件的统一接口。
Disk Cache:当用户发起文件访问请求的时候,首先会到Disk Cache中寻找文件是否被缓存,如果缓存中有则在Cache中读取,如果数据没有被缓存,那就必须到文件系统中去读取。 Mapping Layer:   1、首先确定文件系统的block size,然后计算所请求的数据包含多少个block,   2、调用具体文件系统的函数来访问文件的inode,确定所请求数据在磁盘上面的逻辑地址。 Generic block layer:   Linux内核为快设备抽象成了统一的模型,把块设备看做是若干个扇区组成的数据空间。来完成块设备的相关核心功能。 I/O scheduler layer:   I/O调度层负责将I/O操作顺序,采用电梯算法。提高 I/O 调度器的效率也是影响整个系统对块设备上数据管理效率的一个方面。 Block Device Driver:   快设备驱动程序,完成和硬件的具体交互,块设备相关数据结构

4、设备描述 gendisk结构体   内核使用 gendisk 结构来表示一个独立的磁盘设备,内核还使用 gendisk 结构来表示分区,在此结构中,很多程序必须由驱动程序来进行初始化。该结构体定义<linux/genhd.h>中。

4.1、gendisk结构体解析
    struct gendisk {
        int major;                    /*设备主设备号*/
        int first_minor;            /*起始次设备号*/
        int minors;                    /*次设备号的数量,也称为分区数量,如果改值为1,表示无法分区*/
        char disk_name[32];            /*设备名称*/
        struct hd_struct **part;    /*分区表的信息*/
        int part_uevent_suppress;
        struct block_device_operations *fops;/*块设备操作集合 */
        struct request_queue *queue;         /*请求队列,用于管理该设备IO请求队列的指针*/
        void *private_data;                     /*私有数据*/
        sector_t capacity;                     /*扇区数,512字节为1个扇区,描述设备容量*/
        ....
    };

    struct gendisk *alloc_disk(int minors)
    分配一个gendisk结构,minors为此设备好的个数 = 分区数+1

    void del_gendisk(struct gendisk *disk)
    当不需要这个磁盘的时候,释放gendisk结构

    endisk中包含一个kobject成员, 它是一个可被引用计数的结构体。通过get_disk()和put_disk()函数可用来操作引用计数。驱动通常不需要做这个。
    struct kobject *get_disk(struct gendisk *disk);
    void put_disk(struct gendisk *disk);

    void add_disk(struct gendisk *gd);
    对gendisk初始化之后还不能使用和这个设备,应该使用add_disk注册磁盘设备

    static inline void set_capacity(struct gendisk *disk, sector_t size)
    设置gendisk容量,块设备中最小单位是扇区,扇区的大小一般是2的整数倍,最常见的大小是512kb (xx>>9)表示/512 (xx<<9)表示*512。扇区大小是物理设备所决定的。

 

5、block_device_operationse结构体
    类似与字符设备驱动程序中的file_operations结构,该集合用于控制设备的操作,但是在大多数情况下都是以mount的方式进行访问,用户程序一般不会直接访问块设备中的文件。需要包含<linux/blkdev.h>头文件。
    struct block_device_operations {
        /*打开这个设备时候调用*/
        int (*open) (struct inode *, struct file *);
        
        /*关闭/释放 时候调用*/
        int (*release) (struct inode *, struct file *);
        
        /*ioctl()系统调用的实现,块设备包含大量的标准请求,这些标准请求由 Linux 块设备层处理,因此大部分块设备驱动的*/
        int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
        
        long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
        long (*compat_ioctl) (struct file *, unsigned, unsigned long);
        int (*direct_access) (struct block_device *, sector_t, unsigned long *);
        
        /*内核周期调用检查驱动器介质有没有发生改变,改变返回非0,没有改变返回0。用于支持可移动设备,非可以移动设备不用实现*/
        int (*media_changed) (struct gendisk *);
        
        /*被调用响应介质被改变,驱动进行必要的工作*/
        int (*revalidate_disk) (struct gendisk *);
        
        /*根据驱动器的几何信息填充hd_geometry,包含磁头,柱面,扇区等信息.*/
        int (*getgeo)(struct block_device *, struct hd_geometry *);
        
        /*模块拥有者,一般初始化为THIS_MODULE*/
        struct module *owner;
    };
    block_device_operations 结构中没有实际读或写数据的函数,在块 I/O 子系统中,这些操作由请求函数处理。

6、request 和 bio 结构体

    struct request {
        struct list_head queuelist;/*请求链表*/
        struct list_head donelist;
        request_queue_t *q;           /*请求所属队列*/
        unsigned int cmd_flags;
        enum rq_cmd_type_bits cmd_type;
        sector_t sector;         /* 当前扇区 */
        sector_t hard_sector;     /*要传输的下一个扇区*/
        unsigned long nr_sectors;/* 要传输的扇区数目*/
        unsigned long hard_nr_sectors;  /*要被完成扇区的数目 */
        unsigned int current_nr_sectors;/*当前传送的扇区*/
        unsigned int hard_cur_sectors;  /*当前要被完成的扇区数目*/
        struct bio *bio;    /*请求的block i/o(bio)结构体链表首 request请求 第一个bio*/
        struct bio *biotail;/*请求的bio结构体链表尾 request请求 最后个bio*/
        char *buffer; /*request请求中断 第一个bio*/
        int ref_count;/*引用计数*/
        .....................
    };

 

笔记未完!!!!!!

linux驱动开发之块设备学习笔记