1. 程式人生 > >listen系統調用

listen系統調用

down into sock spa clas shutdown start and already

 1 /*
 2  *    Perform a listen. Basically, we allow the protocol to do anything
 3  *    necessary for a listen, and if that works, we mark the socket as
 4  *    ready for listening.
 5  */
 6 
 7 SYSCALL_DEFINE2(listen, int, fd, int, backlog)
 8 {
 9     struct socket *sock;
10     int
err, fput_needed; 11 int somaxconn; 12 13 /* 查找socket結構 */ 14 sock = sockfd_lookup_light(fd, &err, &fput_needed); 15 if (sock) { 16 somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn; 17 18 /* backlog不能超過設置值 */ 19 if ((unsigned int)backlog > somaxconn)
20 backlog = somaxconn; 21 22 /* 安全模塊檢查 */ 23 err = security_socket_listen(sock, backlog); 24 if (!err) 25 /* 調用具體協議族的listen函數,只有SOCK_STREAM支持listen */ 26 err = sock->ops->listen(sock, backlog); 27 28 fput_light(sock->file, fput_needed);
29 } 30 return err; 31 }

 1 /*
 2  *    Move a socket into listening state.
 3  */
 4 int inet_listen(struct socket *sock, int backlog)
 5 {
 6     struct sock *sk = sock->sk;
 7     unsigned char old_state;
 8     int err;
 9 
10     lock_sock(sk);
11 
12     err = -EINVAL;
13 
14     /* 檢查socket狀態和類型,僅支持SOCK_STREAM */
15     if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM)
16         goto out;
17 
18     /* 記錄連接當前狀態 */
19     old_state = sk->sk_state;
20 
21     /* 檢查連接狀態,需為close或者listen */
22     if (!((1 << old_state) & (TCPF_CLOSE | TCPF_LISTEN)))
23         goto out;
24 
25     /* Really, if the socket is already in listen state
26      * we can only allow the backlog to be adjusted.
27      */
28     /* 如果尚未listen過 */
29     if (old_state != TCP_LISTEN) {
30         /* Enable TFO w/o requiring TCP_FASTOPEN socket option.
31          * Note that only TCP sockets (SOCK_STREAM) will reach here.
32          * Also fastopen backlog may already been set via the option
33          * because the socket was in TCP_LISTEN state previously but
34          * was shutdown() rather than close().
35          */
36         /* TFO相關*/
37         if ((sysctl_tcp_fastopen & TFO_SERVER_WO_SOCKOPT1) &&
38             (sysctl_tcp_fastopen & TFO_SERVER_ENABLE) &&
39             !inet_csk(sk)->icsk_accept_queue.fastopenq.max_qlen) {
40             fastopen_queue_tune(sk, backlog);
41             tcp_fastopen_init_key_once(true);
42         }
43 
44         /* 開始監聽 */
45         err = inet_csk_listen_start(sk, backlog);
46         if (err)
47             goto out;
48     }
49 
50     /* 設置backlog,包括已經listen過,調整backlog */
51     sk->sk_max_ack_backlog = backlog;
52     err = 0;
53 
54 out:
55     release_sock(sk);
56     return err;
57 }
58 EXPORT_SYMBOL(inet_listen);

其中inet_csk_listen_start函數將在閱讀tcp代碼時詳細分析;

listen系統調用