boost.asio 和文件 i/o 有啥关系?

Posted

技术标签:

【中文标题】boost.asio 和文件 i/o 有啥关系?【英文标题】:What's the deal with boost.asio and file i/o?boost.asio 和文件 i/o 有什么关系? 【发布时间】:2010-09-27 13:40:34 【问题描述】:

我注意到 boost.asio 有很多涉及套接字、串行端口和各种非文件示例的示例。谷歌并没有真正为我提供很多关于 asio 是否是执行异步文件 i/o 的好方法或有效方法。

我有大量数据要异步写入磁盘。这可以通过 Windows(我的平台)中的本机重叠 io 来完成,但我希望有一个独立于平台的解决方案。

我很好奇

    boost.asio 支持任何类型的文件 boost.asio 文件支持对于日常文件 i/o 来说已经足够成熟了 是否会添加文件支持?前景如何?

【问题讨论】:

一般的想法是文件应该在大部分时间都在手边读取。插座通常相距数千英里,有时永远无法完成。如果您需要通常的异步文件,因为您正在创建一个 GUI 界面。通过让工作线程在后台处理阻塞文件 I/O 来处理它。 【参考方案1】:

boost.asio 是否支持任何类型的文件?

从(我认为)Boost 1.36(包含 Asio 1.2.0)开始,您可以使用 [boost::asio::]windows::stream_handle 或 windows::random_access_handle 来包装 HANDLE 并执行异步读写方法在内部使用 OVERLAPPED 结构。

User Lazin 还提到 boost::asio::windows::random_access_handle 可用于异步操作(例如命名管道,也包括文件)。

对于日常文件 i/o 的 boost.asio 文件支持是否足够成熟?

由于 Boost.Asio 本身现在已经被广泛使用,并且实现在内部使用重叠 IO,我会说是的。

是否会添加文件支持?前景如何?

由于在Asio 网站上没有找到路线图,我会说 Boost.Asio 不会为此功能添加新的内容。尽管贡献者总是有机会向 Boost.Asio 添加代码和类。也许您甚至可以自己贡献缺失的部分! :-)

【讨论】:

谢谢,这可能很有用。你知道有什么计划来实现一个独立于平台的异步文件吗? 我不知道,抱歉。有一个 posix::stream_descriptor 类对 posix 句柄做同样的事情,所以至少可以为这两种方法编写一个包装器。 我相信 posix::stream_descriptor 不适用于常规文件。见boost.org/doc/libs/1_43_0/doc/html/boost_asio/overview/posix/…。 我前段时间在 boost.asio.users 列表上也读到过;看来 Boost.Asio 没有办法...thread.gmane.org/gmane.comp.lib.boost.asio.user/4043【参考方案2】:

Linux 上的 boost::asio 文件 i/o

在 Linux 上,asio 使用epoll 机制来检测套接字/文件描述符是否准备好进行读/写。如果您尝试在 Linux 上的常规文件上使用 vanilla asio,您将收到“不允许操作”异常,因为 epoll does not support regular files on Linux。

解决方法是将 asio 配置为在 Linux 上使用 select 机制。您可以通过定义BOOST_ASIO_DISABLE_EPOLL 来做到这一点。如果您使用大量打开的套接字,这里的权衡是select tends to be slower than epoll。定期使用open() 打开文件,然后将文件描述符传递给boost::asio::posix::stream_descriptor

Windows 上的 boost::asio 文件 i/o

在 Windows 上,您可以使用 boost::asio::windows::object_handle 包装从文件操作创建的 Handle。见example。

【讨论】:

在FreeBSD上asio默认使用kqueue来复用系统对象 select 不会根据bugreport you listed “对文件系统文件进行轮询/选择没有任何意义。” 和this comment i>” 常规文件总是可读的,它们也总是可写的。这在相关的 POSIX 规范中有明确说明。我不能强调这一点。将常规文件置于非阻塞状态除了更改文件标志。”【参考方案3】:

boost::asio::windows::random_access_handle 是最简单的方法,如果你需要一些高级的东西,例如异步 LockFileEx 或其他东西,你可以扩展 asio,添加你自己的异步事件。 example

【讨论】:

【参考方案4】:

ASIO 在支持良好的 Windows 上支持重叠 I/O。在 Unix 上,这个想法停滞不前,原因是:

文件通常位于同一物理设备上,最好按顺序访问它们。 文件请求通常会很快完成,因为它们在物理上就在附近。 文件通常对于完成程序的基本操作至关重要(例如,必须在进一步初始化之前读取其配置文件)

一个常见的例外是直接向套接字提供文件。这是一种常见的特殊情况,以至于 Linux 有一个 内核函数 可以为您处理这个问题。再次否定使用异步文件 I/O 的原因。

简而言之:ASIO 似乎反映了底层 OS 设计理念,大多数 Unix 开发人员忽略了重叠 I/O,因此该平台不支持它。

【讨论】:

出于好奇,您指的是什么内核函数? 没关系,我相信它的 sendfile 也可以发送到套接字:man7.org/linux/man-pages/man2/sendfile.2.html 需要解决的问题是:没有为每次挂起的文件传输分配线程栈。 sendfile 如何解决这个问题?鉴于 Web 服务器 99% 的 i/o 将是静态内容,在客户端受到限制,这不是一个很大的问题吗?【参考方案5】:

io_uring 改变了一切。 asio 现在支持异步文件读/写。 查看发布说明:asio 1.21.0 releases notes

【讨论】:

【参考方案6】:

Linux 有一个 asio 库,在这项工作中使用起来并不比 Windows API 难(我已经使用过)。两组操作系统都实现了相同的概念架构。它们在与编写一个好的库相关的细节上有所不同,但并没有到您不能为两种操作系统平台(我已经使用过一个)提供通用接口的地步。

基本上,所有类型的异步文件 I/O 都遵循“Fry Cook”架构。这就是我在读取操作上下文中的意思:我(处理线程)走到快餐柜台(OS)并要求一个芝士汉堡(一些数据)。它给了我一份订单票(一些数据结构)的副本,并在后面向厨师(内核和文件系统)发出一张票来烹饪我的汉堡。然后我坐下来或看手机(做其他工作)。后来,有人宣布我的汉堡准备好了(给处理线程的信号),我收集了我的食物(读取缓冲区)。

【讨论】:

究竟谁是 LINUX asio Web 服务器上的炒菜厨师?

以上是关于boost.asio 和文件 i/o 有啥关系?的主要内容,如果未能解决你的问题,请参考以下文章

Boost.Asio的使用技巧

websocketpp 和 boost.asio 有啥区别?

Boost::Asio入门剖析

Boost Asio总结(15)class basic_stream_socket

boost--asio

C++ Boost Asio 简单聊天教程