UDP以不同的线程发送和接收

UDP send and receive in different threads

本文关键字:线程 UDP      更新时间:2023-10-16

UDP的处理在Linux内核中的同一插座上发送和接收如何独立?我拥有的用例是一个工人线程,在(最多)1000个插座上发送UDP测试流量,并在另一个工作人员线程中接收UDP答复。接收器将是一个epoll循环,还接收硬件发送和接收套接字错误队列的时间戳。

要澄清,在执行sendmsg()syscall时,是否会暂时阻止(或在同一套接字接收的接收器线程上生成eagain/ewoldblock)?(即,如果发送和接收到时间重叠的情况下)将所有插座设置为非阻滞模式。

另一个问题是锁定内核的粒度 - 如果我使用sendmmsg/recvMmsg发送和接收,是每个sendmmsg一次锁定插座的锁定,或者在sendmmsg中使用一次udp datagram?

更新:我查看了Linux内核中的SendMMSG的原始补丁,似乎主要好处是避免了多个过渡用户内核空间。如果完成了任何锁定,则可能在__SYS_SENDMSG的单个呼叫中完成。https://lwn.net/articles/441169/

每个系统调用都是独立的。因此,就您不涉及每个过程内核数据而言,两者都会独立运行而不会互相打扰。

另一个不同的事情是内核与与同一inode相关的系统调用(在这种情况下,分配给您用于通信的套接字的虚拟节点)以序列化并对文件系统进行原子调用,而内核通常确实可以。在整个系统调用期间的一个inode锁(是读,写或ioctl系统调用),代表整个系统调用(即使您执行唯一的写入调用以编写千亿个字节,inode也会在执行过程中被阻止整个系统调用)

在TCP-IP堆栈中,这是在套接字级别进行的,并且在您的情况下由特定的AF_INET套接字类软件控制。由于UDP的涉及,发送数据包或接收并不影响需要锁定的共享资源,但是您必须查看UDP实现(或套接字级别),以查看是否完成了一些锁定以及粒度是什么。通常,如果是锁,则应仅在UDP缓冲区的加载/卸载期间使用(通常在UDP中没有缓冲区,因为插座和网卡驱动程序足以提供足够的缓冲资源。