加入收藏 | 设为首页 | 会员中心 | 我要投稿 常州站长网 (https://www.0519zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 移动互联 > 评测 > 正文

5分钟搞懂Linux中直接I/O原理

发布时间:2019-06-15 16:08:37 所属栏目:评测 来源:源理君头条号
导读:副标题#e# 在介绍直接 I/O 之前,先来介绍下直接I/O这种机制产生的原因。毕竟已经有了缓存I/O(Buffered I/O),那肯定能够像到缓存I/O有缺陷吧,就按照这个思路来。 什么是缓存 I/O (Buffered I/O) 缓存 I/O 又被称作标准 I/O,大多数文件系统的默认 I/O

函数 generic_file_direct_IO() 代码如下所示:

  1. static ssize_t  
  2. generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,  
  3.  loff_t offset, unsigned long nr_segs)  
  4. {  
  5.  struct file *file = iocb->ki_filp;  
  6.  struct address_space *mapping = file->f_mapping;  
  7.  ssize_t retval;  
  8.  size_t write_len = 0;  
  9.   
  10.  if (rw == WRITE) {  
  11.  write_len = iov_length(iov, nr_segs);  
  12.  if (mapping_mapped(mapping))  
  13.  unmap_mapping_range(mapping, offset, write_len, 0);  
  14.  }  
  15.   
  16.  retval = filemap_write_and_wait(mapping);  
  17.  if (retval == 0) {  
  18.  retval = mapping->a_ops->direct_IO(rw, iocb, iov,  
  19.  offset, nr_segs);  
  20.  if (rw == WRITE && mapping->nrpages) {  
  21.  pgoff_t end = (offset + write_len - 1)  
  22.  >> PAGE_CACHE_SHIFT;  
  23.  int err = invalidate_inode_pages2_range(mapping,  
  24.  offset >> PAGE_CACHE_SHIFT, end);  
  25.  if (err)  
  26.  retval = err;  
  27.  }  
  28.  }  
  29.  return retval;  

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

  1. ssize_t  
  2. __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,  
  3.  struct block_device *bdev, const struct iovec *iov, loff_t offset,  
  4.  unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,  
  5.  int dio_lock_type)  
  6. {  
  7.  int seg;  
  8.  size_t size;  
  9.  unsigned long addr;  
  10.  unsigned blkbits = inode->i_blkbits;  
  11.  unsigned bdev_blkbits = 0;  
  12.  unsigned blocksize_mask = (1 << blkbits) - 1;  
  13.  ssize_t retval = -EINVAL;  
  14.  loff_t end = offset;  
  15.  struct dio *dio;  
  16.  int release_i_mutex = 0;  
  17.  int acquire_i_mutex = 0;  
  18.   
  19.  if (rw & WRITE)  
  20.  rw = WRITE_SYNC;  
  21.   
  22.  if (bdev)  
  23.  bdev_blkbits = blksize_bits(bdev_hardsect_size(bdev));  
  24.   
  25.  if (offset & blocksize_mask) {  
  26.  if (bdev)  
  27.  blkbits = bdev_blkbits;  
  28.  blocksize_mask = (1 << blkbits) - 1;  
  29.  if (offset & blocksize_mask)  
  30.  goto out;  
  31.  }  
  32.   
  33.  for (seg = 0; seg < nr_segs; seg++) {  
  34.  addr = (unsigned long)iov[seg].iov_base;  
  35.  size = iov[seg].iov_len;  
  36.  end += size;  
  37.  if ((addr & blocksize_mask) || (size & blocksize_mask)) {  
  38.  if (bdev)  
  39.  blkbits = bdev_blkbits;  
  40.  blocksize_mask = (1 << blkbits) - 1;  
  41.  if ((addr & blocksize_mask) || (size & blocksize_mask))  
  42.  goto out;  
  43.  }  
  44.  }  
  45.   
  46.  dio = kmalloc(sizeof(*dio), GFP_KERNEL);  
  47.  retval = -ENOMEM;  
  48.  if (!dio)  
  49.  goto out;  
  50.  dio->lock_type = dio_lock_type;  
  51.  if (dio_lock_type != DIO_NO_LOCKING) {  
  52.  if (rw == READ && end > offset) {  
  53.  struct address_space *mapping;  
  54.   
  55.  mapping = iocb->ki_filp->f_mapping;  
  56.  if (dio_lock_type != DIO_OWN_LOCKING) {  
  57.  mutex_lock(&inode->i_mutex);  
  58.  release_i_mutex = 1;  
  59.  }  
  60.   
  61.  retval = filemap_write_and_wait_range(mapping, offset,  
  62.  end - 1);  
  63.  if (retval) {  
  64.  kfree(dio);  
  65.  goto out;  
  66.  }  
  67.   
  68.  if (dio_lock_type == DIO_OWN_LOCKING) {  
  69.  mutex_unlock(&inode->i_mutex);  
  70.  acquire_i_mutex = 1;  
  71.  }  
  72.  }  
  73.   
  74.  if (dio_lock_type == DIO_LOCKING)  
  75.  down_read_non_owner(&inode->i_alloc_sem);  
  76.  }  
  77.   
  78.  dio->is_async = !is_sync_kiocb(iocb) && !((rw & WRITE) &&  
  79.  (end > i_size_read(inode)));  
  80.   
  81.  retval = direct_io_worker(rw, iocb, inode, iov, offset,  
  82.  nr_segs, blkbits, get_block, end_io, dio);  
  83.   
  84.  if (rw == READ && dio_lock_type == DIO_LOCKING)  
  85.  release_i_mutex = 0;  
  86.   
  87. out:  
  88.  if (release_i_mutex)  
  89.  mutex_unlock(&inode->i_mutex);  
  90.  else if (acquire_i_mutex)  
  91.  mutex_lock(&inode->i_mutex);  
  92.  return retval;  

(编辑:常州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读