免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1168 | 回复: 0
打印 上一主题 下一主题

块设备驱动的数据结构和方法 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-09-19 10:26 |只看该作者 |倒序浏览

               

  Normal
  0
  
  
  
  7.8 磅
  0
  2
  
  false
  false
  false
  
  EN-US
  ZH-CN
  X-NONE
  
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
  
  MicrosoftInternetExplorer4
  
   
   
   
   
   
   
   
   
   
   
   
  

  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  

/* Style Definitions */
table.MsoNormalTable
        {mso-style-name:普通表格;
        mso-tstyle-rowband-size:0;
        mso-tstyle-colband-size:0;
        mso-style-noshow:yes;
        mso-style-priority:99;
        mso-style-qformat:yes;
        mso-style-parent:"";
        mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
        mso-para-margin:0cm;
        mso-para-margin-bottom:.0001pt;
        mso-pagination:widow-orphan;
        font-size:10.0pt;
        font-family:"Calibri","sans-serif";}
从现在开始我们来看一下,在实现一个块设备驱动时你经常会遇到的一些数据结构和函数方法。
下面是一些主要的块设备驱动的数据结构
1、      
内核使用gendisk(generic disk 的简写)结构体来代表一个磁盘设备,该结构体定义在include/linux/genhd.h
struct gendisk {
  /* major, first_minor
and minors are input parameters only,
   * don't use directly.  Use disk_devt() and disk_max_parts().
   */
  int major;                 /* major number of driver */
  int
first_minor;        /*starting minor number*/
  int
minors;       /* maximum number of
minors, =1 for
                 
* disks that can't be partitioned. 每一个分区都有一个minor号*/

  char
disk_name[DISK_NAME_LEN];  /* name of
major driver */

  /* Array of
pointers to partitions indexed by partno.
   * Protected with matching bdev lock but stat
and other
   * non-critical accesses use RCU.  Always access through
   * helpers.
   */
  struct
disk_part_tbl *part_tbl;
  struct
hd_struct part0;

  struct
block_device_operations *fops;
  struct
request_queue *queue;
  void
*private_data;

  int flags;
  struct device
*driverfs_dev;  // FIXME: remove
  struct kobject
*slave_dir;

  struct
timer_rand_state *random;

  atomic_t
sync_io;         /* RAID */
  struct
work_struct async_notify;
#ifdef
CONFIG_BLK_DEV_INTEGRITY
  struct
blk_integrity *integrity;
#endif
  int node_id;
};
2、      
和每一个块设备驱动联系的I/O请求队列,使用request_queue结构体来描述,该结构体定义在include/linux/blkdev.h之中。可以看到这个结构体也是比较大,但是你可能用到的只有request 结构体。
3、      
每一个在request_queue中的请求都是使用request 结构体来表示的,request结构体也定义在include/linux/blkdev.h
/*
* try to put
the fields that are referenced together in the same cacheline.
* if you modify
this structure, be sure to check block/blk-core.c:rq_init()
* as well!
*/
struct request {
      struct
list_head queuelist;
      struct
call_single_data csd;
      int cpu;

      struct
request_queue *q;/*The container request queue*/

   …………
      /* Maintain
bio traversal state for part by part I/O submission.
       * hard_* are block layer internals, no driver
should touch them!
       */

      sector_t
sector;       /* next sector to submit (要访问的数据扇区)*/
      sector_t
hard_sector;         /* next sector to
complete */
      unsigned
long nr_sectors; /* no. of sectors left to
submit */
      unsigned
long hard_nr_sectors;   /* no. of sectors
left to complete */
      /* no. of
sectors left to submit in the current segment */
      unsigned
int current_nr_sectors;

      /* no. of
sectors left to complete in the current segment */
      unsigned
int hard_cur_sectors;

      struct bio
*bio;
      struct bio
*biotail;

      struct
hlist_node hash; /* merge hash */
      /*
       * The rb_node is only used inside the io
scheduler, requests
       * are pruned when moved to the dispatch queue.
So let the
       * completion_data share space with the
rb_node.
       */
      union {
           struct
rb_node rb_node;   /* sort/lookup */
           void
*completion_data;
      };

      /*
       * two pointers are available for the IO
schedulers, if they need
       * more they have to dynamically allocate it.
       */
      void
*elevator_private;
      void
*elevator_private2;

      struct
gendisk *rq_disk;
      unsigned
long start_time;

      /* Number
of scatter-gather DMA addr+len pairs after
       * physical address coalescing is performed.
       */
      unsigned
short nr_phys_segments;

      unsigned
short ioprio;

      void
*special;
      char
*buffer;

      int tag;
      int errors;

      int
ref_count;

      /*
       * when request is used as a packet command
carrier
       */
      unsigned
short cmd_len;
      unsigned
char __cmd[BLK_MAX_CDB];
      unsigned
char *cmd;

      unsigned
int data_len;
      unsigned
int extra_len;      /* length of alignment
and padding */
      unsigned
int sense_len;
      void *data;
      void
*sense;

      unsigned
long deadline;
      struct
list_head timeout_list;
      unsigned
int timeout;
      int
retries;

      /*
       * completion callback.
       */
      rq_end_io_fn
*end_io;
      void
*end_io_data;

      /* for bidi
*/
      struct
request *next_rq; /*队列中的下一个请求*/
};
4、      
块设备的block_device_operations 结构体对应字符设备的file_operations结构体。 该结构体包含着块设备驱动程序的函数入口点。
标准的方法有open()、release()、ioctl()等等
另外对块设备还有一些特殊的方法,例如:media_changed()和revalidate_disk(),这些函数支持可移动(可插拔)的块设备。
结构体block_device_operations 定义在include/linux/fs.h之中
  struct
block_device_operations {
  int (*open)
(struct block_device *, fmode_t);/*打开*/
  int (*release)
(struct gendisk *, fmode_t); /*关闭*/
  int
(*locked_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
  int (*ioctl)
(struct block_device *, fmode_t, unsigned, unsigned long); /*I/O控制*/
  int
(*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
  int
(*direct_access) (struct block_device *, sector_t,
                              void
**, unsigned long *);
  int
(*media_changed) (struct gendisk *);/*检查介质是否可用或拔出*/
  int
(*revalidate_disk) (struct gendisk *);
  int
(*getgeo)(struct block_device *, struct hd_geometry *);
  struct module
*owner;
};
5、      
我们在request结构体中曾看到一个结构体bio,我们现在就来看看这个结构体。一个bio结构体是在通用块层或更底层对块设备i/o操作的的表示单位。该结构体定义在include/linux/bio.h中。
/*
* main unit of
I/O for the block layer and lower layers (ie drivers and
* stacking
drivers)
*/
struct bio {
      sector_t         bi_sector;      /* device address in 512 byte
                                     sectors */
      struct bio      *bi_next; /*
request queue link */
      struct
block_device *bi_bdev;
      unsigned
long          bi_flags;   /* status, command, etc */
      unsigned
long          bi_rw;      /* bottom bits READ/WRITE,
                                   * top bits priority
                                   */

      unsigned
short        bi_vcnt;   /* how many bio_vec's */
      unsigned
short        bi_idx;           /* current index into bvl_vec */

      /* Number
of segments in this BIO after
       * physical address coalescing is performed.
       */
      unsigned
int       bi_phys_segments;

      unsigned
int       bi_size;    /* residual I/O count */

      /*
       * To keep track of the max segment size, we
account for the
       * sizes of the first and last mergeable
segments in this bio.
       */
      unsigned
int       bi_seg_front_size;
      unsigned
int       bi_seg_back_size;

      unsigned
int       bi_max_vecs;     /* max bvl_vecs we can hold */

      unsigned
int       bi_comp_cpu;    /* completion CPU */

      atomic_t       bi_cnt;           /*
pin count */

      struct
bio_vec          *bi_io_vec;   /* the actual vec list */

      bio_end_io_t           *bi_end_io;

      void               *bi_private;
#if defined(CONFIG_BLK_DEV_INTEGRITY)
      struct
bio_integrity_payload *bi_integrity;  /*
data integrity */
#endif

      bio_destructor_t     *bi_destructor;  /* destructor */

      /*
       * We can inline a number of vecs at the end of
the bio, to avoid
       * double allocations for a small number of
bio_vecs. This member
       * MUST obviously be kept at the very end of
the bio.
       */
      struct
bio_vec          bi_inline_vecs[0];
};
块数据内在使用bio_vec结构体来表示的。bio_vec数组的每一个元素都是由(page、page_offset、length)元素组成的。
这次我们简要的介绍了一些块设备常见的数据结构和函数等,下次我们就来使用这些结构和函数来做一个简单 的例子,来感受一下块设备驱动程序的编写方式。
感谢你对小孟的支持!
如果你有什么问题可以和我联系:xiangpengmeng@gmail.com或mxp556@163.com
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/104009/showart_2055722.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP