套接字之shutdown系统调用

shutdown用来关闭一个全双工连接的部分或者全部,比如关闭读,关闭写,或者读写全部关闭;

 1 /*
 2  *    Shutdown a socket.
 3  */
 4 
 5 SYSCALL_DEFINE2(shutdown, int, fd, int, how)
 6 {
 7     int err, fput_needed;
 8     struct socket *sock;
 9 
10     /* 找到socket */
11     sock = sockfd_lookup_light(fd, &err, &fput_needed);
12     if (sock != NULL) {
13         err = security_socket_shutdown(sock, how);
14         if (!err)
15             /* 调用对应类型的shutdown */
16             err = sock->ops->shutdown(sock, how);
17         fput_light(sock->file, fput_needed);
18     }
19     return err;
20 }

 

inet_shutdown会根据连接的状态进行不同的处理,比如已连接状态需要调用传输层实现的shutdown,而监听或者发送了syn包会根据情况则调用传输层的disconnect等;

 1 /* 关闭操作 */
 2 int inet_shutdown(struct socket *sock, int how)
 3 {
 4     struct sock *sk = sock->sk;
 5     int err = 0;
 6 
 7     /* This should really check to make sure
 8      * the socket is a TCP socket. (WHY AC...)
 9      */
10     how++; /* maps 0->1 has the advantage of making bit 1 rcvs and
11                1->2 bit 2 snds.
12                2->3 */
13     /* how值错误 */
14     if ((how & ~SHUTDOWN_MASK) || !how)    /* MAXINT->0 */
15         return -EINVAL;
16 
17     lock_sock(sk);
18 
19     /* 正在连接 */
20     if (sock->state == SS_CONNECTING) {
21         /* syn发送,syn接收,关闭状态 */
22         if ((1 << sk->sk_state) &
23             (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_CLOSE))
24             /* 设置正在关闭连接 */
25             sock->state = SS_DISCONNECTING;
26         /* 否则为已连接状态 */
27         else
28             sock->state = SS_CONNECTED;
29     }
30 
31     switch (sk->sk_state) {
32     case TCP_CLOSE:
33         err = -ENOTCONN;
34         /* Hack to wake up other listeners, who can poll for
35            POLLHUP, even on eg. unconnected UDP sockets -- RR */
36     default:
37         /* 设置how值,并且调用传输层的shutdown */
38         sk->sk_shutdown |= how;
39         if (sk->sk_prot->shutdown)
40             sk->sk_prot->shutdown(sk, how);
41         break;
42 
43     /* Remaining two branches are temporary solution for missing
44      * close() in multithreaded environment. It is _not_ a good idea,
45      * but we have no choice until close() is repaired at VFS level.
46      */
47     case TCP_LISTEN:
48         /* 监听状态,如果无接收方向的关闭操作,跳出 */
49         if (!(how & RCV_SHUTDOWN))
50             break;
51         /* 有接收方向的关闭,继续 */
52         /* Fall through */
53     case TCP_SYN_SENT:
54         /* 调用传输层的disconnect断开连接 */
55         err = sk->sk_prot->disconnect(sk, O_NONBLOCK);
56 
57         /* 调增状态 */
58         sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED;
59         break;
60     }
61 
62     /* Wake up anyone sleeping in poll. */
63     /* 状态改变,唤醒等待的进程 */
64     sk->sk_state_change(sk);
65     release_sock(sk);
66     return err;
67 }

 

tcp层shutdown实现请移步下面文章<TCP层shutdown系统调用的实现分析>;

 

posted @ 2017-10-03 00:59  AlexAlex  阅读(744)  评论(0编辑  收藏  举报