You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BOOST Asio:async_write_some与async_write选型及单写操作需求

解决方案

你的思路完全没问题,针对FunctionFS这类有单次写入语义要求的特殊文件,确实不能用asio::async_write,直接使用async_write_some的核心需求是可行的。

核心原理

Asio的posix::basic_stream_descriptor::async_write_some在处理缓冲区序列时,本质上是直接将整个序列传递给底层的writev(分散写)系统调用,不会主动拆分缓冲区序列去发起多次系统调用。只有当内核因资源限制等原因返回部分写入时,async_write_some才会返回实际写入的字节数——这完全符合你要的“仅当系统调用决定时才写入更少数据”的要求。

处理部分写入的场景

直接调用async_write_some可能出现数据未完全写入的情况,这时候需要你手动处理剩余数据的写入,但必须保证每次剩余数据的写入都作为独立的async_write_some调用,这样才能维持单次写入对应单次系统调用的语义。

以下是一个实现示例:

#include <asio/posix/basic_stream_descriptor.hpp>
#include <vector>

using namespace asio;

void do_write(posix::basic_stream_descriptor<>& stream, std::vector<const_buffer> buffers, std::size_t total_bytes) {
    stream.async_write_some(buffers, [&stream, buffers, total_bytes](std::error_code ec, std::size_t written) {
        if (ec) {
            // 这里处理写入错误,比如打印日志、触发错误回调等
            return;
        }

        if (written < total_bytes) {
            // 整理剩余的缓冲区,跳过已写入的部分
            auto buf_iter = buffer_sequence_begin(buffers);
            std::size_t skipped_bytes = 0;

            // 跳过已经完全写入的缓冲区
            while (skipped_bytes + buffer_size(*buf_iter) <= written) {
                skipped_bytes += buffer_size(*buf_iter);
                ++buf_iter;
            }

            std::vector<const_buffer> remaining_buffers;

            // 如果当前缓冲区有部分数据未写入,截取剩余部分
            if (skipped_bytes < written) {
                const auto& current_buf = *buf_iter;
                auto remaining_in_current = buffer_size(current_buf) - (written - skipped_bytes);
                remaining_buffers.emplace_back(
                    static_cast<const char*>(buffer_cast<const void*>(current_buf)) + (written - skipped_bytes),
                    remaining_in_current
                );
                ++buf_iter;
            }

            // 添加剩下的完整缓冲区
            remaining_buffers.insert(remaining_buffers.end(), buf_iter, buffer_sequence_end(buffers));

            // 发起下一次独立的写入调用
            do_write(stream, remaining_buffers, total_bytes - written);
        } else {
            // 全部数据写入完成,处理后续逻辑
        }
    });
}

为什么不能用asio::async_write

asio::async_write的设计逻辑是自动多次调用async_write_some,直到所有数据被写入完成——这会导致多次系统调用,而多次调用会被FunctionFS解析为多个独立的USB传输,破坏你需要的“单次写入对应单个USB传输”的语义,所以你的选择是正确的。

内容的提问来源于stack exchange,提问作者Johannes Schaub - litb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 10:00:58