[linux驱动]linux块设备学习笔记(四)——请求处理

一,请求处理

块设备的处理函数里没有read write等函数,所有对块设备的请求如读取 写入等都是通过request函数处理的。request函数的原型是void request(request_queue_t *queue);
request函数的处理是异步的。每一个设备都有一个请求队列,当请求队列生成的时候,request函数就与该请求队列绑定在一起了,request函数总是与一个自旋锁一起使用,当request函数拥有自旋锁的时候,该锁防止内核为设备安排其它请求。构request代表了挂起的I/O请求,每个请求用一个结构request实例描述,存放在请求队列链表中

 

[cpp] view plaincopy技术分享技术分享
 
  1. <pre name="code" class="cpp">struct request {    
  2. 02.    //用于挂在请求队列链表的节点,使用函数blkdev_dequeue_request访问它,而不能直接访问    
  3. 04.    struct list_head queuelist;     
  4. 05.    struct list_head donelist;  /*用于挂在已完成请求链表的节点*/    
  5. 06.    struct request_queue *q;   /*指向请求队列*/    
  6. 07.    unsigned int cmd_flags;    /*命令标识*/    
  7. 08.    enum rq_cmd_type_bits cmd_type;  /*命令类型*/    
  8. 09.    /*各种各样的扇区计数,为提交i/o维护bio横断面的状态信息,hard_*成员是块层内部使用的,驱动程序不应该改变它们*/    
  9. 12.    sector_t sector;     /*将提交的下一个扇区*/    
  10. 13.    sector_t hard_sector;        /* 将完成的下一个扇区*/    
  11. 14.    unsigned long nr_sectors;  /* 整个请求还需要传送的扇区数*/    
  12. 15.    unsigned long hard_nr_sectors; /* 将完成的扇区数*/    
  13. 16. /*在当前bio中还需要传送的扇区数 */    
  14. 17.    unsigned int current_nr_sectors;    
  15. 18.    /*在当前段中将完成的扇区数*/    
  16. 19.    unsigned int hard_cur_sectors;    
  17. 20.    struct bio *bio;     /*请求中第一个未完成操作的bio*、  
  18. 21.    struct bio *biotail; /*请求链表中末尾的bio*、  
  19. 22.    struct hlist_node hash;  /*融合 hash */    
  20. 23.    /* rb_node仅用在I/O调度器中,当请求被移到分发队列中时,请求将被删除。因此,让completion_data与rb_node分享空间*/        
  21. 25.    union {    
  22. 26.        struct rb_node rb_node;   /* 排序/查找*/    
  23. 27.        void *completion_data;    
  24. 28.    };    




二,请求队列

 

每个块设备都有一个请求队列,每个请求队列单独执行I/O调度,请求队列是由请求结构实例链接成的双向链表,链表以及整个队列的信息用结构request_queue描述,称为请求队列对象结构或请求队列结构。它存放了关于挂起请求的信息以及管理请求队列(如:电梯算法)所需要的信息。结构成员request_fn是来自设备驱动程序的请求处理函数。

 

三,Bio结构

通常1个bio对应1个I/O请求,IO调度算法可将连续的bio合并成1个请求。所以,1个请求可以包含多个bio。bio为通用层的主要数据结构,既描述了磁盘的位置,又描述了内存的位置,是上层内核vfs与下层驱动的连接纽带

 

[cpp] view plaincopy技术分享技术分享
 
  1. struct bio {    
  2. 02.sector_t        bi_sector;//该bio结构所要传输的第一个(512字节)扇区:磁盘的位置    
  3. 03.struct bio        *bi_next;    //请求链表    
  4. 04.struct block_device    *bi_bdev;//相关的块设备    
  5. 05.unsigned long        bi_flags//状态和命令标志    
  6. 06.unsigned long        bi_rw; //读写    
  7. 07.unsigned short        bi_vcnt;//bio_vesc偏移的个数    
  8. 08.unsigned short        bi_idx;    //bi_io_vec的当前索引    
  9. 09.unsigned short        bi_phys_segments;//当DMA完成时候,它表示BIO中包含的物理段的数目  
  10. 10.unsigned short        bi_hw_segments;//当DMA完成时候,它表示BIO中包含的硬件所能操作的段数   
  11. 11.unsigned int        bi_size;    //以字节为单位所需要传输数据的大小    
  12. 12.unsigned int        bi_hw_front_size;//第一个可合并的段大小;    
  13. 13.unsigned int        bi_hw_back_size;//最后一个可合并的段大小    
  14. 14.unsigned int        bi_max_vecs;    //bio_vecs数目上限    
  15. 15.struct bio_vec        *bi_io_vec;    //bio_vec链表:内存的位置    
  16. 16.bio_end_io_t        *bi_end_io;//I/O完成方法    
  17. 17.atomic_t        bi_cnt; //使用计数    
  18. 18.void            *bi_private; //拥有者的私有方法    
  19. 19.bio_destructor_t    *bi_destructor;    //销毁方法    
  20. 20.};    
  21. 内存数据段结构bio_vec  
  22. struct bio_vec {  
  23.         struct page     *bv_page;   /*数据段所在的页*/  
  24.         unsigned short  bv_len;     /*数据段的长度*/  
  25.         unsigned short  bv_offset;  /*数据段页内偏移*/  
  26.  };  



四:

Linux中的队列请求处理函数为kernel/drivers/mmc/card/Block.c文件的mmc_blk_issue_rq()函数

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。