套接字之close系统调用
close系统调用用于关闭文件描述符,其系统调用实现如下所示;
/
* Careful here! We test whether the file pointer is NULL before
* releasing the fd. This ensures that one clone task can't release
* an fd while another clone is opening it.
*/
SYSCALL_DEFINE1(close, unsigned int, fd)
{
int retval = __close_fd(current->files, fd); /* can't restart close syscall because file table entry was cleared */
if (unlikely(retval == -ERESTARTSYS ||
retval == -ERESTARTNOINTR ||
retval == -ERESTARTNOHAND ||
retval == -ERESTART_RESTARTBLOCK))
retval = -EINTR; return retval;
}
EXPORT_SYMBOL(sys_close);
本文重点在于分析套接字的的close部分,所以简要列出close系统调用通用流程的函数调用关系,如下;
补充:其中重点注意下fput函数,该函数会先现将文件的引用计数-1,然后判断是否为0,为0的时候才会进行继续的流程,也就是说当socket存在多个引用的时候,只有最后一个close才会触发后面的调度销毁流程,也是close与shutdown不同的一个地方;
/**
* close系统调用函数调用关系
*__close_fd
* |-->filp_close
* |-->fput 将file加入到delayed_fput_list链表
* |-->schedule_delayed_work 调度延迟执行队列处理链表
* |-->delayed_fput
* |-->__fput
* |-->file->f_op->release 调用文件的release操作
*/
可见,在close系统调用中会调用文件的release操作,所以我们本文重点分析socket的release操作实现;
socket实现的文件操作结构如下所示,其中本文讨论的release函数实现为sock_close;
/* socket文件操作函数 */
static const struct file_operations socket_file_ops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read_iter = sock_read_iter,
.write_iter = sock_write_iter,
.poll = sock_poll,
.unlocked_ioctl = sock_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_sock_ioctl,
#endif
.mmap = sock_mmap,
.release = sock_close,
.fasync = sock_fasync,
.sendpage = sock_sendpage,
.splice_write = generic_splice_sendpage,
.splice_read = sock_splice_read,
};
在socket_release函数中,会调用socket操作函数release,ipv4对应inet_release;
/* 关闭socket */
static int sock_close(struct inode *inode, struct file *filp)
{
/* socket关闭 */
sock_release(SOCKET_I(inode));
return ;
}
/**
* sock_release - close a socket
* @sock: socket to close
*
* The socket is released from the protocol stack if it has a release
* callback, and the inode is then released if the socket is bound to
* an inode not a file.
*/ void sock_release(struct socket *sock)
{
if (sock->ops) {
struct module *owner = sock->ops->owner; /* 调用socket操作中的release */
sock->ops->release(sock);
sock->ops = NULL;
module_put(owner);
} if (rcu_dereference_protected(sock->wq, )->fasync_list)
pr_err("%s: fasync list not empty!\n", __func__); /* 减少cpu的套接口数量 */
this_cpu_sub(sockets_in_use, ); /* 容错处理 */
if (!sock->file) {
iput(SOCK_INODE(sock));
return;
} /* 套接口完成关闭,继续执行close系统调用其他流程 */
sock->file = NULL;
}
inet_release负责退出组播组,根据是否开启linger标记来设置延迟关闭时间,并且调用传输层的close函数,对于tcp来说,其调用的为tcp_close;
/*
* The peer socket should always be NULL (or else). When we call this
* function we are destroying the object and from then on nobody
* should refer to it.
*/
int inet_release(struct socket *sock)
{
struct sock *sk = sock->sk; if (sk) {
long timeout; /* Applications forget to leave groups before exiting */
/* 退出组播组 */
ip_mc_drop_socket(sk); /* If linger is set, we don't return until the close
* is complete. Otherwise we return immediately. The
* actually closing is done the same either way.
*
* If the close is due to the process exiting, we never
* linger..
*/
timeout = ; /*
设置了linger标记,进程未在退出,
则设置lingertime延迟关闭时间
*/
if (sock_flag(sk, SOCK_LINGER) &&
!(current->flags & PF_EXITING))
timeout = sk->sk_lingertime;
sock->sk = NULL; /* 调用传输层的close函数 */
sk->sk_prot->close(sk, timeout);
}
return ;
}
tcp_close分析请移步另外一篇文章<TCP层close系统调用的实现分析>;
套接字之close系统调用的更多相关文章
- 套接字之recv系统调用
recv系统调用对sys_recvfrom进行了简单的封装,只是其中不包含地址信息,其只需要从建立连接的另一端接收信息: /* * Receive a datagram from a socket. ...
- 套接字之send系统调用
send系统调用只是对sendto系统调用进行了封装,传递的参数不包含目的地址信息,数据会发送到已经建立连接的另一端的地址: /* * Send a datagram down a socket. * ...
- 套接字之recvmsg系统调用
recvmsg系统调用允许用户指定msghdr结构来接收数据,可以将数据接收到多个缓冲区中,并且可以接收控制信息:接收信息过程与其他接收系统调用核心一致,都是调用传输层的接收函数进行数据接收: SYS ...
- 套接字之recvfrom系统调用
recvfrom系统调用通过用户传入的接收空间构造msghdr,并且调用sock_recvmsg,该函数调用socket操作的recvmsg函数sock->ops->recvmsg,ipv ...
- 套接字之sendmsg系统调用
sendmsg系统调用允许在用户空间构造消息头和控制信息,用此函数可以发送多个数据缓冲区的数据,并支持控制信息:当调用进入内核后,会将用户端的user_msghdr对应拷贝到内核的msghdr中,然后 ...
- 套接字之sendto系统调用
sendto系统调用用于向指定的目的地址发送数据,其系统调用的流程比较容易理解,如下面所示,其主要完成 (1)将用户数据组织成msghdr,(2)而后调用socket操作的sendmsg:ipv4对应 ...
- 套接字之select系统调用
select是IO多路复用的一种方式,用来等待一个列表中的多个描述符的可读可写状态: SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_ ...
- 【 Linux 】Linux套接字简要说明
Linux套接字 源IP地址和目的IP地址以及源端口和目标端口号的组合称为套接字.其作用于标识客户端请求的服务器和服务. 套接字,支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间 ...
- 1、套按字及http基础知识之一
MAC地址:设备到设备之间通信时专用(从源主机到目标主机可能经由N台路由设备)4 IP地址:标记主机到主机之间通信时专用 TCP/UDP :提供进程地址 通过port number来标记 进程地址:用 ...
随机推荐
- java 给定一个日期期间 返回形如Mar 2015 3/20-3/31的数据
最近一个项目中有个前台对于表头要求: 给定一个日期期间返回形如 Mar 2015 3/20-3/31Apr 2015 4/1-4/30 这样的月年数据,简单的写了下代码,暂时没想到更好的办法 例如传进 ...
- CentOS7部署HDP3.1.0.0
Apache Ambari是一个基于Web的支持Apache Hadoop集群的供应.管理和监控的开源工具,Ambari已支持大多数Hadoop组件,包括HDFS.MapReduce.Hive.Pig ...
- N1试卷常考词汇总结
免れる まぬがれる 免去,幸免 軽率 けいそつ 轻率,草率 捩れる ねじれる 拧劲儿,扭歪,弯曲 裂ける さける 裂开,破裂 避ける さける 躲避,避开 つまむ 挟,捏,掐 追及 ついきゅう 追上.追 ...
- Java定义队结构,实现入队、出队操作
package com.example.demo; import java.util.ArrayList; public class Queue { ArrayList<Object> l ...
- Jdk1.8的安装(Linux和windows)
1.1 JDK1.8下载地址 JDK下载:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151. ...
- Linux添加虚拟网卡的多种方法
Linux添加虚拟网卡的多种方法有时候,一台服务器需要设置多个ip,但又不想添加多块网卡,那就需要设置虚拟网卡.这里介绍几种方式在linux服务器上添加虚拟网卡. 我们向eth0中添加一块虚拟网卡: ...
- conda 安装虚拟环境 fastai
一.conda常用命令 1.创建一个虚拟环境env_name,后面跟的是创建这个环境时,同时安装的软件包 conda create -n env_name python=3.6 2.通过克隆创建一个环 ...
- [uboot] (番外篇)uboot之fdt介绍 (转)
以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为例 [uboot] uboot流程系列:[project X] tiny210(s5pv210)上电启动流程(B ...
- 轮子:读取config.ini文件
python: 把config.ini文件成map返回 def get_conf(conf_file): conf = {} ll=list(map(lambda x: x.replace('&quo ...
- WSL中使用npm install报错
报错内容类似下面的格式.具体解决方法请看这里:https://github.com/Microsoft/WSL/issues/14 着重关注 https://github.com/Microsoft/ ...