gpt4 book ai didi

c - sendmsg/recvmsg 中的部分读/写问题

转载 作者:太空狗 更新时间:2023-10-29 15:40:12 30 4
gpt4 key购买 nike

我正在编写一个程序,使用 sendmsg 在两个进程之间传递文件描述符和 recvmsg通过域套接字。对于发送文件描述符,附加数据包含在 msghdr.msg_iov 中和 msghdr.msg_iolen .然而,我被告知类似于正常readwrite系统调用,sendmsgrecvmsg也有部分读/写问题。在这种情况下,是否会为每个部分数据自动复制辅助字段中的数据?我问这个是因为我的实现需要非阻塞机制。让我用下面的例子来详细说明一下

发件人:发送msghdr包含 fd 的数据在辅助领域和K msg_iov 中的字节数

接收方:(1) 部分读取,K1字节 (2) 部分读取,K-K1字节

现在如上面的例子,我实际上应该在所有数据到达时处理步骤(2)之后的数据。在这种情况下,我还能正确提取 fd 吗?来自辅助领域?还是只出现在第一次部分阅读中?

最佳答案

通过快速查看内核源代码(linux,但见下文),我相信由您来确保辅助数据只发送一次。也就是说,在非阻塞模式下,如果接收套接字中没有空间,您将返回EAGAIN/EWOULDBLOCK,并且不会发送数据和辅助数据。但是如果接收方有一些空间,那么数据的初始部分将被发送,辅助数据也将被发送。然后您会收到一个返回字节数,指示已部分发送,但辅助数据已发送。

当您尝试发送消息的其余部分时,您需要注意这一点,因为内核不会维护您之前发送的部分缓冲区的内存,后续缓冲区在逻辑上是连续的(真的不可能——你可能会发送完全不同的数据)。因此,如果您只是为后续缓冲区部分提供相同的辅助数据,我相信内核会很乐意为您的后续缓冲区部分再次提供辅助数据。这可能会导致接收方出现重复的文件描述符(如果您不避免的话,您可能会忽略关闭它们)。

现在,如果您在发送方处于阻塞模式,并且传输被分成多个部分,则辅助数据将仅发送一次 - 第一个缓冲区部分,因为整个缓冲区的发送仍在内核控制。

因此,在接收端,如果您没有收到完整的逻辑消息,您需要注意辅助数据伴随着接收到的数据的第一 block 。

我相信此行为与@Klas-Lindbäck ( https://unix.stackexchange.com/questions/185011/what-happens-with-unix-stream-ancillary-data-on-partial-reads) 给出的 stackexchange 引用中报告的行为一致。 (虽然这个问题没有涉及非阻塞模式。)

这个答案是特定于 linux 的。因此,在其他操作系统上的结果当然可能会略有不同,尽管我很难看出它们有何显着差异并仍然保持理智的语义。内核无法合理地维护之前发送的内容的内存,并且 sendmsg 原型(prototype)不允许它覆盖用户的 msghdr 以反射(reflect) msg_control部分已经发送。

关于c - sendmsg/recvmsg 中的部分读/写问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38431713/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com