目錄
1 udp埠繫結概述
2 udp埠分配 udp_v4_get_port()
2.1 ip_local_port_range 修改(tcp、udp共用)
2.2 判斷埠是否可用udp_lib_lport_inuse()
3 埠的自動繫結 inet_autobind
udp套接字的埠號繫結發生在三種場景:
應用程式顯示的呼叫bind()系統呼叫實現埠繫結,一般伺服器端程式設計時會這麼做;
udp套接字建立後,客戶端使用connect()連線伺服器;
udp套接字建立後是可以直接使用sendto()傳送資料的,這種情況下會由kernel自動為該套接字繫結乙個可用埠。
當然,無論是哪種情況,它們最終都是使用同乙個介面進行埠分配的。系統呼叫bind()的函式呼叫關係如下圖所示:
注意:bind()可以繫結ip位址和埠號,只不過這裡我們只關心埠的繫結過程。再者關於inet_bind等介面的介紹已經在分析tcp的bind呼叫中作了介紹,此處直接介紹udp協議的分流處。
int udp_v4_get_port(struct sock *sk, unsigned short snum)
/** * udp_lib_get_port - udp/-lite port lookup for ipv4 and ipv6
* * @sk: socket struct in question
* @snum: port number to look up
* @saddr_comp: af-dependent comparison of bound local ip addresses
*/int udp_lib_get_port(struct sock *sk, unsigned short snum,
int (*saddr_comp)(const struct sock *sk1, const struct sock *sk2))
while (snum != first);
spin_unlock_bh(&hslot->lock);
} goto fail;
} else
found:
// 找到了可用埠
inet_sk(sk)->num = snum;
sk->sk_hash = snum;
if (sk_unhashed(sk))
error = 0;
fail_unlock:
spin_unlock_bh(&hslot->lock);
fail:
return error;
}
1顯示當前臨時埠的範圍:
一般情形下:linux臨時埠號範圍是(32768,61000)
sysctl net.ipv4.ip_local_port_range 或 cat /proc/sys/net/ipv4/ip_local_port_range
2.暫時性修改臨時埠的範圍:
# echo 1024 65535 > /proc/sys/net/ipv4/ip_local_port_range
注意以上命令是在root使用者時執行的!!
或者 sudo sysctl -w net.ipv4.ip_local_port_range="1024 64000"
3.永久性修改
修改檔案/etc/sysctl.conf
鍵入如下語句:
net.ipv4.ip_local_port_range = 1024 65535
核心操作:如果找到其他的 sock 也和本套接字繫結了相同的位址和埠就返回true。
static int udp_lib_lport_inuse(struct net *net, __u16 num, const struct udp_hslot *hslot,
unsigned long *bitmap, struct sock *sk,
int (*saddr_comp)(const struct sock *sk1, const struct sock *sk2))
return 0;
}//位址比較 saddr_comp
static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
綜上,udp的埠選擇過程還是非常複雜,並且對是乙個埠是否已經被使用的條件判定非常複雜,沒有真正理解。
系統呼叫中的各中send()到了核心就乙個入口,對於af_inet協議族就是inet_sendmsg()。
int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr,
int addr_len, int flags)
int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
size_t size)
static int inet_autobind(struct sock *sk)
inet->sport = htons(inet->num);
} release_sock(sk);
return 0;
}
注:埠的自動繫結流程屬於af_inet協議族的通用處理,tcp和udp都符合這個流程。 linux核心協議棧 鄰居協議概述
1 什麼是鄰居協議?ndp neighbor discovery protocol,鄰居發現協議 是ipv6的乙個關鍵協議,它組合了ipv4中的arp icmp路由器發現和icmp重定向等協議,並對它們作了改進。作為ipv6的基礎性協議,ndp還提供了字首發現 鄰居不可達檢測 重複位址監測 位址自動...
Linux 網路協議棧之核心鎖(二) 核心搶占
一 核心搶占 早期的linux核心是不可搶占的。它的排程方法是 乙個程序可以通過schedule 函式自願地啟動一次排程。非自願的強制性排程只能發生在每次從系統呼叫返回的前夕以及每次從中斷或異常處理返回到使用者空間的前夕。但是,如果在系統空間發生中斷或異常是不會引起排程的。這種方式使核心實現得以簡化...
《探尋linux協議棧》之一 linux協議棧概述
linux協議棧分層設計思想 linux分層究竟對報文做了什麼總結 本人所從事開發以來,一直在做資料面相關。資料面是乙個通訊裝置最終好不好用最直接的體現。因為乙個網路裝置,好不好用,資料 快不快,資料 穩定不穩定,全部都是使用者最直接體 現。所以工作八年以來,對linux核心協議棧業也積累了自己的一...