Linux内核中同一个套接字上UDP发送和接收的处理有多独立?我的用例是一个工作线程在(最多)1000个套接字上发送UDP测试流量,并在另一个工作线程中接收UDP回复。接收器将是一个epoll循环,它还接收硬件发送和接收套接字错误队列上的时间戳。
为了澄清一下,在执行sendmsg()系统调用时,这是否会在接收器线程上临时阻塞(或生成EAGAIN / EWOULDBLOCK)? (即如果发送和接收在时间上发生重叠)所有套接字都设置为非阻塞模式。
另一个问题是内核中的锁定粒度 - 如果我使用sendmmsg / recvmmsg发送和接收,是对每个sendmmsg锁定一次的套接字的锁定,还是sendmmsg中每个UDP数据报锁定一次?
更新:我看了一下Linux内核中sendmmsg的原始补丁,看来主要的好处是避免了多个转换用户内核空间。如果进行了任何锁定,则可能是在__sys_sendmsg的单个调用中完成的: https://lwn.net/Articles/441169/
答案 0 :(得分:0)
每个系统调用都与线程无关。因此,只要您不涉及每个进程内核数据,两者都将独立运行而不会相互干扰。
另一个不同的是内核对与同一inode相关的系统调用所做的事情(在这种情况下,分配给用于通信的套接字的虚拟节点)为了序列化并对文件系统进行原子调用,内核通常会这样做整个系统调用期间的一个inode锁(这是一个读,写或ioctl系统调用)代表整个系统调用(即使你执行一个唯一的写调用来写一个数字的字节,inode在执行期间被阻塞)整个系统电话)
在tcp-ip堆栈中,这是在套接字级别进行的,并且在特定情况下由特定的AF_INET
套接字类软件控制。就udp而言,发送数据包或接收不会影响需要锁定的共享资源,但是您必须查看您的udp实现(或套接字级别)以查看是否已完成某些锁定并且粒度是多少。通常情况下,应该只在加载/卸载udp缓冲区时使用锁(通常在udp中没有缓冲区,因为套接字和网卡驱动程序足以提供足够的缓冲区资源。 / p>