chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

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

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

SO_REUSEADDR 與 SO_REUSEPORT是什么?

Linux愛(ài)好者 ? 來(lái)源:187J3X1 ? 作者:187J3X1 ? 2020-12-11 16:38 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

SO_REUSEPORT選項(xiàng)在Linux 3.9被引入內(nèi)核,在這之前也有一個(gè)很像的選項(xiàng)SO_REUSEADDR。

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

如果不想讀,那么下面這一節(jié)算是為懶人準(zhǔn)備的。

SO_REUSEADDR 與 SO_REUSEPORT 是什么?

TCP/UDP用五元組唯一標(biāo)識(shí)一個(gè)連接。

任何時(shí)候,兩條連接的五元組都不能完全相同,否則當(dāng)收到一個(gè)報(bào)文時(shí),協(xié)議棧沒(méi)辦法判斷它是屬于哪個(gè)連接的。

五元組{, , , , }

五元組里,protocol在創(chuàng)建socket時(shí)確定,在bind()時(shí)確定,在connect()時(shí)確定。

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

那么,如果對(duì)socket設(shè)置了SO_REUSEADDR和SO_REUSEPORT選項(xiàng),它們什么時(shí)候起作用呢?

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

不同操作系統(tǒng)內(nèi)核對(duì)待SO_REUSEADDR和SO_REUSEPORT的行為有少許差異,但它們都源自BSD。

因此,接下來(lái)就以BSD的實(shí)現(xiàn)為標(biāo)準(zhǔn)進(jìn)行說(shuō)明。

SO_REUSEADDR

假設(shè)我現(xiàn)在需要bind()將socketA綁定到A:X,將socketB綁定到B:Y(不考慮X=0或者Y=0,因?yàn)?表示讓內(nèi)核自動(dòng)分配端口,一定不會(huì)沖突)。

如果X!=Y,那么無(wú)論A和B的關(guān)系如何,兩個(gè)bind()都會(huì)成功。但如果X==Y,那么結(jié)果會(huì)是下面這樣:

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)

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

注:這里設(shè)置的對(duì)象是指后綁定的socket(也就是說(shuō)不關(guān)心前一個(gè)是否設(shè)置)

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

SO_REUSEADDR還有一種應(yīng)用情景:在TCP中存在一個(gè)TIME_WAIT狀態(tài),它是指主動(dòng)關(guān)閉的一端最后停留的階段。

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

SO_REUSEPORT

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

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

提醒一下,以上的結(jié)果都是BSD的結(jié)果,Linux內(nèi)核有一些不一樣的地方,具體表現(xiàn)為

3.9版本支持SO_REUSEPORT,作為Server的TCP Socket一旦綁定到了具體的端口,啟動(dòng)了LISTEN,即使它之前設(shè)置過(guò)SO_REUSEADDR, 也不會(huì)生效。這一點(diǎn)Linux比BSD更加嚴(yán)格

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選項(xiàng)具有BSD中的SO_REUSEPORT的效果。這一點(diǎn)Linux又比BSD更加寬松。

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

Linux中reuseport的演進(jìn)

Linux < 3.9

下面看看具體是怎么做的: 內(nèi)核socket使用skc_reuse字段表示是否設(shè)置了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表示一個(gè)綁定的端口。

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

上面結(jié)構(gòu)中的fastreuse表示該端口是否支持共享,所有共享該端口的socket掛到owner成員上。在用戶使用bind()時(shí),內(nèi)核使用TCP:inet_csk_get_port(),UDP:udp_v4_get_port()來(lái)綁定端口。

/* 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;

所以,當(dāng)該端口支持共享,且socket也設(shè)置了SO_REUSEADDR并且不為L(zhǎng)ISTEN狀態(tài)時(shí),此次bind()可以成功。

3.9 =< Linux < 4.5

3.9版本內(nèi)核增加了對(duì)SO_REUSEPORT的支持,listener可以綁定到相同的了。

這個(gè)時(shí)候,當(dāng)Server收到Client發(fā)送的SYN報(bào)文時(shí),會(huì)選擇其中一個(gè)socket進(jìn)行響應(yīng)。

具體到實(shí)現(xiàn),3.9版本擴(kuò)展了sock_common,將原來(lái)記錄skc_reuse進(jìn)行了拆分.

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;

然后對(duì)inet_bind_bucket也相應(yīng)進(jìn)行了擴(kuò)展

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

而在綁定端口時(shí),增加了一個(gè)隊(duì)reuseport的通過(guò)條件

/* 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;

而當(dāng)Client的SYN報(bào)文到達(dá)時(shí),Server會(huì)首先根據(jù)本地端口(SYN報(bào)文的)計(jì)算出一條hash沖突鏈,然后遍歷該鏈表上的所有Socket,根據(jù)四元組匹配程度進(jìn)行打分;

如果使能了reuseport,那么可能有多個(gè)Socket都將拿到最高分,此時(shí)內(nèi)核將隨機(jī)選擇一個(gè)進(jìn)行后續(xù)處理。

/* 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]; // 根據(jù)本地端口找到hash沖突鏈 /* code omitted */ result = NULL; hiscore = 0; sk_nulls_for_each_rcu(sk, node, &ilb->head) { score = compute_score(sk, net, hnum, daddr, dif); // 根據(jù)匹配程度進(jìn)行打分 if (score > hiscore) { result = sk; hiscore = score; reuseport = sk->sk_reuseport; if (reuseport) { phash = inet_ehashfn(net, daddr, hnum, saddr, sport); matches = 1; // 如果是reuseport 則累計(jì)多少個(gè)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; }

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

沖突鏈?zhǔn)且远丝跒镵ey的,因此A、B、D會(huì)掛到同一條沖突鏈上。

如果此時(shí)收到對(duì)端一個(gè)SYN報(bào)文<192.168.10.1, 21>,那么內(nèi)核會(huì)遍歷listening_hash[0],為上面的7個(gè)socket進(jìn)行打分,而由于B監(jiān)聽(tīng)的是精確的地址,所以B的得分會(huì)比A高,內(nèi)核最終選擇出一個(gè)SocketB進(jìn)行后續(xù)處理。

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

4.5 < Linux

從上面的例子可以看出,當(dāng)收到SYN報(bào)文時(shí),內(nèi)核一定會(huì)遍歷一條完整hash沖突鏈,為每一個(gè)socket進(jìn)行打分,這稍微有些多余。

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

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; };

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

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

@@ -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; } }

責(zé)任編輯:lq

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

    關(guān)注

    4

    文章

    1436

    瀏覽量

    42470
  • Linux
    +關(guān)注

    關(guān)注

    88

    文章

    11622

    瀏覽量

    217827

原文標(biāo)題:Linux 內(nèi)核中 reuseport 的演進(jìn)

文章出處:【微信號(hào):LinuxHub,微信公眾號(hào):Linux愛(ài)好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    昂科燒錄器支持Microchip微芯科技的8位CMOS微控制器PIC16F54-I/SO

    芯片燒錄領(lǐng)導(dǎo)者昂科技術(shù)在發(fā)布新版燒錄軟件的同時(shí),宣布擴(kuò)展了兼容芯片型號(hào)列表。新增型號(hào)里有了微芯科技的8位CMOS微控制器PIC16F54-I/SO,這款芯片已得到昂科通用燒錄平臺(tái)AP8000通用
    的頭像 發(fā)表于 08-05 09:38 ?811次閱讀
    昂科燒錄器支持Microchip微芯科技的8位CMOS微控制器PIC16F54-I/<b class='flag-5'>SO</b>

    如何為L(zhǎng)SDK構(gòu)建libgtk-x11-2.0.so.0?

    我正在嘗試為我的 LS1028A RDB板(運(yùn)行 LSDK)構(gòu)建 libgtk-x11-2.0.so.0。這是 libopencv_highgui.so 所需要的。有沒(méi)有辦法為 LS1028A 交叉編譯這個(gè)庫(kù)?
    發(fā)表于 04-04 08:00

    為imx6qsabresd進(jìn)行bitbake mesa時(shí)未構(gòu)建libGL.so,為什么?

    /gl.h 標(biāo)頭,但我找不到,但我可以在 /usr/lib 下看到 libGL.so。我的理解是專有的 GPU 驅(qū)動(dòng)程序不支持 OpenGL,僅支持 OpenGLES,并且提供的 libGL.so
    發(fā)表于 03-28 08:18

    SO1400光耦參數(shù)測(cè)試系統(tǒng) 多通道光電器件綜合測(cè)試平臺(tái)

    SO1400是專為?第三代光耦器件?設(shè)計(jì)的全自動(dòng)測(cè)試系統(tǒng),集成1400V高壓測(cè)試與1A大電流驅(qū)動(dòng)能力。本設(shè)備采用軍工級(jí)測(cè)試架構(gòu),滿足?工業(yè)4.0?標(biāo)準(zhǔn)下對(duì)光耦器件的?在線質(zhì)量檢測(cè)?與?可靠性驗(yàn)證?需求,適用于新能源、智能電網(wǎng)等高可靠性應(yīng)用場(chǎng)景。
    的頭像 發(fā)表于 03-13 12:05 ?751次閱讀
    <b class='flag-5'>SO</b>1400光耦參數(shù)測(cè)試系統(tǒng)  多通道光電器件綜合測(cè)試平臺(tái)

    STM32H7使用LWIP通信,數(shù)據(jù)量過(guò)大會(huì)卡死怎么解決?

    , SO_REUSEADDR, &enable, sizeof(enable));//允許本地地址重用 // 設(shè)置讀取超時(shí) struct timeval timeout
    發(fā)表于 03-11 06:43

    在linux下編譯了cyusbserial SDK生成so文件,但是運(yùn)行測(cè)試程序和編寫API都訪問(wèn)不到DLP3010EVM,為什么?

    在win下我可以正常使用GUI軟件和示例API訪問(wèn)DLP3010EVM,但是在linux下我編譯了cyusbserial SDK生成so文件,但是運(yùn)行測(cè)試程序和編寫API都訪問(wèn)不到DLP。我目的
    發(fā)表于 02-26 08:27

    請(qǐng)發(fā)我一份CS1237-SO的STC51例程

    請(qǐng)發(fā)我一份CS1237-SO的STC51例程,xutao@sau.edu.cn
    發(fā)表于 02-10 11:53

    設(shè)計(jì)SO-8封裝的詳細(xì)步驟和注意事項(xiàng)

    設(shè)計(jì) SO-8(Small Outline-8)芯片的 PCB 封裝需要遵循一定的規(guī)范和步驟。SO-8 是一種常見(jiàn)的表面貼裝封裝,具有 8 個(gè)引腳,引腳間距通常為 1.27mm(50 mil)。以下是設(shè)計(jì) SO-8 封裝的詳細(xì)步
    的頭像 發(fā)表于 02-06 15:24 ?4703次閱讀
    設(shè)計(jì)<b class='flag-5'>SO</b>-8封裝的詳細(xì)步驟和注意事項(xiàng)

    MariaDB配置日志審計(jì)

    確認(rèn)插件路徑下是否有日志審計(jì)插件server_audit.so。
    的頭像 發(fā)表于 02-05 13:34 ?711次閱讀

    SO63-4-55-22-90焊接套管現(xiàn)貨庫(kù)存Raychem瑞侃

    SO63-4-55-22-90焊接套管現(xiàn)貨庫(kù)存Raychem瑞侃SO63-4-55-22-90焊接套管是Raychem瑞侃的一款性能穩(wěn)定、安裝簡(jiǎn)便的屏蔽焊接套管,適用于各種電氣連接技術(shù)應(yīng)用,尤其是
    發(fā)表于 01-21 09:41

    SO63-3-55-22-90焊接套管現(xiàn)貨庫(kù)存Raychem瑞侃

    SO63-3-55-22-90焊接套管現(xiàn)貨庫(kù)存Raychem瑞侃SO63-3-55-22-90焊接套管是款性能卓越、安裝便捷的屏蔽焊接套管,適用于各種電氣連接應(yīng)用。技術(shù)參數(shù)尺寸:18.25mm直徑
    發(fā)表于 01-10 08:51

    TEA2376DT恩智浦PFC控制器驅(qū)動(dòng)芯片

    - SO10/SO14的交錯(cuò)PFC?相移,為優(yōu)秀的PF/THD?先進(jìn)的頻率控制,效率高?添加/脫落/BM?高靈活性和易于通過(guò)GUI設(shè)計(jì)最小包裝,SO10和SO14通過(guò)MTP實(shí)現(xiàn)高可配置
    發(fā)表于 12-23 17:13 ?8次下載

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

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

    吉林大學(xué):研究用于農(nóng)業(yè)早期火災(zāi)識(shí)別的ppb級(jí)SO2/NO2雙氣體傳感器系統(tǒng)的開(kāi)發(fā)和現(xiàn)場(chǎng)部署

    背景介紹 大氣中二氧化硫(SO2)和二氧化氮(NO2)的來(lái)源多種多樣,化石燃料的燃燒是主要來(lái)源,自然火災(zāi)和農(nóng)業(yè)秸稈的燃燒是重要的排放途徑。作為典型的酸性氣體,它們是氣溶膠系統(tǒng)的組成部分,改變了大氣
    的頭像 發(fā)表于 12-05 09:22 ?754次閱讀
    吉林大學(xué):研究用于農(nóng)業(yè)早期火災(zāi)識(shí)別的ppb級(jí)<b class='flag-5'>SO</b>2/NO2雙氣體傳感器系統(tǒng)的開(kāi)發(fā)和現(xiàn)場(chǎng)部署

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

    恒溫箱作為生物學(xué)、微生物學(xué)和醫(yī)療保健領(lǐng)域的關(guān)鍵工具,為細(xì)胞、組織和微生物樣本的生長(zhǎng)和培養(yǎng)提供了必要的控制條件。在這些應(yīng)用中,準(zhǔn)確監(jiān)測(cè)和調(diào)整培養(yǎng)環(huán)境中的氧水平非常重要,氧化鋯氧傳感器SO
    的頭像 發(fā)表于 12-04 01:07 ?958次閱讀
    恒溫箱內(nèi)的敏銳氣體偵探-氧化鋯氧傳感器<b class='flag-5'>SO</b>-E2-250、<b class='flag-5'>SO</b>-E2-960