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系统调用的实现分析>;