boost.asio和文件I/O有什么关系?

52

我注意到boost.asio有很多涉及套接字、串口和各种非文件示例的例子。谷歌并没有给我带来太多关于asio是否适用于异步文件i/o的信息。

我有大量数据想要异步写入磁盘。这可以通过Windows本地重叠I/O完成(我的平台),但我更愿意拥有一个平台无关的解决方案。

我想知道:

  1. boost.asio是否支持文件操作?
  2. boost.asio文件操作是否成熟,适合日常文件i/o?
  3. 是否会添加文件操作支持?对此的展望如何?

1
总的想法是文件大部分时间都应该被即时读取。而套接字通常位于数千英里之外,有时甚至永远不会完成连接。如果您需要异步文件,那通常是因为您正在创建GUI界面。通过让工作线程在后台处理阻塞的文件I/O来解决这个问题。 - unixman83
相关:https://dev59.com/gFIH5IYBdhLWcg3wb9w6 - janekb04
7个回答

20

boost.asio 是否支持文件操作?

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

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

boost.asio 的文件支持是否足够成熟以应对日常文件 I/O?

由于 Boost.Asio 本身已被广泛使用,且实现内部使用 overlapped IO,因此我认为是的。

是否会添加文件支持?展望如何?

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


3
谢谢,这可能会很有用。你知道是否有任何计划实现平台无关的异步文件吗? - Doug T.
不是我知道的,抱歉。有一个posix :: stream_descriptor类可以为posix句柄执行相同的操作,因此至少可以编写两种方法的包装器。 - vividos
1
我相信posix :: stream_descriptor不适用于常规文件。请参见http://www.boost.org/doc/libs/1_43_0/doc/html/boost_asio/overview/posix/stream_descriptor.html。 - villintehaspam
我之前也在boost.asio.users列表上读到过这个问题,看起来使用Boost.Asio没有办法解决... http://thread.gmane.org/gmane.comp.lib.boost.asio.user/4043 - vividos
文件支持已添加。https://dev59.com/ZnRC5IYBdhLWcg3wMeHf#73311047 - MHebes

7

boost::asio在Linux上的文件I/O

在Linux上,asio使用epoll机制来检测套接字/文件描述符是否准备好进行读写操作。如果您尝试在Linux上的普通文件上使用原始asio,则会出现“操作不允许”的异常,因为epoll在Linux上不支持普通文件

解决方法是在Linux上配置asio使用select机制。您可以通过定义BOOST_ASIO_DISABLE_EPOLL来实现此操作。这里的权衡是,如果您正在处理大量打开的套接字,则select往往比epoll慢。使用open()定期打开文件,然后将文件描述符传递给boost::asio::posix::stream_descriptor

Windows上的boost::asio文件I/O

在Windows上,您可以使用boost::asio::windows::object_handle来封装从文件操作创建的Handle。请参见示例

1
在FreeBSD上,asio默认使用kqueue来复用系统对象。 - Slav
1
根据您列出的错误报告此评论select对文件系统文件不会有任何有用的作用。*"从文件系统文件上的轮询/选择中没有返回任何有意义的内容。",并且"常规文件始终可读,也始终可写。这在相关的POSIX规范中明确说明。我再次强调,将常规文件设置为非阻塞除了更改文件标志中的一位之外,绝对没有任何影响。"* - Zulan

6

io_uring已经改变了一切。
现在,asio支持异步文件读写。
请查看发布说明:
asio 1.21.0发布说明


你知道asio和uring是否支持写入多个缓冲区吗?liburing本身支持,但不确定asio实现是否支持。 - Jacko

5

如果您需要进行高级操作,例如异步LockFileEx或其他操作,boost::asio::windows::random_access_handle是最简单的方法。如果您需要扩展asio并添加自己的异步事件,可以参考示例


4

ASIO支持在Windows上进行重叠I/O,支持良好。在Unix系统中,由于以下原因,这个想法已经停滞不前:

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

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

简而言之:ASIO似乎反映了底层操作系统设计哲学,大多数Unix开发人员忽略了重叠I/O,因此在该平台上不支持。


2
你好奇的是,你指的是哪个内核函数? - Riot
1
没关系,我相信sendfile也能够发送到套接字:http://man7.org/linux/man-pages/man2/sendfile.2.html - Riot
需要解决的问题是:对于每个挂起的文件传输未分配线程堆栈。sendfile如何解决这个问题?鉴于Web服务器99%的I / O将是静态内容,在客户端进行限制,这不是一个相当大的问题吗? - Robin Davies

1
Asio 1.21似乎已经添加了内置的文件系统支持。例如,现在存在asio::stream_file,具有您期望的所有异步方法。

0

Linux有一个asio库,用于这项工作不比Windows API更难使用(我已经使用过了)。两个操作系统实现了相同的概念架构。它们在编写良好的库时有所不同的细节,但不至于不能在两个操作系统平台上拥有共同的接口(我已经使用了一个)。

基本上,所有类型的异步文件I/O都遵循“炸薯条工”体系结构。下面是在读取操作的上下文中我指的意思:我(处理线程)走到快餐柜台(OS)前,要求一份芝士汉堡(一些数据)。它给了我一份我的订单票据的拷贝(一些数据结构),并在后面开了一个票给炸薯条师傅(内核和文件系统)来做我的汉堡。然后我去坐下或看手机(做其他工作)。稍后,有人宣布我的汉堡已经准备好了(处理线程的信号),我拿到我的食物(读取缓冲区)。


那么,在 LINUX asio web 服务器上,到底是谁担任炸薯条的厨师? - Robin Davies

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接