【问题标题】:linux socket: lifetime of ancillary data for sendmsglinux socket:sendmsg的辅助数据的生命周期
【发布时间】:2018-09-13 14:41:18
【问题描述】:

我使用 cmsg 在 linux socket tx 上激活时间戳。

ssize_t sendWithOptions
(int sd, std::vector<uint8_t> &payload, uint32_t destIP, int flags)
{
    msghdr msg { };
    .... // filling standard
    std::array<uint8_t, CMSG_LEN(sizeof(__u32))> buf;
    msg.msg_control = buf.data();
    msg.msg_controlen = buf.size();

    auto cmsg { CMSG_FIRSTHDR ( &msg ) };
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SO_TIMESTAMPING;
    cmsg->cmsg_len = buf.size();

    *(reinterpret_cast<__u32>(CMSG_DATA (cmsg)) = static_cast<__u32>(flags);
    return sendmsg ( sd, &msg, MSG_DONTWAIT );
}

离开函数,“buf”会被自动销毁,但是sendmsg是否需要这个缓冲区才能活得更久? 我是否可以保证该函数在返回发送的字节数后不需要此缓冲区。

【问题讨论】:

    标签: linux sockets


    【解决方案1】:

    除了特定的接口外,一般情况下操作系统调用在完成后不依赖用户空间来维护影响其操作的数据结构。例外情况将在手册页中详细说明。

    尤其是sendmsg,您可以依靠调用立即完成——无论成功与否。因此,您可以使用动态分配的缓冲区,并在调用后立即销毁它。

    作为一个例外的示例,aio_write(2) 专门用于允许用户空间对将异步完成的写入操作进行排队。对于此调用,数据在可以成功写入之前不会被消耗。因此,在确认调用完成之前,您不得修改调用中提供的数据结构。手册页的NOTES 部分提到了该警告:

    ... 在写入操作进行时,不得更改控制块。在操作过程中不能访问正在写出的缓冲区,否则可能会出现未定义的结果。所涉及的内存区域必须保持有效。

    总结:查看系统调用的手册页。但大多数时候,您不必担心。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-09
      • 2015-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多