分享

harddisk

 海漩涡 2014-05-05

 






//根据驱动器的几何信息填充hd_geometry,包含磁头,柱面,扇区等信息.

    int (* getgeo)(struct block_device*, struct hd_geometry*);


3.gendisk结构体

使用gendisk结果提来描述一个独立的磁盘设备或分区.

    //gendisk structure

    struct gendisk{

        /*前三个元素共同表征了一个磁盘的主,次设备号,同一个磁盘的各个分区共享一个主设备号*/

        int major;/*主设备号*/

        int first_minor;/*第一个次设备号*/

        int minors;/*最大的次设备数,如果不能分区,则为1*/

        char disk_name[32];

        struct hd_struct** part;/*磁盘上的分区信息*/

        struct block_device_operations* fops;/*块设备操作,block_device_operations*/

        struct request_queue* queue;/*请求队列,用于管理该设备IO请求队列的指针*/

        void* private_data;/*私有数据*/

        sector_t capacity;/*扇区数,512字节为1个扇区,描述设备容量*/

        //......

    };

 关于gendisk的操作:

    /*分配一个gendisk结构体,此结构体是由内核动态分配的*/

    struct gendisk* alloc_disk(int minors);

    /*增加gendisk,来注册该设备,此动作应该在设备驱动初始化完毕,并能响应磁盘请求之后*/

    void add_disk(struct gendisk* gd);

    /*释放一个不再需要的磁盘*/

void del_gendisk(struct gendisk* gd);

    /*gendisk引用计数*/

    /**

    ***gendisk引用计数器:gendisk包含一个kobject成员.通过get_disk()&put_disk()函数来操作引用

    ***计数,此操作不需要驱动亲自完成.通常调用del_gendisk()会去掉gendisk的最终引用计数,但不是必 

    ***须的,因此在del_gendisk()后gendisk结构体能继续存在.

    **/

    /*设置gendisk容量*/

    void set_capacity(struct gendisk* disk, sector_t size);

块设备中,最小的可寻址单元就扇区,常见扇区大小是512字节.扇区的大小是设备的物理属性,是所有块设备的基本单元,块设备无法对比扇区小的单元进行寻址和操作.不过许多块设备能够一次传输多个扇区.不管物理设备的真实扇区是多少,内核与块设备交互的扇区均以512字节为单位.所以set_capcity()函数以512字节为单位.



4.request和bio结构体

1)请求request

request和request_queue结构体:Linux块设备驱动中,使用request结构体来表征等待进行的IO请求;并用request_queue来表征一个块IO请求队列.两个结构体的定义如下:

request结构体

    struct request{

        struct list_head queuelist;

        unsigned long flags;

 

        sector_t sector;/*要传输的下一个扇区*/

        unsigned long nr_sectors;/*要传送的扇区数目*/

        unsigned int current_nr_sector;/*当前要传送的扇区*/

 

        sector_t hard_sector;/*要完成的下一个扇区*/

        unsigned long hard_nr_sectors;/*要被完成的扇区数目*/

        unsigned int hard_cur_sectors;/*当前要被完成的扇区数目*/

 

        struct bio* bio;/*请求的bio结构体的链表*/

        struct bio* biotail;/*请求的bio结构体的链表尾*/

        

        /*请求在屋里内存中占据的不连续的段的数目*/

        unsigned short nr_phys_segments;

        unsigned short nr_hw_segments;

 

        int tag;

        char* buffer;/*传送的缓冲区,内核的虚拟地址*/

        int ref_count;/*引用计数*/

        ...

    };

说明:

request结构体的主要成员包括:

        sector_t hard_sector;/*要完成的下一个扇区*/

        unsigned long hard_nr_sectors;/*要被完成的扇区数目*/

        unsigned int hard_cur_sectors;/*当前要被完成的扇区数目*/

        /*

         * 上述三个成员依次是第一个尚未传输的扇区,尚待完成的扇区数,当前IO操作中待完成的扇区数

         * 但驱动中一般不会用到他们.而是下面的一组成员.

         */

        sector_t sector;/*要传输的下一个扇区*/

        unsigned long nr_sectors;/*要传送的扇区数目*/

        unsigned int current_nr_sector;/*当前要传送的扇区*/

        /* 

         * 这三个成员,以字节为单位.如果硬件的扇区大小不是512字节.如字节,则在开始对硬件进行操作之

         * 前,应先用4来除起始扇区号.前三个成员,与后三个成员的关系可以理解为"副本".

         */

关于unsigned short nr_phys_segments:该成员表示相邻的页被合并后,这个请求在物理内存中的段的数目.如果该设备支持SG(分散/聚合,scatter/gather),可根据该字段申请sizeof(scatterlist*) nr_phys_segments的内存,并使用下面的函数进行DMA映射:

int blk_rq_map_sg(request_queue_t* q, struct request* rq, struct scatterlist *sg);

该函数与dma_map_sg()类似,返回scatterlist列表入口的数量.

关于struct list_head queuelist:该成员用于链接这个请求到请求队列的链表结构,函数blkdev_ dequeue_request()可用于从队列中移除请求.宏rq_data_dir(struct request* req)可获得数据传送方向.返回0表示从设备读取,否则表示写向设备.



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多