【问题标题】: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 来完成,但我希望有一个独立于平台的解决方案。

我很好奇

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

【问题讨论】:

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

标签: c++ boost file-io boost-asio


【解决方案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 添加代码和类。也许您甚至可以自己贡献缺失的部分! :-)

【讨论】:

【解决方案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 服务器上的炒菜厨师?
      猜你喜欢
      • 1970-01-01
      • 2022-07-25
      • 2020-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-17
      • 2011-08-11
      • 1970-01-01
      相关资源
      最近更新 更多