系统调用listen的实现

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值