linux版本:4.9.51
在APP中,
listen(listenfd, BACKLOG_SIZE);
//The backlog argument defines the maximum length to which the queue of pending connections for sockfd may grow.
SYSCALL_DEFINE2(listen, int, fd, int, backlog)
SYSCALL_DEFINE2(listen, int, fd, int, backlog)
{
struct socket *sock;
int err, fput_needed;
int somaxconn;
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock) {
somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
if ((unsigned int)backlog > somaxconn)
backlog = somaxconn;
err = security_socket_listen(sock, backlog);
// sock->ops = inet_stream_ops
// inet_listen
if (!err)
err = sock->ops->listen(sock, backlog);
fput_light(sock->file, fput_needed);
}
return err;
}
其中 somaxconn = 128(默认值),在sysctl_core_net_init设定,调用路径是:
[ 0.084553] [sysctl_core_net_init 435]net->core.sysctl_somaxconn: 128 .
[ 0.084701] [<c0e29e70>] (sysctl_core_net_init) from [<c07f5ed4>] (ops_init.constprop.5+0xa4/0x110)
[ 0.084723] [<c07f5ed4>] (ops_init.constprop.5) from [<c07f5fec>] (register_pernet_operations+0xac/0xdc)
[ 0.084743] [<c07f5fec>] (register_pernet_operations) from [<c07f6048>] (register_pernet_subsys+0x2c/0x40)
[ 0.084763] [<c07f6048>] (register_pernet_subsys) from [<c0201898>] (do_one_initcall+0x54/0x190)
[ 0.084786] [<c0201898>] (do_one_initcall) from [<c0e00e74>] (kernel_init_freeable+0x158/0x1e4)
[ 0.084810] [<c0e00e74>] (kernel_init_freeable) from [<c09b69bc>] (kernel_init+0x8/0x114)
[ 0.084832] [<c09b69bc>] (kernel_init) from [<c0208628>] (ret_from_fork+0x14/0x2c)
/*
* Move a socket into listening state.
*/
int inet_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
unsigned char old_state;
int err;
// 检查状态
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, int backlog)
{
struct inet_connection_sock *icsk = inet_csk(sk);
struct inet_sock *inet = inet_sk(sk);
int err = -EADDRINUSE;
reqsk_queue_alloc(&icsk->icsk_accept_queue);
sk->sk_max_ack_backlog = backlog;
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.
*/
sk_state_store(sk, TCP_LISTEN);
if (!sk->sk_prot->get_port(sk, inet->inet_num)) {
inet->inet_sport = htons(inet->inet_num);
sk_dst_reset(sk);
err = sk->sk_prot->hash(sk);
if (likely(!err))
return 0;
}
sk->sk_state = TCP_CLOSE;
return err;
}