close system call to close the file descriptor, which system call is as follows;
1 / 2 * Careful here! We test whether the file pointer is NULL before 3 * releasing the fd. This ensures that one clone task can't release 4 * an fd while another clone is opening it. 5 */ 6 SYSCALL_DEFINE1(close, unsigned int, fd) 7 { 8 int retval = __close_fd(current->files, fd); 9 10 /* can't restart close syscall because file table entry was cleared */ 11 if (unlikely(retval == -ERESTARTSYS || 12 retval == -ERESTARTNOINTR || 13 retval == -ERESTARTNOHAND || 14 retval == -ERESTART_RESTARTBLOCK)) 15 retval = -EINTR; 16 17 return retval; 18 } 19 EXPORT_SYMBOL(sys_close);
This paper focuses on the analysis of the close portions of the socket, so that outlines the close system call function calls general flow relationship, as follows;
Added: where the focus of attention at fput function, the reference count of -1 will now function will first file, and then determine whether it is 0, 0 of the time will be to continue the process, that is to say when there are multiple references socket only the last one close will trigger the destruction process behind schedule, a different place is close to the shutdown of;
. 1 / * * 2 * Close the system call function call relationship . 3 * __ close_fd . 4 * | -> filp_close . 5 * | -> fput delayed_fput_list the file is added to the list . 6 * | - queue processing list> schedule_delayed_work scheduling delay execution 7 * | -> delayed_fput 8 * | -> __ fput 9 * | -> File-> f_op-> release files operating release call 10 * /
Seen in the close system call invokes the release operation file, so we focus on the analysis of this release socket operation implementation;
Operation of socket file structure shown below, wherein the release function is implemented as discussed herein sock_close;
1 /* socket文件操作函数 */ 2 static const struct file_operations socket_file_ops = { 3 .owner = THIS_MODULE, 4 .llseek = no_llseek, 5 .read_iter = sock_read_iter, 6 .write_iter = sock_write_iter, 7 .poll = sock_poll, 8 .unlocked_ioctl = sock_ioctl, 9 #ifdef CONFIG_COMPAT 10 .compat_ioctl = compat_sock_ioctl, 11 #endif 12 .mmap = sock_mmap, 13 .release = sock_close, 14 .fasync = sock_fasync, 15 .sendpage = sock_sendpage, 16 .splice_write = generic_splice_sendpage, 17 .splice_read = sock_splice_read, 18 };
In socket_release function, operation function calls socket release, ipv4 corresponding to inet_release;
1 /* 关闭socket */ 2 static int sock_close(struct inode *inode, struct file *filp) 3 { 4 /* socket关闭 */ 5 sock_release(SOCKET_I(inode)); 6 return 0; 7 }
1 /** 2 * sock_release - close a socket 3 * @sock: socket to close 4 * 5 * The socket is released from the protocol stack if it has a release 6 * callback, and the inode is then released if the socket is bound to 7 * an inode not a file. 8 */ 9 10 void sock_release(struct socket *sock) 11 { 12 if (sock->ops) { 13 struct module *owner = sock->ops->owner; 14 15 / * Invoke socket operation Release * / 16 sock-> OPS-> Release (our sock); . 17 sock-> OPS = NULL; 18 is module_put (owner); . 19 } 20 is 21 is IF (rcu_dereference_protected (sock-> WQ, . 1 ) -> fasync_list) 22 is pr_err ( " !% S: fasync List Not empty \ n- " , __func__ in); 23 is 24 / * reduce the set number of cpu interface * / 25 this_cpu_sub (sockets_in_use, . 1 ); 26 is 27 / * fault tolerance * / 28 IF (sock->! File) { 29 iput (SOCK_INODE (our sock)); 30 return ; 31 is } 32 33 is / * socket closing is completed, continue with other processes close system call * / 34 is sock-> File = NULL; 35 }
inet_release responsible leave a multicast group, to set the delay time in accordance with off flag is turned linger, and calls the close function of the transport layer, for tcp, its call is tcp_close;
1 /* 2 * The peer socket should always be NULL (or else). When we call this 3 * function we are destroying the object and from then on nobody 4 * should refer to it. 5 */ 6 int inet_release(struct socket *sock) 7 { 8 struct sock *sk = sock->sk; 9 10 if (sk) { 11 long timeout; 12 13 /* Applications forget to leave groups before exiting */ 14 /* 退出组播组 */ 15 ip_mc_drop_socket (SK); 16 . 17 / * the If the linger IS SET, WE do Not Close The return an until 18 is * IS of The Complete Immediately return the Otherwise WE.. . 19 * Actually either the closing IS DONE The Same Way. 20 is * 21 is * the If Due to IS the Close the exiting the process, WE Never 22 is * linger .. 23 is * / 24 timeout = 0 ; 25 26 is / * 27 provided linger flag, the process is not exit 28 is set off delay time lingertime 29 * / 30 if(sock_flag (SK, SOCK_LINGER) && 31 is (to current-> the flags &! PF_EXITING)) 32 timeout = SK-> sk_lingertime; 33 is sock-> SK = NULL; 34 is 35 / * calls the close function of the transmission layer * / 36 SK- > sk_prot-> Close (SK, timeout); 37 [ } 38 is return 0 ; 39 }
tcp_close analysis please move on to another article <TCP layer to achieve close analysis of the system calls>;