kfs代码研究(磁盘异步IO)

 

磁盘IO在[qcdio/qcdiskqueue.h]和[qcdio/qcdiskqueue.cc]中实现,基于线程池和消费者/生产者模型。在这两个源文件中实现了基于成块读写的异步磁盘IO。

[qcdio/qcdiskqueue.cpp] class QCDiskQueue::Queue,实现了磁盘文件的异步IO。文件读写的单位是块(支持direct-io)。它会启动给定数量(inThreadCount)的线程处理io请求,支持管理给定数量(mFileCount)的磁盘文件,并且只支持给定数量(inMaxQueueDepth)的请求队列长度。每次读写请求都表示为一个Request,并插入Queue本身的请求队列中,执行线程从请求队列中取下Request并请求,请求执行完成以后,调用请求的回调函数。Queue本身并不保证磁盘请求的执行顺序,也就是说,对于同一个文件发出的请求可能被并行执行,上层用户必须保证发起的请求是可并行的。对于一个由Queue管理的文件,它会为每个工作线程打开一个文件描述符,这样就可以充分发挥读的并行性,同时也意味着每个文件会打开inThreadCount个文件描述符。Queue用数组组织所有的打开的文件,当上层调用Open接口,Queue会返回一个int表示该文件在文件数组中的下标,类似于系统层的文件描述符,后续的读写请求都在该"文件描述符"上进行。Queue使用数组和链表组织所有的读写请求,当上层发起一个请求,首先在数组中分配一个未使用的Request,然后将该request放入请求队列中,并把request的id(request在数组中的下标)返回给调用者,后续该request的操作以requestid为标示。文件的读写由工作线程使用writev完成。每个请求都有一个与之关联的回调函数,该请求失败或者成功会调用该回调函数。由于单个Request的buffer数量是有限的,最多为writev支持的最大数组长度,因此一个请求可能有多个Request组成,由链表链接起来。第一个Request包含了整个请求读写的块数量,工作线程每次会取一个完整的请求的所有Request,因此每个请求都是有一个线程完成的。看代码发现可能的一个bug,Cancel一个请求的时候,代码只是把请求的第一个Request从请求链表中移除,而没有移除所有的Request。在0.4的版本中,Sync接口没有实现,仅仅是一个空读。

[qcdio/qcdiskqueue.cpp] class QCDiskQueue 该类是对QCDiskQueue::Queue进行了简单的封装,同时使用条件变量提供了文件读写的磁盘接口。就是请求发起线程阻塞在那里,等待工作线程完成io操作。

以上就是磁盘异步IO的主要实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值