嵌入式开发交流网论坛
标题:
Linux内核中reuseport的演进
[打印本页]
作者:
回头把L妖孽
时间:
2021-1-9 15:29
标题:
Linux内核中reuseport的演进
转自:187J3X1
选项在Linux 3.9被引入内核,在这之前也有一个很像的选项。
如果你不太清楚这两者的区别和联系,建议搜索 How do SO_REUSEADDR and SO_REUSEPORT differ?。
如果不想读,那么下面这一节算是为懒人准备的。
[attach]56819[/attach]
SO_REUSEADDR 与 SO_REUSEPORT 是什么?
TCP/UDP用唯一标识一个连接。
任何时候,两条连接的五元组都不能完全相同,否则当收到一个报文时,协议栈没办法判断它是属于哪个连接的。
五元组里,在创建socket时确定,和在时确定,和在时确定。
当然,和在一些时候并不需要显式使用,不过这不在本文的讨论范围里。
那么,如果对socket设置了和选项,它们什么时候起作用呢?
答案是,也就在确定和时。
不同操作系统内核对待和的行为有少许差异,但它们都源自BSD。
因此,接下来就以BSD的实现为标准进行说明。
SO_REUSEADDR
假设我现在需要将绑定到,将绑定到(不考虑或者,因为表示让内核自动分配端口,一定不会冲突)。
如果,那么无论和的关系如何,两个都会成功。但如果,那么结果会是下面这样:
第一列表示是否设置,最后一列表示后绑定的socket是否能绑定成功。
:这里设置的对象是指后绑定的socket(也就是说不关心前一个是否设置)
可以看出,BSD的实现中可以让一个使用通配地址(0.0.0.0),一个使用指定地址(192.168.1.0)的socket同时绑定成功。
还有一种应用情景:在中存在一个状态,它是指主动关闭的一端最后停留的阶段。
假设绑定到,在完成TCP通信后主动使用进入,此时,如果也去绑定,那么同样会得到 错误,但如果设置了,那么就可以绑定成功。
SO_REUSEPORT
如果理解了,那么就很好理解了,它让两个socket可以绑定完全相同的。
提醒一下,以上的结果都是BSD的结果,Linux内核有一些不一样的地方,具体表现为
3.9版本支持,作为Server的TCP Socket一旦绑定到了具体的端口,启动了LISTEN,即使它之前设置过, 也不会生效。这一点Linux比BSD更加严格
3.9版本之前,作为Client的Socket,选项具有BSD中的的效果。这一点Linux又比BSD更加宽松。
Linux中reuseport的演进
Linux
下面看看具体是怎么做的: 内核socket使用字段表示是否设置了
表示一个绑定的端口。
上面结构中的表示该端口是否支持共享,所有共享该端口的socket挂到成员上。在用户使用时,内核使用TCP:,UDP:来绑定端口。
所以,当该端口支持共享,且socket也设置了并且不为状态时,此次可以成功。
3.9 =
版本内核增加了对的支持,可以绑定到相同的了。
这个时候,当Server收到Client发送的SYN报文时,会选择其中一个socket进行响应。
具体到实现,版本扩展了,将原来记录进行了拆分.
然后对也相应进行了扩展
而在绑定端口时,增加了一个队reuseport的通过条件
而当Client的SYN报文到达时,Server会首先根据本地端口(SYN报文的)计算出一条hash冲突链,然后遍历该链表上的所有Socket,根据四元组匹配程度进行打分;
如果使能了reuseport,那么可能有多个Socket都将拿到最高分,此时内核将随机选择一个进行后续处理。
举个栗子,假设内核有4条listening socket的hash冲突链,然后用户建立了4个Server:A、B、C、D,监听的地址和端口如下图所示,A和B使能了。
冲突链是以端口为Key的,因此A、B、D会挂到同一条冲突链上。
如果此时收到对端一个SYN报文,那么内核会遍历,为上面的7个socket进行打分,而由于B监听的是精确的地址,所以B的得分会比A高,内核最终选择出一个SocketB进行后续处理。
4.5
从上面的例子可以看出,当收到SYN报文时,内核一定会遍历一条完整hash冲突链,为每一个socket进行打分,这稍微有些多余。
因此,在4.5版本中,内核引入了,它将绑定到同一个IP和Port,并且设置了选项的socket组织到一个内部。
[attach]56820[/attach]
这个特性在4.5版本只支持UDP,而在4.6版本开始支持TCP(patch)。
这样在查找listen socket时,内核将不用再遍历整个冲突链,而是在找到一个合格的socket时,如果它设置了就直接找到它所属的,从中选择一个进行后续处理。
欢迎光临 嵌入式开发交流网论坛 (http://www.dianzixuexi.com/bbs/)
Powered by Discuz! X3.2