设为首页 加入收藏

TOP

Linux 中直接 I/O 机制的介绍(三)
2011-03-21 13:14:14 来源:IBM 作者:黄 晓晨 【 】 浏览:3565
Tags:Linux 直接 I/O 机制 介绍
gt;> PAGE_CACHE_SHIFT; int err = invalidate_inode_pages2_range(mapping, offset >> PAGE_CACHE_SHIFT, end); if (err) retval = err; } } return retval; }

函数 generic_file_direct_IO() 对 WRITE 操作类型进行了一些特殊处理,这在下边介绍 write() 系统调用的时候再做说明。除此之外,它主要是调用了 direct_IO 方法去执行直接 I/O 的读或者写操作。在进行直接  I/O  读操作之前,先将页缓存中的相关脏数据刷回到磁盘上去,这样做可以确保从磁盘上读到的是最新的数据。这里的 direct_IO 方法最终会对应到 __blockdev_direct_IO() 函数上去。__blockdev_direct_IO() 函数的代码如下所示:


清单 7. 函数 __blockdev_direct_IO()
ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, struct block_device *bdev, const struct iovec *iov, loff_t offset, unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, int dio_lock_type) { int seg; size_t size; unsigned long addr; unsigned blkbits = inode->i_blkbits; unsigned bdev_blkbits = 0; unsigned blocksize_mask = (1 << blkbits) - 1; ssize_t retval = -EINVAL; loff_t end = offset; struct dio *dio; int release_i_mutex = 0; int acquire_i_mutex = 0; if (rw & WRITE) rw = WRITE_SYNC; if (bdev) bdev_blkbits = blksize_bits(bdev_hardsect_size(bdev)); if (offset & blocksize_mask) { if (bdev) blkbits = bdev_blkbits; blocksize_mask = (1 << blkbits) - 1; if (offset & blocksize_mask) goto out; } for (seg = 0; seg < nr_segs; seg++) { addr = (unsigned long)iov[seg].iov_base; size = iov[seg].iov_len; end += size; if ((addr & blocksize_mask) || (size & blocksize_mask)) { if (bdev) blkbits = bdev_blkbits; blocksize_mask = (1 << blkbits) - 1; if ((addr & blocksize_mask) || (size & blocksize_mask)) goto out; } } dio = kmalloc(sizeof(*dio), GFP_KERNEL); retval = -ENOMEM; if (!dio) goto out; dio->lock_type = dio_lock_type; if (dio_lock_type != DIO_NO_LOCKING) { if (rw == READ && end > offset) { struct address_space *mapping; mapping = iocb->ki_filp->f_mapping; if (dio_lock_type != DIO_OWN_LOCKING) { mutex_lock(&inode->i_mutex); release_i_mutex = 1; } retval = filemap_write_and_wait_range(mapping, offset, end - 1); if (retval) { kfree(dio); goto out; } if (dio_lock_type == DIO_OWN_LOCKING) { mutex_unlock(&inode->i_mutex); acquire_i_mutex = 1; } } if (dio_lock_type == DIO_LOCKING) down_read_non_owner(&inode->i_alloc_sem); } dio->is_async = !is_sync_kiocb(iocb) && !((rw & WRITE) && (end > i_size_read(inode))); retval = direct_io_worker(rw, iocb, inode, iov, offset, nr_segs, blkbits, get_block, end_io, dio); if (rw == READ && dio_lock_type == DIO_LOCKING) release_i_mutex = 0; out: if (release_i_mutex) mutex_unlock(&inode->i_mutex); else if (acquire_i_mutex) mutex_lock(&inode->i_mutex); return retval; }

该函数将要读或者要写的数据进行拆分,并检查缓冲区对齐的情况。本文在前边介绍 open() 函数的时候指出,使用直接 I/O 读写数据的时候必须要注意缓冲区对齐的问题,从上边的代码可以看出,缓冲区对齐的检查是在 __blockdev_direct_IO() 函数里边进行的。用户地址空间的缓冲区可以通过 iov 数组中的 iovec 描述符确定。直接 I/O 的读操作或者写操作都是同步进行

首页 上一页 1 2 3 4 5 6 下一页 尾页 3/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇使用 google-perftools 剖析程序.. 下一篇纯真IP数据库格式详解

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: