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文章
11199浏览量
208691 -
函数
+关注
关注
3文章
4276浏览量
62315 -
系统
+关注
关注
1文章
1006浏览量
21289
发布评论请先 登录
相关推荐
linux中的busybox,是否带有bind和ifenslave?
想问下,飞凌提供的linux中的busybox,是否带有bind和ifenslave?如果没有有什么办法可以添加?
发表于 01-11 06:53
Bind源代码包安装
先到官方下载Bind的安装包 wgetftp://ftp.isc.org/isc/bind9/9.6.0-P1/bind-9.6.0-P1.tar.gz tar xzvf
发表于 04-04 20:30
•23次下载
Linux下进程的创建、执行和终止
许多操作系统提供的都是产生进程的机制,也就是说,首先在新的地址空间里创建进程、读入可执行文件,后再开始执行。Linux中进程的创建很特别,它把上述步骤分解到两个单独的函数中去
发表于 06-11 09:21
•600次阅读
如何使用Arduino millis函数执行多任务处理
在本教程中,我们将学习Arduino 如何使用 Arduino millis 函数执行多任务处理。通常在 Arduino 中使用delay()函数来执行LED 闪烁等周期性任务,但此
什么是bind?你真的熟悉bind吗?
bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被指定 bind()的第一个参数,而其余参数将作为新
bind系统调用背后的端口管理复用
的bind系统调用进行分析,主要是了解一下bind背后,Linux内核是如何进行端口绑定、如何管理本地众多的端口号。 先直观感受bind系统调用背后的端口管理、端口复用 # inclu
Linux内核分析 端口哈希桶
是用来封装各种协议的绑定哈希表,具体定义如下所示,这个结构体在[Linux内核角度分析服务器Listen细节中介绍过,具体地,struct inet_bind_hashbcket是bind相关的哈希桶
Linux内核分析 bind端口选择
端口选择 继续看inet_csk_get_port函数: 在端口选择前, 先确定当前该socket的“属性”,即是否可以端口复用,是否在TCP_LISTEN状态,以便后面插入到桶队列时设置
SCP固件执行步骤和模块间通信
SCP固件执行步骤 运行前阶段:按固定顺序排列的5个阶段 • 模块初始化:框架使用模块配置数据调用的模块的.init()函数。 • 元素初始化:带有元素配置数据的框架调用的模块
评论