从linux源码看socket的close

本文详细探讨了Linux下TCP socket的关闭过程,包括主动关闭和被动关闭的四次挥手,重点分析了`close(fd)`在不同阶段的操作,如`tcp_close`和状态迁移。同时讨论了操作系统如何处理大量`close_wait`状态的连接,以及进程关闭和Java GC时如何清理socket资源。
摘要由CSDN通过智能技术生成

从linux源码看socket的close

笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情。上篇博客讲了socket的阻塞和非阻塞,这篇就开始谈一谈socket的close(以tcp为例且基于linux-2.6.24内核版本)

TCP关闭状态转移图:

众所周知,TCP的close过程是四次挥手,状态机的变迁也逃不出TCP状态转移图,如下图所示:
tcp的关闭主要分主动关闭、被动关闭以及同时关闭(特殊情况,不做描述)

主动关闭

close(fd)的过程

以C语言为例,在我们关闭socket的时候,会使用close(fd)函数:

int    socket_fd;
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
...
// 此处通过文件描述符关闭对应的socket
close(socket_fd)

而close(int fd)又是通过系统调用sys_close来执行的:

asmlinkage long sys_close(unsigned int fd)
{
	// 清除(close_on_exec即退出进程时)的位图标记
	FD_CLR(fd, fdt->close_on_exec);
	// 释放文件描述符
	// 将fdt->open_fds即打开的fd位图中对应的位清除
	// 再将fd挂入下一个可使用的fd以便复用
	__put_unused_fd(files, fd);
	// 调用file_pointer的close方法真正清除
	retval = filp_close(filp, files);
}
	

我们看到最终是调用的filp_close方法:

int filp_close(struct file *filp, fl_owner_t id)
{
	// 如果存在flush方法则flush
	if (filp->f_op && filp->f_op->flush)
		filp->f_op->flush(filp, id);
	// 调用fput	
	fput(filp);
	......
}

紧接着我们进入fput:

void fastcall fput(struct file *file)
{
	// 对应file->count--,同时检查是否还有关于此file的引用
	// 如果没有,则调用_fput进行释放
	if (atomic_dec_and_test(&file->f_count))
		__fput(file);
}

同一个file(socket)有多个引用的情况很常见,例如下面的例子:
所以在多进程的socket服务器编写过程中,父进程也需要close(fd)一次,以免socket无法最终关闭

然后就是_fput函数了:

void fastcall __fput(struct file *file)
{
	// 从eventpoll中释放file
	eventpoll_release(file);
	// 如果是release方法,则调用release
	if (file->f_op && file->f_op->release)
		file->f_op->release(inode, file);
}

由于我们讨论的是socket的close,所以,我们现在探查下file->f_op->release在socket情况下的实现:

f_op->release的赋值

我们跟踪创建socket的代码,即

socket(AF_INET, SOCK_STREAM, 0);
	|-sock_create  // 创建sock
	|-sock_map_fd  // 将sock和fd关联
			|-sock_attach_fd
					|-init_file(file,...,&socket_file_ops);
							|-file->f_op = fop; //fop赋值为socket_file_ops

socket_file_ops的实现为:

static const struct file_operations socket_file_ops = {
	.owner =	THIS_MODULE,
	......
	// 我们在这里只考虑sock_close
	.release =	sock_close,
	......
};

继续跟踪:

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值