首页 > 其他 > 详细

相同端口的UDP套接字数量过多导致软中断占用CPU利用率高的原因分析

时间:2014-03-07 21:46:16      阅读:1160      评论:0      收藏:0      [点我收藏+]
  导致出现很多相同端口的UDP套接字的原因有两点:
    1)在reload的时候,调用shutdown()而不是close()来关闭UDP套接字。shutdown()是用来关闭连接,但是文件描述符还是会存在。UDP协议并没有提供shutdown接口(参见udp_prot),所以调用shutdown()并没有真的关闭套接字,而且reload的次数太多
    2)设置了SO_REUSEADDR选项。如果没有设置这个选项,在bind的时候就会报错,漏关或者使用shutdown()关闭的错误就很容易发现。UDP套接字没有TIME_WAIT状态,而且要使用的UDP套接字数量不多,所以没有必要设置该选项。
  现在我们结合内核代码来分析一下为什么相同端口的UDP套接字数量过多导致软中断占用CPU利用率高。
  UDP套接字在绑定端口后才会添加到udp_table哈希表中,解决冲突使用的是“拉链法”,放置的槽位是由绑定的端口决定的(参见不考虑CONFIG_NET_NS选项)。所以绑定到相同端口的套接字会放置到同一个槽位的链表中,这种套接字数量越多,链表就越长。
  在接收到UDP协议的SKB包后,会调用__udp4_lib_lookup()函数来查找对应的UDP套接字,相关代码如下所示:
static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
        __be16 sport, __be32 daddr, __be16 dport,
        int dif, struct udp_table *udptable)
{
    struct sock *sk, *result;
    struct hlist_nulls_node *node;
    unsigned short hnum = ntohs(dport);
    unsigned int hash = udp_hashfn(net, hnum);
    struct udp_hslot *hslot = &udptable->hash[hash];
    int score, badness;

    rcu_read_lock();
begin:
    result = NULL;
    badness = -1;
    sk_nulls_for_each_rcu(sk, node, &hslot->head) {
        score = compute_score(sk, net, saddr, hnum, sport,
                      daddr, dport, dif);
        if (score > badness) {
            result = sk;
            badness = score;
        }
    }
    ......
}
  首先根据SKB包的目的端口号来查找要遍历的链表,然后通过sk_nulls_for_each_rcu宏来遍历链表上的所有套接字。我们可以看到,不管这个链表上有多少个套接字,都要从头到尾遍历一遍。如果遍历的链表越长,耗费的时间就越多,这个处理是在软中断的上下文中,因此会导致软中断占用CPU利用率高。
  下面是使用perf top命令看到的结果(可以清楚地看到__udp4_lib_lookup会成为热点,在同等压力下是不会出现的):
bubuko.com,布布扣

相同端口的UDP套接字数量过多导致软中断占用CPU利用率高的原因分析,布布扣,bubuko.com

相同端口的UDP套接字数量过多导致软中断占用CPU利用率高的原因分析

原文:http://blog.csdn.net/justlinux2010/article/details/20727135

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!