关于listen的backlog
1. Listen的backlog是为了限制服务端半连接队列和全连接队列的长度。在系统中有三个地方可调节:
1) listen(fd, backlog)
2) /proc/sys/net/core/somaxconn
3) /proc/sys/net/ipv4/tcp_max_syn_backlog
内核文档中的解释:
a) somaxconn: Limit of socket listen() backlog。
b) tcp_max_syn_backlog: Maximal number of remembered connection requests, which have not received an acknowledgment from connecting client.
简而言之, somaxconn限定了listen中backlog的参数, 而tcp_max_syn_backlog决定了半连接队列的最大值。
2. 实验。 使用systemtap编写:
kinwin@tencent-king:/data2/linux-3.4$ cat /data/systemtap/listen.stp probe begin { printf("inet listen Monitoring Started...\n") } probe kernel.function("inet_listen").return { accept_backlog = $backlog recvq_backlog = @cast($sock->sk, "inet_connection_sock")->icsk_accept_queue-> listen_opt->nr_table_entries printf("%-20s:accept backlog is %d, syn backlog is %d.\n", execname(),accept_backlog, recvq_backlog) }
1) listen(128), somaxconn 128, tcp_max_syn_backlog 128
listen :accept backlog is 128, syn backlog is 256.
2) listen(127), somaxconn 128 tcp_max_syn_backlog 128
listen :accept backlog is 127, syn backlog is 128.
3) listen(256), somaxconn 128 tcp_max_syn_backlog 128
listen :accept backlog is 128, syn backlog is 256.
4) listen(1024), somaxconn 1024, tcp_max_syn_backlog 256
listen :accept backlog is 1024, syn backlog is 512.
问题? 实际syn backlog值都超过了设定的tcp_max_syn_backlog. why?
在实际决定半连接队列长度的代码逻辑中:
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 = roundup_pow_of_two(nr_table_entries + 1);
会对原始值进行加一,并向上取二的次幂的操作。因此即使是max_syn_backlog,也会被操纵为2*max_syn_backlog。但这里逻辑显然是和内核文档中“Maximal number of remembered connection requests”不符的。