色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

SO_REUSEADDR 與 SO_REUSEPORT是什么?

Linux愛好者 ? 來源:187J3X1 ? 作者:187J3X1 ? 2020-12-11 16:38 ? 次閱讀

SO_REUSEPORT選項在Linux 3.9被引入內核,在這之前也有一個很像的選項SO_REUSEADDR。

如果你不太清楚這兩者的區別和聯系,建議搜索 How do SO_REUSEADDR and SO_REUSEPORT differ?。

如果不想讀,那么下面這一節算是為懶人準備的。

SO_REUSEADDR 與 SO_REUSEPORT 是什么?

TCP/UDP用五元組唯一標識一個連接。

任何時候,兩條連接的五元組都不能完全相同,否則當收到一個報文時,協議棧沒辦法判斷它是屬于哪個連接的。

五元組{, , , , }

五元組里,protocol在創建socket時確定,在bind()時確定,在connect()時確定。

當然,bind()和connect()在一些時候并不需要顯式使用,不過這不在本文的討論范圍里。

那么,如果對socket設置了SO_REUSEADDR和SO_REUSEPORT選項,它們什么時候起作用呢?

答案是bind(),也就在確定時。

不同操作系統內核對待SO_REUSEADDR和SO_REUSEPORT的行為有少許差異,但它們都源自BSD

因此,接下來就以BSD的實現為標準進行說明。

SO_REUSEADDR

假設我現在需要bind()將socketA綁定到A:X,將socketB綁定到B:Y(不考慮X=0或者Y=0,因為0表示讓內核自動分配端口,一定不會沖突)。

如果X!=Y,那么無論A和B的關系如何,兩個bind()都會成功。但如果X==Y,那么結果會是下面這樣:

SO_REUSEADDR socketA socketB Result --------------------------------------------------------------------- ON/OFF 192.168.0.1:21 192.168.0.1:21 Error (EADDRINUSE) ON/OFF 192.168.0.1:21 10.0.0.1:21 OK ON/OFF 10.0.0.1:21 192.168.0.1:21 OK OFF 0.0.0.0:21 192.168.1.0:21 Error (EADDRINUSE) OFF 192.168.1.0:21 0.0.0.0:21 Error (EADDRINUSE) ON 0.0.0.0:21 192.168.1.0:21 OK ON 192.168.1.0:21 0.0.0.0:21 OK ON/OFF 0.0.0.0:21 0.0.0.0:21 Error (EADDRINUSE)

第一列表示是否設置SO_REUSEADDR注,最后一列表示后綁定的socket是否能綁定成功。

注:這里設置的對象是指后綁定的socket(也就是說不關心前一個是否設置)

可以看出,BSD的實現中SO_REUSEADDR可以讓一個使用通配地址(0.0.0.0),一個使用指定地址(192.168.1.0)的socket同時綁定成功。

SO_REUSEADDR還有一種應用情景:在TCP中存在一個TIME_WAIT狀態,它是指主動關閉的一端最后停留的階段。

假設socketA綁定到A:X,在完成TCP通信后主動使用close(),進入TIME_WAIT,此時,如果socketB也去綁定A:X,那么同樣會得到EADDRINUSE錯誤,但如果socketB設置了SO_REUSEADDR,那么就可以綁定成功。

SO_REUSEPORT

如果理解了SO_REUSEADDR,那么SO_REUSEPORT就很好理解了,它讓兩個socket可以綁定完全相同的

SO_REUSEPORT socketA socketB Result --------------------------------------------------------------------- ON 192.168.0.1:21 192.168.0.1:21 OK

提醒一下,以上的結果都是BSD的結果,Linux內核有一些不一樣的地方,具體表現為

3.9版本支持SO_REUSEPORT,作為Server的TCP Socket一旦綁定到了具體的端口,啟動了LISTEN,即使它之前設置過SO_REUSEADDR, 也不會生效。這一點Linux比BSD更加嚴格

SO_REUSEADDR socketA socketB Result --------------------------------------------------------------------- ON/OFF 192.168.0.1:21 0.0.0.0:21 Error (EADDRINUSE)

3.9版本之前,作為Client的Socket,SO_REUSEADDR選項具有BSD中的SO_REUSEPORT的效果。這一點Linux又比BSD更加寬松。

SO_REUSEADDR socketA socketB Result --------------------------------------------------------------------- ON 192.168.0.2:55555 192.168.0.2:55555 OK

Linux中reuseport的演進

Linux < 3.9

下面看看具體是怎么做的: 內核socket使用skc_reuse字段表示是否設置了SO_REUSEADDR

struct sock_common { /* omitted */ unsigned char skc_reuse; /* omitted */ } int sock_setsockopt(struct socket *sock, int level, int optname,... { ...... case SO_REUSEADDR: sk->sk_reuse = (valbool ? SK_CAN_REUSE : SK_NO_REUSE); break; }

inet_bind_bucket表示一個綁定的端口。

struct inet_bind_bucket { /* omitted */ unsigned short port; signed short fastreuse; int num_owners; struct hlist_node node; struct hlist_head owners; };

上面結構中的fastreuse表示該端口是否支持共享,所有共享該端口的socket掛到owner成員上。在用戶使用bind()時,內核使用TCP:inet_csk_get_port(),UDP:udp_v4_get_port()來綁定端口。

/* inet_connection_Sock.c: inet_csk_get_port() */ tb_found: if (!hlist_empty(&tb->owners)) { ...... if (tb->fastreuse > 0 && sk->sk_reuse && sk->sk_state != TCP_LISTEN && smallest_size == -1) { goto success;

所以,當該端口支持共享,且socket也設置了SO_REUSEADDR并且不為LISTEN狀態時,此次bind()可以成功。

3.9 =< Linux < 4.5

3.9版本內核增加了對SO_REUSEPORT的支持,listener可以綁定到相同的了。

這個時候,當Server收到Client發送的SYN報文時,會選擇其中一個socket進行響應。

具體到實現,3.9版本擴展了sock_common,將原來記錄skc_reuse進行了拆分.

struct sock_common { unsigned short skc_family; volatile unsigned char skc_state; - unsigned char skc_reuse; + unsigned char skc_reuse:4; + unsigned char skc_reuseport:4; @@ int sock_setsockopt(struct socket *sock, int level, int optname, case SO_REUSEADDR: sk->sk_reuse = (valbool ? SK_CAN_REUSE : SK_NO_REUSE); break; + case SO_REUSEPORT: + sk->sk_reuseport = valbool; + break;

然后對inet_bind_bucket也相應進行了擴展

struct inet_bind_bucket { /* omitted */ unsigned short port; - signed short fastreuse; + signed char fastreuse; + signed char fastreuseport; + kuid_t fastuid;

而在綁定端口時,增加了一個隊reuseport的通過條件

/* inet_connection_sock.c: inet_csk_get_port() */ tb_found: if (sk->sk_reuse == SK_FORCE_REUSE) goto success; - if (tb->fastreuse > 0 && - sk->sk_reuse && sk->sk_state != TCP_LISTEN && + if (((tb->fastreuse > 0 && + sk->sk_reuse && sk->sk_state != TCP_LISTEN) || + (tb->fastreuseport > 0 && + sk->sk_reuseport && uid_eq(tb->fastuid, uid))) && smallest_size == -1) { goto success;

而當Client的SYN報文到達時,Server會首先根據本地端口(SYN報文的)計算出一條hash沖突鏈,然后遍歷該鏈表上的所有Socket,根據四元組匹配程度進行打分;

如果使能了reuseport,那么可能有多個Socket都將拿到最高分,此時內核將隨機選擇一個進行后續處理。

/* inet_hashtables.c */ struct sock *__inet_lookup_listener(struct......) { struct sock *sk, *result; unsigned int hash = inet_lhashfn(net, hnum); struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash]; // 根據本地端口找到hash沖突鏈 /* code omitted */ result = NULL; hiscore = 0; sk_nulls_for_each_rcu(sk, node, &ilb->head) { score = compute_score(sk, net, hnum, daddr, dif); // 根據匹配程度進行打分 if (score > hiscore) { result = sk; hiscore = score; reuseport = sk->sk_reuseport; if (reuseport) { phash = inet_ehashfn(net, daddr, hnum, saddr, sport); matches = 1; // 如果是reuseport 則累計多少個socket滿足 } } else if (score == hiscore && reuseport) { matches++; if (reciprocal_scale(phash, matches) == 0) result = sk; phash = next_pseudo_random32(phash); } } /* * if the nulls value we got at the end of this lookup is * not the expected one, we must restart lookup. * We probably met an item that was moved to another chain. */ return result; }

舉個栗子,假設內核有4條listening socket的hash沖突鏈,然后用戶建立了4個Server:A、B、C、D,監聽的地址和端口如下圖所示,A和B使能了SO_REUSEPORT。

沖突鏈是以端口為Key的,因此A、B、D會掛到同一條沖突鏈上。

如果此時收到對端一個SYN報文<192.168.10.1, 21>,那么內核會遍歷listening_hash[0],為上面的7個socket進行打分,而由于B監聽的是精確的地址,所以B的得分會比A高,內核最終選擇出一個SocketB進行后續處理。

89f4964a-2eb2-11eb-a64d-12bb97331649.png

4.5 < Linux

從上面的例子可以看出,當收到SYN報文時,內核一定會遍歷一條完整hash沖突鏈,為每一個socket進行打分,這稍微有些多余。

因此,在4.5版本中,內核引入了reuseport groups,它將綁定到同一個IP和Port,并且設置了SO_REUSEPORT選項的socket組織到一個group內部。

8a34dac0-2eb2-11eb-a64d-12bb97331649.png

--- a/include/net/sock.h +++ b/include/net/sock.h @@ -318,6 +318,7 @@ struct cg_proto; * @sk_error_report: callback to indicate errors (e.g. %MSG_ERRQUEUE) * @sk_backlog_rcv: callback to process the backlog * @sk_destruct: called at sock freeing time, i.e. when all refcnt == 0 + * @sk_reuseport_cb: reuseport group container */ struct sock { /* @@ -453,6 +454,7 @@ struct sock { int (*sk_backlog_rcv)(struct sock *sk, struct sk_buff *skb); void (*sk_destruct)(struct sock *sk); + struct sock_reuseport __rcu *sk_reuseport_cb; };

這個特性在4.5版本只支持UDP,而在4.6版本開始支持TCP(patch)。

這樣在查找listen socket時,內核將不用再遍歷整個沖突鏈,而是在找到一個合格的socket時,如果它設置了SO_REUSEPORT,就直接找到它所屬的reuseport group,從中選擇一個進行后續處理。

@@ -215,6 +217,7 @@ struct sock *__inet_lookup_listener(struct net *net, unsigned int hash = inet_lhashfn(net, hnum); struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash]; int score, hiscore, matches = 0, reuseport = 0; + bool select_ok = true; u32 phash = 0; rcu_read_lock(); @@ -230,6 +233,15 @@ begin: if (reuseport) { phash = inet_ehashfn(net, daddr, hnum, saddr, sport); + if (select_ok) { + struct sock *sk2; + sk2 = reuseport_select_sock(sk, phash, + skb, doff); + if (sk2) { + result = sk2; + goto found; + } + } matches = 1; } }

責任編輯:lq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內核
    +關注

    關注

    3

    文章

    1376

    瀏覽量

    40319
  • Linux
    +關注

    關注

    87

    文章

    11320

    瀏覽量

    209843

原文標題:Linux 內核中 reuseport 的演進

文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    TEA2376DT恩智浦PFC控制器驅動芯片

    - SO10/SO14的交錯PFC?相移,為優秀的PF/THD?先進的頻率控制,效率高?添加/脫落/BM?高靈活性和易于通過GUI設計最小包裝,SO10和SO14通過MTP實現高可配置
    發表于 12-23 17:13 ?0次下載

    3PEAK最新物料選型總表(包含MPQ、最新LT交期情況

    TPA3662-VS1R MSOP8 3000 10 OPATPA3664-SO2R SOP14 2500 24 OPATPM1525-SO1R-S SOP8 4000 10
    發表于 12-10 12:35 ?0次下載

    恒溫箱內的敏銳氣體偵探-氧化鋯氧傳感器SO-E2-250、SO-E2-960

    恒溫箱作為生物學、微生物學和醫療保健領域的關鍵工具,為細胞、組織和微生物樣本的生長和培養提供了必要的控制條件。在這些應用中,準確監測和調整培養環境中的氧水平非常重要,氧化鋯氧傳感器SO
    的頭像 發表于 12-04 01:07 ?187次閱讀
    恒溫箱內的敏銳氣體偵探-氧化鋯氧傳感器<b class='flag-5'>SO</b>-E2-250、<b class='flag-5'>SO</b>-E2-960

    氧化鋯氧傳感器SO-E2-XXX在恒溫箱內的應用

    SO-E2-XXX正是實現這一目標的重要工具。 氧測量傳感器如何有益于細胞培養箱? 細胞培養箱中的氧測量傳感器,如氧化鋯氧傳感器SO-E2-XXX,通過精確監測和調節氧水平,確保了細胞生長所需的理想環境。細胞在分化、增殖和存活等關鍵過程中
    的頭像 發表于 11-07 13:43 ?164次閱讀
    氧化鋯氧傳感器<b class='flag-5'>SO</b>-E2-XXX在恒溫箱內的應用

    IGBT 和 MOSFET 驅動器-延展型 SO-6 封裝,實現緊湊設計、快速開關和高壓

    最新 IGBT 和 MOSFET 驅動器 器件峰值輸出電流高達?4 A 工作溫度高達?+125 °C,傳播延遲低至?200 ns Vishay 推出兩款采用緊湊、高隔離延展型 SO-6 封裝
    的頭像 發表于 11-03 13:42 ?262次閱讀
    IGBT 和 MOSFET 驅動器-延展型 <b class='flag-5'>SO</b>-6 封裝,實現緊湊設計、快速開關和高壓

    請問OPA2378有沒有SO-8封裝的呢?

    請問OPA2378 有沒有SO-8封裝的呢? Tks!
    發表于 09-26 07:45

    ADS114S06和ADS114S08與低成本ADS114S06B和ADS114SO8B的比較

    電子發燒友網站提供《ADS114S06和ADS114S08與低成本ADS114S06B和ADS114SO8B的比較.pdf》資料免費下載
    發表于 09-10 10:34 ?2次下載
    ADS114S06和ADS114S08與低成本ADS114S06B和ADS114<b class='flag-5'>SO</b>8B的比較

    麻煩廠家發一份CS1237-SO的驅動程序給我STC版本的

    麻煩廠家發一份CS1237-SO的驅動程序給我STC版本的741891100@qq.com
    發表于 08-23 14:48

    STM32MP157運行glmark2提示沒有openEGL.so,為什么?

    使用weston相關的應用,運行glmark2提示沒有openEGL.so。請問一下這是為什么呢?這些應用和動態庫應該都是在根文件系統啊。****
    發表于 07-23 08:19

    【飛凌嵌入式OK527N-C開發板體驗】終章-傳感器數據互通

    , SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror(\"setsockopt\"
    發表于 07-10 22:16

    如何在ROS中調用.so文件

    的是 liblibdaq-2.0.0.so這個文件,下面以ROS為例子怎么調用.so文件。 結合cmake的使用 新建工作空間,功能包等流程不再贅述,網上已經有很多教程了。著重講cmakelist的配置
    發表于 07-02 14:44

    如何在ROS中調用.so文件

    設備筆者有一個需求,需要結合ROS做模擬量采集。有一種解決方法是ADC芯片+STM32主控,通過串口的方式與上位機通信,但串口通信速度很慢,達不到要求遂放棄。也考慮過使用NI的數據采集卡,貌似NI沒有給ubuntu作配套,也放棄了。在淘寶上找到一款凌智電子的DAQ,價格便宜,也能滿足使用需求,故做記錄。系統環境ubuntu20.04+ROSnoetic硬件設
    的頭像 發表于 06-30 08:23 ?565次閱讀
    如何在ROS中調用.<b class='flag-5'>so</b>文件

    使用IAR和STlink,stm8 so disco的板子,提示Failed to set option byte: 怎么解決?

    使用IAR和STlink,stm8 so disco的板子,提示 Failed to set option byte: 寫保護應該是取消了的,有沒有前輩遇到這個問題
    發表于 04-16 08:03

    STM32MP157無法使用weston相關的應用,運行glmark2提示沒有openEGL.so,為什么?

    使用weston相關的應用,運行glmark2提示沒有openEGL.so。請問一下這是為什么呢?這些應用和動態庫應該都是在根文件系統啊。
    發表于 03-15 07:47

    SO14;SMD卷軸包,13“;Q1/T1產品定位包裝信息

    電子發燒友網站提供《SO14;SMD卷軸包,13“;Q1/T1產品定位包裝信息.pdf》資料免費下載
    發表于 02-22 09:30 ?0次下載
    <b class='flag-5'>SO</b>14;SMD卷軸包,13“;Q1/T1產品定位包裝信息
    主站蜘蛛池模板: 亚洲欧美人成视频在线| 91精品国产色综合久久| zoovideo人与驴mp4| 欧美xxx性| 成人精品视频网站| 四虎国产精品永久一区高清| 国产精品热久久高潮AV袁孑怡| 亚洲 成人网| 老湿机一区午夜精品免费福利| 99久久蜜臀亚洲AV无码精品| 三级黄色在线免费观看| 嗨嗨快播电影| 99久久伊人一区二区yy5099| 四虎成人影院| 快乐激情网| 国产成人综合在线视频| 伊伊人成亚洲综合人网| 日本大片免a费观看视频| 午夜精品国产自在现线拍| 寂寞护士中文字幕 mp4| adc网址在线观看| 晓雪老师我要进你里面好爽| 老熟风间由美AV在线一区二区| 穿白丝袜边走边尿白丝袜| 一道精品视频一区二区| 日本精品无码久久久久APP| 精品国产自在天天线2019| BT7086福利二区最新| 亚洲看片网站| 肉伦禁忌小说np| 久久国产一区二区三区| 国产99久久亚洲综合精品西瓜tv| 一个人HD高清在线观看免费视频| 日本全彩黄漫无遮挡| 久久久无码精品亚洲日韩按摩| 国产av久久免费观看| 97国产精品视频在线观看| 亚洲精品久久久无码| 入禽太深视频免费视频| 麻豆E奶女教师国产精品| 国模玲玲自拍337p|