- 论坛徽章:
- 0
|
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 |
|