我注意到boost.asio有很多涉及套接字、串口和各种非文件示例的例子。谷歌并没有给我带来太多关于asio是否适用于异步文件i/o的信息。
我有大量数据想要异步写入磁盘。这可以通过Windows本地重叠I/O完成(我的平台),但我更愿意拥有一个平台无关的解决方案。
我想知道:
- boost.asio是否支持文件操作?
- boost.asio文件操作是否成熟,适合日常文件i/o?
- 是否会添加文件操作支持?对此的展望如何?
我注意到boost.asio有很多涉及套接字、串口和各种非文件示例的例子。谷歌并没有给我带来太多关于asio是否适用于异步文件i/o的信息。
我有大量数据想要异步写入磁盘。这可以通过Windows本地重叠I/O完成(我的平台),但我更愿意拥有一个平台无关的解决方案。
我想知道:
从 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 本身已被广泛使用,且实现内部使用 overlapped IO,因此我认为是的。
由于 Asio 网站上没有找到路线图, 我认为 Boost.Asio 不会再针对此功能进行新的添加。尽管总有贡献者向 Boost.Asio 添加代码和类,也许您自己甚至可以贡献缺失的部分!:-)
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
。请参见示例。io_uring已经改变了一切。
现在,asio支持异步文件读写。
请查看发布说明:
asio 1.21.0发布说明
如果您需要进行高级操作,例如异步LockFileEx或其他操作,boost::asio::windows::random_access_handle是最简单的方法。如果您需要扩展asio并添加自己的异步事件,可以参考示例。
ASIO支持在Windows上进行重叠I/O,支持良好。在Unix系统中,由于以下原因,这个想法已经停滞不前:
唯一的共同例外是直接向套接字提供文件。这是一个如此常见的特殊情况,以至于Linux有一个内核函数为您处理这个问题。再次否定使用异步文件I/O的原因。
简而言之:ASIO似乎反映了底层操作系统设计哲学,大多数Unix开发人员忽略了重叠I/O,因此在该平台上不支持。
Linux有一个asio库,用于这项工作不比Windows API更难使用(我已经使用过了)。两个操作系统实现了相同的概念架构。它们在编写良好的库时有所不同的细节,但不至于不能在两个操作系统平台上拥有共同的接口(我已经使用了一个)。
基本上,所有类型的异步文件I/O都遵循“炸薯条工”体系结构。下面是在读取操作的上下文中我指的意思:我(处理线程)走到快餐柜台(OS)前,要求一份芝士汉堡(一些数据)。它给了我一份我的订单票据的拷贝(一些数据结构),并在后面开了一个票给炸薯条师傅(内核和文件系统)来做我的汉堡。然后我去坐下或看手机(做其他工作)。稍后,有人宣布我的汉堡已经准备好了(处理线程的信号),我拿到我的食物(读取缓冲区)。