Jes*_*Jes 5 c sockets unix-socket
我正在编写一个程序,该程序使用sendmsg
和recvmsg
通过域套接字在两个进程之间传递文件描述符。为了发送文件描述符,附加数据包含在msghdr.msg_iov
和 中msghdr.msg_iolen
。但是,我被告知类似于正常read
和write
系统调用,sendmsg
并且recvmsg
也有部分读/写问题。在这种情况下,是否会为每个部分数据自动复制辅助字段中的数据?我问这个是因为我的实现需要非阻塞机制。让我用下面的例子来详细说明一下
发送方:发送msghdr
包含fd
辅助字段中的 a和K
字节中的数据msg_iov
接收器:(1) 部分读取,K1
字节 (2) 部分读取,K-K1
字节
现在作为上面的例子,当所有数据到达时,我应该在步骤(2)之后实际处理数据。在这种情况下,我还能fd
从辅助字段中正确提取吗?还是只出现在第一部分阅读中?
快速浏览一下内核源代码(Linux,但请参见下文),我相信您需要确保辅助数据仅发送一次。也就是说,在非阻塞模式下,如果接收套接字没有空间,就会返回EAGAIN
/ EWOULDBLOCK
,并且既不会发送数据,也不会发送辅助数据。但如果接收端有一些空间,那么数据的初始部分将被发送,辅助数据也将被发送。然后,您将收到一个返回字节计数,指示部分发送,但辅助数据将已发送。
当您尝试发送消息的其余部分时,您需要意识到这一点,因为内核不会保留您之前发送的部分缓冲区的内存,而后续缓冲区在逻辑上是连续的(实际上不可能——就其所知而言,您可能会发送完全不同的数据)。因此,如果您只是为后续缓冲区部分提供相同的辅助数据,我相信内核会很乐意再次通过后续缓冲区部分传递辅助数据。如果您不避免的话,这可能会导致接收方出现重复的文件描述符(您可能会忽略关闭它们,因为您不会期望它们)。
\n\n现在,如果您在发送端处于阻塞模式,并且传输被分成多个部分,则辅助数据将仅发送一次 - 使用第一个缓冲区部分,因为整个缓冲区的发送仍然在内核控制范围内。
\n\n因此,在接收方,如果您没有收到整个逻辑消息,则需要注意辅助数据伴随着接收到的第一块数据。
\n\n我相信这种行为与 @Klas-Lindb\xc3\xa4ck 给出的 stackexchange 参考中报告的行为一致(https://unix.stackexchange.com/questions/185011/what-happens-with-unix-stream-ancillary-部分读取数据)。(这个问题并未涉及非阻塞模式。)
\n\n这个答案是针对linux的。因此,结果在其他操作系统上当然可能会略有不同,尽管我很难看出它们如何在显着不同的情况下仍然保持理智的语义。内核无法合理地维护先前发送的内容的内存,并且sendmsg
原型不允许它覆盖用户的内存msghdr
以反映该msg_control
部分已经发送。
归档时间: |
|
查看次数: |
1754 次 |
最近记录: |