本文主要是介绍Linux: network: 内核里的一个隐匿陷阱 inet_csk_bind_conflict,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
最近和同事一块看一个问题,内核版本4.18。总结如下:
说有一个函数是inet_csk_bind_conflict,如果只是普通socket的应用,socket数量不多,可能用不到这个函数,或者用到了也感知不到。
但是最近就遇到了一个问题,说应用在一个端口建立起来了tons of sockets,来对外链接,
这个时候就有可能出现问题,而且使用的这个端口,还是一个临时的端口,在net.ipv4.ip_local_port_range之内的一个临时端口。
应用本身对所建立的socket都会设置SO_REUSEADDR选项,通过内核代码走读,即使有很多的socket,也不会走到这个conflict的检查。
因为内核里相关的结构体里有一个标记为:inet_bind_bucket.fastreuse,如果这个端口上的所有的socket都是reuse,这个标记为就一直生效,这样就一直不走conflict函数,也就不会产生什么特别的影响。
但是有两个情况,会打破这种以为或者是默认的行为:
第一个是,如果有一个socket的设置SO_REUSEADDR函数调用失败,setsockopt,而且继续后面的bind操作;
第二个是,其他应用通过系统分配临时端口,也没有设置SO_REUSEADDR;
这两种情况都会将这个hash bucket表的快速reuse的标记污染,也就是必须走conflict,导致inet_csk_bind_conflict函数占用CPU非常高。
这种问题非常难于发现,除非是碰巧有人用了这个相同的端口,而且没有设置REUSE。再就是CPU的使用率需要特别的显眼,才能注意到问题的存在。
后续5.19版本上对这个conflict函数有增加,多加一个hash bucket,关联IP地址。算是可以缓解这种问题。
这篇关于Linux: network: 内核里的一个隐匿陷阱 inet_csk_bind_conflict的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!