bind的核心執行函數
bind系統調用的核心函數調用流程如下:
SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
|
sock- >ops- >bind(sock,
(struct sockaddr *)
&address, addrlen);
|
inet_bind
|
inet_csk_get_port
中間的流程暫且不看,本文主要分析最重要的函數:inet_csk_get_port,從該函數出發了解本地綁定端口如何管理。
以下是原函數,通過下文章節逐步分段分析
int inet_csk_get_port(struct sock *sk, unsigned short snum)
{
bool reuse = sk- >sk_reuse && sk- >sk_state != TCP_LISTEN;
struct inet_hashinfo *hinfo = sk- >sk_prot- >h.hashinfo;
int ret = 1, port = snum;
struct inet_bind_hashbucket *head;
struct net *net = sock_net(sk);
struct inet_bind_bucket *tb = NULL;
kuid_t uid = sock_i_uid(sk);
if (!port) {
head = inet_csk_find_open_port(sk, &tb, &port);
if (!head)
return ret;
if (!tb)
goto tb_not_found;
goto success;
}
head = &hinfo- >bhash[inet_bhashfn(net, port,
hinfo- >bhash_size)];
spin_lock_bh(&head- >lock);
inet_bind_bucket_for_each(tb, &head- >chain)
if (net_eq(ib_net(tb), net) && tb- >port == port)
goto tb_found;
tb_not_found:
tb = inet_bind_bucket_create(hinfo- >bind_bucket_cachep,
net, head, port);
if (!tb)
goto fail_unlock;
tb_found:
if (!hlist_empty(&tb- >owners)) {
if (sk- >sk_reuse == SK_FORCE_REUSE)
goto success;
if ((tb- >fastreuse > 0 && reuse) ||
sk_reuseport_match(tb, sk))
goto success;
if (inet_csk_bind_conflict(sk, tb, true, true))
goto fail_unlock;
}
success:
if (hlist_empty(&tb- >owners)) {
tb- >fastreuse = reuse;
if (sk- >sk_reuseport) {
tb- >fastreuseport = FASTREUSEPORT_ANY;
tb- >fastuid = uid;
tb- >fast_rcv_saddr = sk- >sk_rcv_saddr;
tb- >fast_ipv6_only = ipv6_only_sock(sk);
tb- >fast_sk_family = sk- >sk_family;
#if IS_ENABLED(CONFIG_IPV6)
tb- >fast_v6_rcv_saddr = sk- >sk_v6_rcv_saddr;
#endif
} else {
tb- >fastreuseport = 0;
}
} else {
if (!reuse)
tb- >fastreuse = 0;
if (sk- >sk_reuseport) {
if (!sk_reuseport_match(tb, sk)) {
tb- >fastreuseport = FASTREUSEPORT_STRICT;
tb- >fastuid = uid;
tb- >fast_rcv_saddr = sk- >sk_rcv_saddr;
tb- >fast_ipv6_only = ipv6_only_sock(sk);
tb- >fast_sk_family = sk- >sk_family;
#if IS_ENABLED(CONFIG_IPV6)
tb- >fast_v6_rcv_saddr = sk- >sk_v6_rcv_saddr;
#endif
}
} else {
tb- >fastreuseport = 0;
}
}
if (!inet_csk(sk)- >icsk_bind_hash)
inet_bind_hash(sk, tb, port);
WARN_ON(inet_csk(sk)- >icsk_bind_hash != tb);
ret = 0;
fail_unlock:
spin_unlock_bh(&head- >lock);
return ret;
}
-
Linux
+關注
關注
87文章
11230瀏覽量
208937 -
函數
+關注
關注
3文章
4307瀏覽量
62434 -
系統
+關注
關注
1文章
1008瀏覽量
21316
發布評論請先 登錄
相關推薦
評論