偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Linux 內(nèi)核網(wǎng)絡(luò)之 Listen 的實(shí)現(xiàn)

系統(tǒng) Linux
listen 系統(tǒng)調(diào)用用于通知進(jìn)程準(zhǔn)備接受套接口上的連接請(qǐng)求,它同時(shí)也指定套接口上可以排隊(duì)等待的連接數(shù)的門限值。超過門限值時(shí),套接口將拒絕新的連接請(qǐng)求,TCP 將忽略進(jìn)入的連接請(qǐng)求。

listen 系統(tǒng)調(diào)用用于通知進(jìn)程準(zhǔn)備接受套接口上的連接請(qǐng)求,它同時(shí)也指定套接口上可以排隊(duì)等待的連接數(shù)的門限值。超過門限值時(shí),套接口將拒絕新的連接請(qǐng)求,TCP 將忽略進(jìn)入的連接請(qǐng)求。

/*
fd, 進(jìn)行監(jiān)聽的套接口的文件描述符
backlog,為指定連接隊(duì)列長(zhǎng)度的最大值
*/
asmlinkage long sys_listen(int fd, int backlog)
{
struct socket *sock;
int err, fput_needed;
//根據(jù)文件描述符獲取套接口指針,同時(shí)返回是否需要減少對(duì)文件引用計(jì)數(shù)的標(biāo)志
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock) {
//對(duì)參數(shù)門限值做檢驗(yàn),門限值不能超過上限
if ((unsigned)backlog > sysctl_somaxconn)
backlog = sysctl_somaxconn;
// 安全檢查
err = security_socket_listen(sock, backlog);
/*
通過套接口系統(tǒng)調(diào)用的跳轉(zhuǎn)表proto_ops結(jié)構(gòu),調(diào)用對(duì)應(yīng)傳輸層協(xié)議中的 listen 操作。
SOCK_DGRAM 和 SOCK_RAW 類型不支持listen,只有 SOCK_STREAM 類型支持listen接口,
TCP中為 inet_listen()
*/
if (!err)
err = sock->ops->listen(sock, backlog); //inet_listen()
//根據(jù) fput_needed,調(diào)用fput_light減少對(duì)文件引用計(jì)數(shù)操作
fput_light(sock->file, fput_needed);
}
return err;
}
上述的函數(shù)功能就是通過文件描述符獲取對(duì)應(yīng)的套接口指針,然后調(diào)用 inet_listen 進(jìn)行監(jiān)聽操作。
int inet_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
unsigned char old_state;
int err;
lock_sock(sk);
/*
*只有插口的類型為 SOCK_STREAM,即“有連接”模式的插口,并且已經(jīng)為其 bind()了插口地址,才允許 listen()。
*對(duì)于符合這些條件的插口也不是什么時(shí)候都可以調(diào)用 listen()的。
*插口的 sock結(jié)構(gòu)中有個(gè)成分 state,用來(lái)實(shí)現(xiàn)一種“有限狀態(tài)機(jī)”。只有當(dāng)這個(gè)狀態(tài)機(jī)處于 TCP_CLOSE 或 TCP_LISTEN
*這兩種狀態(tài)時(shí)才可以對(duì)其調(diào)用 listen()。
*在前面 sock_create()的代碼中可以看到在創(chuàng)建一個(gè)插口時(shí)要調(diào)用函數(shù) sock_init_data()對(duì)分配的sock數(shù)據(jù)結(jié)構(gòu)進(jìn)行初始化,
*在那里state被設(shè)置成 TCP_CLOSE。
*狀態(tài)TCP_CLOSE 表示插口只是剛剛建立,尚未宣布成為 server 插口;
*TCP_LISTEN 則表示插口已經(jīng)設(shè)置成 server 插口,當(dāng)尚未建立起連接,并且不是在等待來(lái)自 client 一方的連接請(qǐng)求。
*只有在這兩種狀態(tài)下才允許改變插口的參數(shù)(主要是連接請(qǐng)求隊(duì)列的容量)。
*/
err = -EINVAL;
if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM)
goto out;
old_state = sk->sk_state;
if (!((1 << old_state) & (TCPF_CLOSE | TCPF_LISTEN)))
goto out;
/* Really, if the socket is already in listen state
? we can only allow the backlog to be adjusted.
/
if (old_state != TCP_LISTEN) {
err = inet_csk_listen_start(sk, backlog);/ 開始偵聽 */
if (err)
goto out;
}
sk->sk_max_ack_backlog = backlog;
err = 0;
out:
release_sock(sk);
return err;
}
int inet_csk_listen_start(struct sock *sk, const int nr_table_entries)
{
struct inet_sock *inet = inet_sk(sk);
struct inet_connection_sock *icsk = inet_csk(sk);
//創(chuàng)建接收隊(duì)列,并把該隊(duì)列和傳輸控制塊綁定
int rc = reqsk_queue_alloc(&icsk->icsk_accept_queue, nr_table_entries);
if (rc != 0)
return rc;
sk->sk_max_ack_backlog = 0;
sk->sk_ack_backlog = 0;
inet_csk_delack_init(sk);
/* There is race window here: we announce ourselves listening,
? but this transition is still not validated by get_port().
? It is OK, because this socket enters to hash table only
? after validation is complete.
/
/ 設(shè)置控制塊的狀態(tài) /
sk->sk_state = TCP_LISTEN;
/ 檢查端口是否仍然可用,防止bind()后其它進(jìn)程修改了端口信息 */
if (!sk->sk_prot->get_port(sk, inet->num)) { // tcp_v4_get_port()
inet->sport = htons(inet->num);
sk_dst_reset(sk);
/* 把sock鏈接入監(jiān)聽哈希表中 */
sk->sk_prot->hash(sk); // tcp_v4_hash
return 0;
}
sk->sk_state = TCP_CLOSE;
__reqsk_queue_destroy(&icsk->icsk_accept_queue);
return -EADDRINUSE;
}

啟動(dòng)監(jiān)聽時(shí),做的工作主要包括:

創(chuàng)建半連接隊(duì)列的實(shí)例,初始化全連接隊(duì)列。 初始化 sock 的一些變量,把它的狀態(tài)設(shè)為 TCP_LISTEN。 檢查端口是否可用,防止bind()后其它進(jìn)程修改了端口信息。 把sock鏈接進(jìn)入監(jiān)聽哈希表 listening_hash 中。

創(chuàng)建半連接隊(duì)列

listen_sock 結(jié)構(gòu)用于保存 SYN_RECV 狀態(tài)的連接請(qǐng)求塊,所以也叫半連接隊(duì)列。

queue 為連接請(qǐng)求控制塊,nr_table_entries 為半連接的最大個(gè)數(shù),即 backlog。

int sysctl_max_syn_backlog = 256;
int reqsk_queue_alloc(struct request_sock_queue *queue,
unsigned int nr_table_entries)
{
size_t lopt_size = sizeof(struct listen_sock);
struct listen_sock *lopt;
/* nr_table_entries必需在[8, sysctl_max_syn_backlog]之間,默認(rèn)是[8, 256]
? 但實(shí)際上在sys_listen()中要求backlog <= sysctl_somaxconn(默認(rèn)為128)
? 所以此時(shí)默認(rèn)區(qū)間為[8, 128]
/
nr_table_entries = min_t(u32, nr_table_entries, sysctl_max_syn_backlog);
nr_table_entries = max_t(u32, nr_table_entries, 8);
/ 使nr_table_entries = 2^n,向上取整 */
nr_table_entries = roundup_pow_of_two(nr_table_entries + 1);
//為半連接隊(duì)列申請(qǐng)內(nèi)存
lopt_size += nr_table_entries * sizeof(struct request_sock );
if (lopt_size > PAGE_SIZE)
/ 如果申請(qǐng)內(nèi)存大于1頁(yè),則申請(qǐng)?zhí)摂M地址連續(xù)的空間 /
lopt = __vmalloc(lopt_size,
GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
PAGE_KERNEL);
else
/ 申請(qǐng)內(nèi)存在1頁(yè)內(nèi),則申請(qǐng)物理地址連續(xù)的空間 */
lopt = kzalloc(lopt_size, GFP_KERNEL);
if (lopt == NULL)
return -ENOMEM;
for (lopt->max_qlen_log = 3;
(1 << lopt->max_qlen_log) < nr_table_entries;
lopt->max_qlen_log++);
/* 獲取一個(gè)隨機(jī)數(shù) */
get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd));
rwlock_init(&queue->syn_wait_lock);
//全連接隊(duì)列頭初始化
queue->rskq_accept_head = NULL;
// 半連接隊(duì)列的最大長(zhǎng)度
lopt->nr_table_entries = nr_table_entries;
write_lock_bh(&queue->syn_wait_lock);
//半連接隊(duì)列設(shè)置
queue->listen_opt = lopt;
write_unlock_bh(&queue->syn_wait_lock);
return 0;
}

責(zé)任編輯:華軒 來(lái)源: 今日頭條
相關(guān)推薦

2023-03-10 14:56:37

Linuxconnect系統(tǒng)

2023-03-01 23:53:30

Linuxshutdown進(jìn)程

2023-03-28 15:51:20

2023-03-06 15:43:56

2021-09-17 11:59:21

tcpdump網(wǎng)絡(luò)包Linux

2021-09-08 10:21:33

內(nèi)核網(wǎng)絡(luò)包Tcpdump

2024-08-22 14:47:50

開源Linux網(wǎng)絡(luò)抓包工具

2009-07-16 09:02:38

LINUX 2.4.x網(wǎng)絡(luò)安全LINUX開發(fā)

2025-03-07 08:30:00

pwruLinux網(wǎng)絡(luò)包追蹤

2025-10-13 02:11:00

2023-05-12 07:27:24

Linux內(nèi)核網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)

2010-07-19 10:05:52

ibmdwLinux

2021-11-14 07:29:55

Linux 內(nèi)核靜態(tài)追蹤Linux 系統(tǒng)

2021-11-15 04:00:07

Linux 內(nèi)核動(dòng)態(tài)

2021-04-15 05:51:25

Linux

2013-12-18 14:44:10

2021-08-23 06:59:38

Linux內(nèi)核代碼

2023-11-24 11:24:16

Linux系統(tǒng)

2021-09-30 09:43:11

Linux內(nèi)核Zstd補(bǔ)丁

2020-04-13 07:00:00

Fedora防火墻系統(tǒng)運(yùn)維
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)