我正在学习UNIX域套接字并尝试一些客户端服务器程序。 我正在使用SOCK_DGRAM套接字系列。
我的疑问是:
所以我的电话:
sendto(send_thread_socket, (void*)argData, sizeof(*argData), 0, (struct sockaddr *)&dpdkServer, sizeof(struct sockaddr_un))
会将缓冲区复制到内核空间缓冲区,还是直接复制到接收进程的用户空间缓冲区。 由于UNIX套接字在文件系统命名空间上工作,我认为它不应该做一个缓冲区的副本。
比方说,我使用相同的sendto()调用,但接收方不保证及时收集数据,我可以有一个发送超时。
sendto
函数在返回之前不等待接收者接收数据。 所以是的,为了达到这个目的,数据将被复制到内核拥有的缓冲区中,然后由接收过程再次复制出来。
原因:如果情况并非如此,那么两个进程交换消息或多或少是不可能的。 如果进程P2试图发送消息到进程P2,它将不会成功,直到P2被read
。 如果P2正在尝试向P1发送一个消息,在P1 read
之前它不能成功。 但P1正在等待阻塞呼叫sendto
。 这些进程将会陷入僵局。
内核缓冲是解决这个问题的方法。
Ben本来就很好,但是这里还有其他的东西。
让我们假设我们将允许在域套接字上进行零复制,并让我们说我们允许sendto()阻塞,直到recvfrom()被调用以离开内核缓冲区。 我在内核中看到了一个令人头痛的问题 – 我们不得不将这个页面翻译成接收过程(这意味着最好是整个页面),而且,如果一切都没有执行完毕,您无论如何都会得到副本。 发件人无法调用free()或重用缓冲区,因为这会强制使用pagefault-copy。
丑,只是丑。 没有人会费心写这些难以使用的东西。 唯一足够大的unix域套接字的用户是X,X不保证消息的大小。