【发布时间】:2017-07-05 15:03:35
【问题描述】:
Linux 内核在同一个套接字上处理 UDP 发送和接收的独立性如何?我的用例是一个工作线程在(最多)1000 个套接字上发送 UDP 测试流量,并在另一个工作线程中接收 UDP 回复。接收器将是一个 epoll 循环,它还接收套接字错误队列上的硬件发送和接收时间戳。
澄清一下,在执行 sendmsg() 系统调用时,这会在同一套接字上接收的接收线程上暂时阻塞(或生成 EAGAIN/EWOULDBLOCK)吗? (即如果发送和接收恰好在时间上重叠)所有套接字都设置为非阻塞模式。
另一个问题是内核中锁定的粒度 - 如果我使用 sendmmsg/recvmmsg 发送和接收,该套接字的锁定是每个 sendmmsg 锁定一次,还是每个 sendmmsg 中的 UDP 数据报锁定一次?
更新:我查看了 Linux 内核中 sendmmsg 的原始补丁,似乎主要的好处是避免了用户内核空间的多次转换。如果完成了任何锁定,它可能是在对 __sys_sendmsg 的单独调用中完成的: https://lwn.net/Articles/441169/
【问题讨论】:
-
不得不说,看标题的时候没想到这么好的问题。
-
考虑到 UDP 是多么微不足道,如果 UDP 发送会干扰 UDP 接收,我会感到非常惊讶。对于 TCP 来说,隐藏的 ACK 是一对发送和接收,而 UDP 只不过是 IP 加上一个端口号。
-
@MSalters:我同意,发送和接收是相当独立的。如果我有时间,我会深入研究我更新的内核存储库,看看是否能找到更多信息。
-
@MSalters 快速浏览一下 net/ipv4/udp.c 可以看出,对于非阻塞情况(用于 udp 发送)有一个快速、无锁的路径。我对内核不够精通,无法确定这是否意味着对于普通的 UDP 数据包根本没有锁定。
标签: c++ linux multithreading sockets linux-kernel