Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1426037
  • 博文数量: 613
  • 博客积分: 11499
  • 博客等级: 上将
  • 技术积分: 5511
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-12 19:27
  • 认证徽章:
文章分类

全部博文(613)

文章存档

2016年(5)

2015年(18)

2014年(12)

2013年(16)

2012年(300)

2011年(45)

2010年(37)

2009年(79)

2008年(101)

分类:

2012-09-19 16:38:53

原文地址:046 fs/iobuf.c 作者:hylpro

2008-1-3 
kiobuf和raw设备的关系比较密切. raw设备十一个字符设备,单仅仅是字符设备而已.读写一个raw设备对应于一个block device.通过raw设备bind的块设备,使用另一种读写方式,没有copy to/form user的过程了,不像设备文件那样(block_dev.c). 其基本思路是把用户传进来的buf,强制调度到memory中,使之在读写的时候不会mm fault,同时收集这些页面的page的指针,并记录到kiobuf中. 然后,为每个page创建一个buffer entry,启动读写过程, 完成之后就可以释放kiobuf并返回了. 不在有copy过程了.

这些代码分布在iobuf.c buffer.c memory.c raw.c之中.但并不难理解.kiobuf本身注释很全面.
struct kiobuf
{
int nr_pages; /* Pages actually referenced */
int array_len; /* Space in the allocated lists */
int offset; /* Offset to start of valid data */
int length; /* Number of valid bytes of data */

/* Keep separate track of the physical addresses and page
* structs involved. If we do IO to a memory-mapped device
* region, there won't necessarily be page structs defined for
* every address. */

struct page ** maplist;

unsigned int locked : 1; /* If set, pages has been locked */

/* Always embed enough struct pages for 64k of IO */
struct page * map_array[KIO_STATIC_PAGES];

/* Dynamic state for IO completion: */
atomic_t io_count; /* IOs still in progress */
int errno; /* Status of completed IO */
void (*end_io) (struct kiobuf *); /* Completion callback */
wait_queue_head_t wait_queue;
}

我们从raw设备使用kiobuf的流程走一下吧.然后就不具体分析各个函数了.
ssize_t rw_raw_dev(int rw, struct file *filp, char *buf,
size_t size, loff_t *offp)
{
struct kiobuf * iobuf;
.....

/*
* First, a few checks on device size limits
*/
.......

/*
* We'll just use one kiobuf
*/

err = alloc_kiovec(1, &iobuf); /*分配kiobuf*/
if (err)
return err;

/*
* Split the IO into KIO_MAX_SECTORS chunks, mapping and
* unmapping the single kiobuf as we go to perform each chunk of
* IO.
*/
transferred = 0;
blocknr = *offp >> sector_bits;
while (size > 0) {
blocks = size >> sector_bits;
if (blocks > max_sectors) /*max_sectors:kiobuf一次最大64k*/
blocks = max_sectors;
if (blocks > limit - blocknr) /*limit是blkdev上最大编号的扇区*/
blocks = limit - blocknr;
if (!blocks)
break;

iosize = blocks << sector_bits;

err = map_user_kiobuf(rw, iobuf, (unsigned long) buf, iosize);
/*以前分析过了:检查权限,将buf开始的长度为iosize涉及到的page调度到内存,并记录到kiobuf*/
if (err)
break;
....
for (i=0; i < blocks; i++)
b[i] = blocknr++;

err = brw_kiovec(rw, 1, &iobuf, dev, b, sector_size);
/*将记录下来的page,分割成buffer entry,启动io并等待其io操作完成*/
if (err >= 0) {
transferred += err;
size -= err;
buf += err;
}

unmap_kiobuf(iobuf); /* The unlock_kiobuf is implicit here */
/*释放记录下来的page(一般情况下就是减少引用计数)*/
if (err != iosize)
break;
}

free_kiovec(1, &iobuf); /*释放kiobuf本身*/

if (transferred) {
*offp += transferred;
return transferred;
}

return err;
}

具体的函数不再列出,分析buffer.c memory.c 的时候都有涉及. 这里的分析把以前的种种操作串起来,有个整体印象.

阅读(310) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
请登录后评论。

登录 注册