bind的port是通过tcp_hashinfo
里的bhash管理的。
跟tcp client的端口号管理有一样。
注:bind 系统调用时,还不会把当前的socket挂载到listen队列上,需要等待listen系统调用。
bind系统调用只是把对应的这个端口給占用上了, 其他程序没发bind。
call trace
case1: 如果是第一次bind,并且没有client占用这个port。
在inet_csk_get_port遍历bhash里对应的hash链表,
因为首次bind,所以tb没有找到。
[inet_bind_bucket_create]创建tb并挂载到bhash的链表里。
[inet_bind_hash]将socket挂载到tb对应的ownerlist上。
1 | system call bind |
case 2: bind+reuseport。close socket后再次bind一个新的soket到同一个port
通过inet_csk_bind_conflict
保证port之间冲突的检查。
1 | system call bind |
case 3: 如果bind的port,之前已经有client使用了。
那么对应tb的fastreuse
应该是-1,所以可以重用。
这个复用是有条件的,需要两个socket都设置为reuse才可以。
原理:
每个client socket在创建时候,都会在bhash的下挂载一个port占用信息。
listen socket在调用bind之前,会做检查,如果bhash下有socket占用了,
则绑定失败。
1 | 1361 /* |
1 | 901 const struct proto_ops inet_stream_ops = { |
1 | 423 int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) |
``inet_csk_get_port`
1 | 90 /* Obtain a reference to a local port for the given sock, |
inet_bind_bucket_create
1 | 57 /* |