sk_reuse sk- >sk_state != TCP_LISTEN; 進(jìn)行端口選擇和綁定: 端口綁定分為兩種,一種指定端口,一種隨機(jī)選擇。如果給 bind 傳 遞的地址參數(shù)中,port 字段為 0,那么就會自動選擇參數(shù)。 如代碼所示,當(dāng)端口port沒有指定時(shí),調(diào)用inet_csk_find_open_port(sk, port): if (!port) { head = inet_csk_" />
0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux內(nèi)核分析 bind端口選擇

麥辣雞腿堡 ? 來源:技術(shù)簡說 ? 作者:董旭 ? 2023-07-31 11:08 ? 次閱讀

端口選擇

繼續(xù)看inet_csk_get_port函數(shù):

在端口選擇前,先確定當(dāng)前該socket的“屬性”,即是否可以端口復(fù)用,是否在TCP_LISTEN狀態(tài),以便后面插入到桶隊(duì)列時(shí)設(shè)置fastreuse字段。

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

進(jìn)行端口選擇和綁定:

端口綁定分為兩種,一種指定端口,一種隨機(jī)選擇。如果給 bind 傳 遞的地址參數(shù)中,port 字段為 0,那么就會自動選擇參數(shù)。

如代碼所示,當(dāng)端口port沒有指定時(shí),調(diào)用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實(shí)現(xiàn),重點(diǎn)看端口指定,暫時(shí)不看端口不指定(其實(shí)邏輯差不多)。那么當(dāng)用戶指定了端口,也就是port有值時(shí):

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端口號,計(jì)算哈希值,找到對應(yīng)的inet_bind_hashbucket:
head = &hinfo- >bhash[inet_bhashfn(net, port,hinfo- >bhash_size)];
  • 2 、調(diào)用inet_bind_bucket_for_each遍歷該inet_bind_hashbucke中的chain鏈表
inet_bind_bucket_for_each(tb, &head- >chain)
  • 3、如果遍歷chain鏈表時(shí),找到了指定port相同的桶結(jié)構(gòu),則跳轉(zhuǎn)到tb_found:
if (net_eq(ib_net(tb), net) && tb- >port == port)
   goto tb_found;
  • 4、在tb_found標(biāo)簽中:判斷該桶結(jié)構(gòu)中sock隊(duì)列是否為空,為空且當(dāng)前套接字支持復(fù)用,則綁定成功。進(jìn)入success標(biāo)簽。
  • 5、在succeess完成對該port對應(yīng)的桶結(jié)構(gòu)的初始化或修改
  • 6、如果在3、中沒有找到對應(yīng)的桶結(jié)構(gòu),進(jìn)入tb_not_found標(biāo)簽,在當(dāng)前的chain鏈表中創(chuàng)建一個(gè)新的桶結(jié)構(gòu),再進(jìn)行4、5操作:
tb_not_found:
 tb = inet_bind_bucket_create(hinfo- >bind_bucket_cachep,
         net, head, port);
 if (!tb)
  goto fail_unlock;

端口復(fù)用的解釋

還是要從文章開頭的圖說起,bind時(shí)端口號都會經(jīng)過哈希計(jì)算分配在【相應(yīng)的哈希桶結(jié)構(gòu)inet_bind_hashbucket】上的chain鏈表節(jié)點(diǎn)的【桶結(jié)構(gòu)inet_bind_bucket上】,inet_bind_bucket 結(jié)構(gòu)就是用來描述端口和 sock 之間的綁定關(guān)系的。它的 port 字段表示一個(gè)綁定的端口,而 owners 則表示綁定到這個(gè)端口之上的所有 sock,因?yàn)槎丝诳梢灾赜?,所以同一端口可能有多個(gè) sock 綁定。

bind端口復(fù)用的實(shí)際用途基本上也就是:

防止服務(wù)器重啟時(shí)之前綁定的端口還未釋放或者程序突然退出而系統(tǒng)沒有釋放端口。這種情況下如果設(shè)定了端口復(fù)用,則新啟動的服務(wù)器進(jìn)程可以直接綁定端口。如果沒有設(shè)定端口復(fù)用,綁定會失敗,提示ADDR已經(jīng)在使用中!

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11161

    瀏覽量

    208466
  • 端口
    +關(guān)注

    關(guān)注

    4

    文章

    934

    瀏覽量

    31945
  • Bind
    +關(guān)注

    關(guān)注

    0

    文章

    5

    瀏覽量

    7594
收藏 人收藏

    評論

    相關(guān)推薦

    Linux源碼分析bind系統(tǒng)調(diào)用

    眾所周知,一個(gè)Server端Socket的建立,需要socket、bind、listen、accept四個(gè)步驟。
    的頭像 發(fā)表于 10-16 11:08 ?3175次閱讀
    從<b class='flag-5'>Linux</b>源碼<b class='flag-5'>分析</b><b class='flag-5'>bind</b>系統(tǒng)調(diào)用

    udp_bind這個(gè)綁定的端口怎么解除?

    請教下,udp_bind 這個(gè)綁定的端口,剛開始是可以的,但是重新綁定時(shí)返回錯誤,有什么方法可以在 重新綁定前解除之前的綁定 ?
    發(fā)表于 04-22 07:41

    linux內(nèi)核分析及編程

    linux內(nèi)核分析及編程
    發(fā)表于 04-20 08:26

    TCP server 不能 bind 80 端口

    后程序只開一個(gè) AP 模式下的 TCP server ,測試。 ?但是發(fā)現(xiàn) 80 端口沒法 bind ,錯誤碼是 -98 ,意思是端口已被占用? 換一個(gè)其它端口號(比如 12345)就
    發(fā)表于 05-14 00:33

    Android內(nèi)核分析

    介紹Android 移動平臺系統(tǒng)架構(gòu),通過對Android 源代碼的分析,將其與標(biāo)準(zhǔn)Linux 內(nèi)核(2.6.27)源代碼相比較,詳細(xì)解析Android 內(nèi)核的功能更新,
    發(fā)表于 10-29 16:17 ?116次下載

    linux內(nèi)核啟動內(nèi)核解壓過程分析

    linux啟動時(shí)內(nèi)核解壓過程分析,一份不錯的文檔,深入了解內(nèi)核必備
    發(fā)表于 03-09 13:39 ?1次下載

    基于Linux 2.6內(nèi)核Makefile分析

    基于2.4內(nèi)核的,可以說關(guān)于2.6內(nèi)核Makefile相關(guān)的文章鳳毛麟角,筆者抽時(shí)間完成了這篇分析文章,讓讀者迅速熟悉Linux最新Makefile體系,從而加深對
    發(fā)表于 09-18 19:09 ?0次下載
    基于<b class='flag-5'>Linux</b> 2.6<b class='flag-5'>內(nèi)核</b>Makefile<b class='flag-5'>分析</b>

    關(guān)于Linux 2.6內(nèi)核Makefile的分析

    的介紹文章都是基于2.4內(nèi)核的,可以說關(guān)于2.6內(nèi)核Makefile相關(guān)的文章鳳毛麟角,筆者抽時(shí)間完成了這篇分析文章,讓讀者迅速熟悉Linux最新Makefile體系,從而加深對
    發(fā)表于 11-02 10:12 ?1次下載

    谷歌Android設(shè)備內(nèi)核引入主線Linux內(nèi)核難嗎?

    Android是基于Linux內(nèi)核的操作系統(tǒng),但是,運(yùn)行在Android設(shè)備上的內(nèi)核其實(shí)與Google選擇的LTS版本Linux
    的頭像 發(fā)表于 11-22 10:41 ?2986次閱讀
    谷歌Android設(shè)備<b class='flag-5'>內(nèi)核</b>引入主線<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>難嗎?

    Linux內(nèi)核配置編譯分析的設(shè)計(jì)方案

    Linux內(nèi)核配置編譯分析的設(shè)計(jì)方案
    發(fā)表于 07-08 16:53 ?18次下載
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>配置編譯<b class='flag-5'>分析</b>的設(shè)計(jì)方案

    Linux內(nèi)核GPIO操作函數(shù)的詳解分析

    本文檔的主要內(nèi)容詳細(xì)介紹的是Linux內(nèi)核GPIO操作函數(shù)的詳解分析免費(fèi)下載。
    發(fā)表于 01-22 16:58 ?28次下載

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

    bind()方法創(chuàng)建一個(gè)新的函數(shù),在bind()被調(diào)用時(shí),這個(gè)新函數(shù)的this被指定 bind()的第一個(gè)參數(shù),而其余參數(shù)將作為新函數(shù)的參數(shù),供調(diào)用時(shí)使用。
    的頭像 發(fā)表于 07-13 09:56 ?2545次閱讀

    bind系統(tǒng)調(diào)用背后的端口管理復(fù)用

    bind系統(tǒng)調(diào)用進(jìn)行分析,主要是了解一下bind背后,Linux內(nèi)核是如何進(jìn)行端口綁定、如何管
    的頭像 發(fā)表于 07-31 10:45 ?494次閱讀
    <b class='flag-5'>bind</b>系統(tǒng)調(diào)用背后的<b class='flag-5'>端口</b>管理復(fù)用

    Linux bind的核心執(zhí)行函數(shù)

    不看,本文主要分析最重要的函數(shù):inet_csk_get_port,從該函數(shù)出發(fā)了解本地綁定端口如何管理。 以下是原函數(shù),通過下文章節(jié)逐步分段分析 int inet_csk_get_port
    的頭像 發(fā)表于 07-31 10:51 ?512次閱讀

    Linux內(nèi)核分析 端口哈希桶

    是用來封裝各種協(xié)議的綁定哈希表,具體定義如下所示,這個(gè)結(jié)構(gòu)體在[Linux內(nèi)核角度分析服務(wù)器Listen細(xì)節(jié)中介紹過,具體地,struct inet_bind_hashbcket是
    的頭像 發(fā)表于 07-31 11:03 ?680次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b><b class='flag-5'>分析</b> <b class='flag-5'>端口</b>哈希桶