小编Tar*_* AC的帖子

在高负载下recvmmsg/recv/recvfrom块

我们在Centos 6上有一个应用程序,它调用recvmmsg()多播地址一次读取1024个UDP数据包.当我们在同一个盒子上运行这个应用程序的多个实例(都收听相同的流量)时,有时这个调用将阻塞多秒,尽管套接字是非阻塞的,并且传入MSG_DONTWAIT.它在所有其他情况下都能正常工作,但在高负载(50MB/s)下会冻结.当应用程序阻塞时,我们落后于UDP流量而无法恢复.使用RR调度程序作为高优先级运行该进程以避免来自其他进程的干扰.我们尝试切换到recvfrom(),并recv()在for循环也具有相同的结果.

我们在内核源代码中可以看到的唯一可以阻止它的是spin_lock_irqsave()队列锁定__skb_try_recv_datagram().但我不知道在什么情况下会出现问题,或者为了防止阻塞该怎么做,或者这是否真的是问题.

我不确定下一步该在哪里,所以任何指针都会受到赞赏.

创建了一个非常简单的程序,可以在我们看到的一个服务器上复制它(没有粘贴接口检索功能,但这里不应该相关,请告诉我你是否需要它).

recv()示例:

int main(){
    int fd = socket(AF_INET,SOCK_DGRAM,0);
    int flags = fcntl(fd,F_GETFL,0);
    fcntl(fd,F_SETFL, flags | O_NONBLOCK);
    int reuse = 1;
    setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&reuse,sizeof(reuse));
    struct sockaddr_in sockaddr;
    sockaddr.sin_port = htons(4755);
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    if(bind(fd,(struct sockaddr*)&sockaddr,sizeof(sockaddr)) < 0){ 
      printf("Failed to bind.\n");
      return 1;
    }

    in_addr_t interface;
    if(!getInterface("192.168.15.255",&interface)){
      printf("Failed to get interface.\n");
      return 1;
    }
    struct ip_mreq imr;
    memset(&imr,0,sizeof(imr));
    imr.imr_multiaddr.s_addr = inet_addr("239.255.61.255");
    imr.imr_interface.s_addr = interface;
    if(!IN_MULTICAST(htonl(imr.imr_multiaddr.s_addr))){ …
Run Code Online (Sandbox Code Playgroud)

c sockets centos6 recvfrom recvmmsg

5
推荐指数
0
解决办法
172
查看次数

标签 统计

c ×1

centos6 ×1

recvfrom ×1

recvmmsg ×1

sockets ×1