相关疑难解决方法(0)

Linux上真的没有异步块I/O吗?

考虑一个受CPU限制的应用程序,但也具有高性能I/O要求.

我正在将Linux文件I/O与Windows进行比较,我看不出epoll将如何帮助Linux程序.内核会告诉我文件描述符"准备好读取",但是我仍然需要调用阻塞read()来获取我的数据,如果我想读取兆字节,那么很明显它会阻塞.

在Windows上,我可以创建一个设置了OVERLAPPED的文件句柄,然后使用非阻塞I/O,并在I/O完成时收到通知,并使用该完成函数中的数据.我需要不花费应用程序级别的挂钟时间等待数据,这意味着我可以精确地将我的线程数调整为我的内核数量,并获得100%的高效CPU利用率.

如果我必须在Linux上模拟异步I/O,那么我必须分配一些线程来执行此操作,并且这些线程将花费一些时间来处理CPU事务,并且大量时间阻塞I/O,此外,在这些线程的消息传递中会有开销.因此,我将过度订阅或利用我的CPU核心.

我把mmap()+ madvise()(WILLNEED)视为"穷人的异步I/O",但它仍然没有完全通过那里,因为当它完成时我无法得到通知 - 我有"猜测",如果我猜"错误",我将最终阻止内存访问,等待数据来自磁盘.

Linux似乎在io_submit中启动了异步I/O,它似乎也有一个用户空间POSIX aio实现,但它已经有一段时间了,我知道没有人会担保这些系统的关键,高性能的应用程序.

Windows模型的工作方式大致如下:

  1. 发出异步操作.
  2. 将异步操作绑定到特定的I/O完成端口.
  3. 等待该端口上的操作完成
  4. 当I/O完成时,等待端口的线程解除阻塞,并返回对挂起的I/O操作的引用.

步骤1/2通常作为单个事物完成.步骤3/4通常使用工作线程池完成,而不是(必要)与发出I/O相同的线程.这个模型有点类似于boost :: asio提供的模型,除了boost :: asio实际上不会给你异步的基于块的(磁盘)I/O.

Linux中epoll的不同之处在于,在步骤4中,还没有I/O发生 - 它会在步骤4之后提升第1步,如果你确切知道你需要的话,那就是"向后".

编写了大量的嵌入式,桌面和服务器操作系统之后,我可以说这种异步I/O模型对于某些类型的程序来说非常自然.它还具有非常高的吞吐量和低开销.我认为这是Linux I/O模型在API级别上仍然存在的真正缺点之一.

linux posix asynchronous overlapped-io

25
推荐指数
3
解决办法
1万
查看次数

标签 统计

asynchronous ×1

linux ×1

overlapped-io ×1

posix ×1