0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux内核分析 bind端口选择

麦辣鸡腿堡 来源:技术简说 作者:董旭 2023-07-31 11:08 次阅读

端口选择

继续看inet_csk_get_port函数:

在端口选择前,先确定当前该socket的“属性”,即是否可以端口复用,是否在TCP_LISTEN状态,以便后面插入到桶队列时设置fastreuse字段。

bool reuse = sk- >sk_reuse && sk- >sk_state != TCP_LISTEN;

进行端口选择和绑定:

端口绑定分为两种,一种指定端口,一种随机选择。如果给 bind 传 递的地址参数中,port 字段为 0,那么就会自动选择参数。

如代码所示,当端口port没有指定时,调用inet_csk_find_open_port(sk, &tb, &port):

if (!port) {
  head = inet_csk_find_open_port(sk, &tb, &port);
  if (!head)
   return ret;
  if (!tb)
   goto tb_not_found;
  goto success;
 }

主要逻辑在net_csk_find_open_port实现,重点看端口指定,暂时不看端口不指定(其实逻辑差不多)。那么当用户指定了端口,也就是port有值时:

head = &hinfo- >bhash[inet_bhashfn(net, port,hinfo- >bhash_size)];
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;
 }
  • 1、通过指定的port端口号,计算哈希值,找到对应的inet_bind_hashbucket:
head = &hinfo- >bhash[inet_bhashfn(net, port,hinfo- >bhash_size)];
  • 2 、调用inet_bind_bucket_for_each遍历该inet_bind_hashbucke中的chain链表
inet_bind_bucket_for_each(tb, &head- >chain)
  • 3、如果遍历chain链表时,找到了指定port相同的桶结构,则跳转到tb_found:
if (net_eq(ib_net(tb), net) && tb- >port == port)
   goto tb_found;
  • 4、在tb_found标签中:判断该桶结构中sock队列是否为空,为空且当前套接字支持复用,则绑定成功。进入success标签。
  • 5、在succeess完成对该port对应的桶结构的初始化或修改
  • 6、如果在3、中没有找到对应的桶结构,进入tb_not_found标签,在当前的chain链表中创建一个新的桶结构,再进行4、5操作:
tb_not_found:
 tb = inet_bind_bucket_create(hinfo- >bind_bucket_cachep,
         net, head, port);
 if (!tb)
  goto fail_unlock;

端口复用的解释

还是要从文章开头的图说起,bind时端口号都会经过哈希计算分配在【相应的哈希桶结构inet_bind_hashbucket】上的chain链表节点的【桶结构inet_bind_bucket上】,inet_bind_bucket 结构就是用来描述端口和 sock 之间的绑定关系的。它的 port 字段表示一个绑定的端口,而 owners 则表示绑定到这个端口之上的所有 sock,因为端口可以重用,所以同一端口可能有多个 sock 绑定。

bind端口复用的实际用途基本上也就是:

防止服务器重启时之前绑定的端口还未释放或者程序突然退出而系统没有释放端口。这种情况下如果设定了端口复用,则新启动的服务器进程可以直接绑定端口。如果没有设定端口复用,绑定会失败,提示ADDR已经在使用中!

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    10994

    浏览量

    206772
  • 端口
    +关注

    关注

    4

    文章

    822

    浏览量

    31609
  • Bind
    +关注

    关注

    0

    文章

    5

    浏览量

    7530
收藏 人收藏

    评论

    相关推荐

    Linux源码分析bind系统调用

    众所周知,一个Server端Socket的建立,需要socket、bind、listen、accept四个步骤。
    的头像 发表于 10-16 11:08 2895次阅读
    从<b class='flag-5'>Linux</b>源码<b class='flag-5'>分析</b><b class='flag-5'>bind</b>系统调用

    一文详解Linux内核源码组织结构

    概要:本文内容包含Linux源码树结构分析Linux Makefile分析、Kconfig文件分析L
    的头像 发表于 05-10 19:28 5345次阅读

    udp_bind这个绑定的端口怎么解除?

    请教下,udp_bind 这个绑定的端口,刚开始是可以的,但是重新绑定时返回错误,有什么方法可以在 重新绑定前解除之前的绑定 ?
    发表于 04-22 07:41

    linux内核分析及编程

    linux内核分析及编程
    发表于 04-20 08:26

    linux内核分析及编程--

    本帖最后由 lee_st 于 2018-5-19 10:26 编辑 linux内核分析及编程--
    发表于 05-09 09:49

    TCP server 不能 bind 80 端口

    后程序只开一个 AP 模式下的 TCP server ,测试。  但是发现 80 端口没法 bind ,错误码是 -98 ,意思是端口已被占用? 换一个其它端口号(比如 12345)就
    发表于 05-14 00:33

    linux中的busybox,是否带有bind和ifenslave?

    想问下,飞凌提供的linux中的busybox,是否带有bind和ifenslave?如果没有有什么办法可以添加?
    发表于 01-11 06:53

    嵌入式LINUX内核网络栈(源代码)

    本文选择 LINUX-1.2.13 内核所包含的网络部分代码分析(注意网络部分代码与内核代码的演变是分离的,如
    发表于 05-12 10:39 57次下载
    嵌入式<b class='flag-5'>LINUX</b><b class='flag-5'>内核</b>网络栈(源代码)

    linux内核启动内核解压过程分析

    linux启动时内核解压过程分析,一份不错的文档,深入了解内核必备
    发表于 03-09 13:39 1次下载

    基于Linux 2.6内核Makefile分析

    基于2.4内核的,可以说关于2.6内核Makefile相关的文章凤毛麟角,笔者抽时间完成了这篇分析文章,让读者迅速熟悉Linux最新Makefile体系,从而加深对
    发表于 09-18 19:09 0次下载
    基于<b class='flag-5'>Linux</b> 2.6<b class='flag-5'>内核</b>Makefile<b class='flag-5'>分析</b>

    Linux内核GPIO操作函数的详解分析

    本文档的主要内容详细介绍的是Linux内核GPIO操作函数的详解分析免费下载。
    发表于 01-22 16:58 28次下载

    什么是bind?你真的熟悉bind吗?

    bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被指定 bind()的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
    的头像 发表于 07-13 09:56 1875次阅读

    bind系统调用背后的端口管理复用

    bind系统调用进行分析,主要是了解一下bind背后,Linux内核是如何进行端口绑定、如何管
    的头像 发表于 07-31 10:45 355次阅读
    <b class='flag-5'>bind</b>系统调用背后的<b class='flag-5'>端口</b>管理复用

    Linux bind的核心执行函数

    不看,本文主要分析最重要的函数:inet_csk_get_port,从该函数出发了解本地绑定端口如何管理。 以下是原函数,通过下文章节逐步分段分析 int inet_csk_get_port
    的头像 发表于 07-31 10:51 358次阅读

    Linux内核分析 端口哈希桶

    是用来封装各种协议的绑定哈希表,具体定义如下所示,这个结构体在[Linux内核角度分析服务器Listen细节中介绍过,具体地,struct inet_bind_hashbcket是
    的头像 发表于 07-31 11:03 436次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b><b class='flag-5'>分析</b> <b class='flag-5'>端口</b>哈希桶