TCP层accept系统调用的实现分析
inet_csk_accept函数实现了tcp协议accept操作,其主要完成的功能是,从已经完成三次握手的队列中取控制块,如果没有已经完成的连接,则需要根据阻塞标记来来区分对待,若非阻塞则直接返回,若阻塞则需要在一定时间范围内阻塞等待;
/*
* This will accept the next outstanding connection.
*/
struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern)
{
struct inet_connection_sock *icsk = inet_csk(sk);
struct request_sock_queue *queue = &icsk->icsk_accept_queue;
struct request_sock *req;
struct sock *newsk;
int error; lock_sock(sk); /* We need to make sure that this socket is listening,
* and that it has something pending.
*/
error = -EINVAL; /* 不是listen状态 */
if (sk->sk_state != TCP_LISTEN)
goto out_err; /* Find already established connection */ /* 还没有已完成的连接 */
if (reqsk_queue_empty(queue)) { /* 获取等待时间,非阻塞为0 */
long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); /* If this is a non blocking socket don't sleep */
error = -EAGAIN;
/* 非阻塞立即返回错误 */
if (!timeo)
goto out_err; /* 等待连接到来 */
error = inet_csk_wait_for_connect(sk, timeo);
if (error)
goto out_err;
} /* 从已完成连接队列中移除 */
req = reqsk_queue_remove(queue, sk); /* 设置新控制块指针 */
newsk = req->sk; /* TCP协议 && fastopen */
if (sk->sk_protocol == IPPROTO_TCP &&
tcp_rsk(req)->tfo_listener) {
spin_lock_bh(&queue->fastopenq.lock);
if (tcp_rsk(req)->tfo_listener) {
/* We are still waiting for the final ACK from 3WHS
* so can't free req now. Instead, we set req->sk to
* NULL to signify that the child socket is taken
* so reqsk_fastopen_remove() will free the req
* when 3WHS finishes (or is aborted).
*/
req->sk = NULL;
req = NULL;
}
spin_unlock_bh(&queue->fastopenq.lock);
}
out:
release_sock(sk); /* 释放请求控制块 */
if (req)
reqsk_put(req); /* 返回找到的连接控制块 */
return newsk;
out_err:
newsk = NULL;
req = NULL;
*err = error;
goto out;
}
如果请求队列中没有已完成握手的连接,并且套接字已经设置了阻塞标记,则需要加入调度队列等待连接的到来,inet_csk_wait_for_connect函数完成了这个功能;
/*
* Wait for an incoming connection, avoid race conditions. This must be called
* with the socket locked.
*/
static int inet_csk_wait_for_connect(struct sock *sk, long timeo)
{
struct inet_connection_sock *icsk = inet_csk(sk);
DEFINE_WAIT(wait);
int err; /*
* True wake-one mechanism for incoming connections: only
* one process gets woken up, not the 'whole herd'.
* Since we do not 'race & poll' for established sockets
* anymore, the common case will execute the loop only once.
*
* Subtle issue: "add_wait_queue_exclusive()" will be added
* after any current non-exclusive waiters, and we know that
* it will always _stay_ after any new non-exclusive waiters
* because all non-exclusive waiters are added at the
* beginning of the wait-queue. As such, it's ok to "drop"
* our exclusiveness temporarily when we get woken up without
* having to remove and re-insert us on the wait queue.
*/
for (;;) { /* 加入等待队列 */
prepare_to_wait_exclusive(sk_sleep(sk), &wait,
TASK_INTERRUPTIBLE);
release_sock(sk); /* 如果为空计算,进行调度 */
if (reqsk_queue_empty(&icsk->icsk_accept_queue))
timeo = schedule_timeout(timeo);
sched_annotate_sleep();
lock_sock(sk);
err = ;
/* 队列不为空*/
if (!reqsk_queue_empty(&icsk->icsk_accept_queue))
break;
err = -EINVAL;
/* 连接状态不是LISTEN */
if (sk->sk_state != TCP_LISTEN)
break;
/* 信号打断 */
err = sock_intr_errno(timeo);
if (signal_pending(current))
break;
err = -EAGAIN;
/* 调度超时 */
if (!timeo)
break;
}
/* 结束等待 */
finish_wait(sk_sleep(sk), &wait);
return err;
}
reqsk_queue_remove函数完成了将完成握手的控制块从请求队列移除的工作;
static inline struct request_sock *reqsk_queue_remove(struct request_sock_queue *queue,
struct sock *parent)
{
struct request_sock *req; spin_lock_bh(&queue->rskq_lock); /* 找到队列头 */
req = queue->rskq_accept_head;
if (req) {
/* 减少已连接计数 */
sk_acceptq_removed(parent);
/* 头部指向下一节点 */
queue->rskq_accept_head = req->dl_next; /* 队列为空 */
if (queue->rskq_accept_head == NULL)
queue->rskq_accept_tail = NULL;
}
spin_unlock_bh(&queue->rskq_lock);
return req;
}
TCP层accept系统调用的实现分析的更多相关文章
- TCP层sendmsg系统调用的实现分析
概述 sendmsg系统调用在tcp层的实现是tcp_sendmsg函数,该函数完成以下任务:从用户空间读取数据,拷贝到内核skb,将skb加入到发送队列的任务,调用发送函数:函数在执行过程中会锁定控 ...
- TCP层recvmsg系统调用的实现分析
概述 recvmsg系统调用在tcp层的实现是tcp_recvmsg函数,该函数完成从接收队列中读取数据复制到用户空间的任务:函数在执行过程中会锁定控制块,避免软中断在tcp层的影响:函数会涉及从接收 ...
- TCP层shutdown系统调用的实现分析
概述 shutdown系统调用在tcp层会调用两个函数,对于ESTABLISHED状态需要调用tcp_shutdown关闭连接,对于LISTEN和SYN_SENT状态则需要以非阻塞模式调用tcp_di ...
- TCP层close系统调用的实现分析
在调用close系统调用关闭套接字时,如果套接字引用计数已经归零,则需继续向上层调用其close实现,tcp为tcp_close:本文仅介绍tcp部分,前置部分请参考本博关于close系统调用的文章: ...
- TCP层bind系统调用的实现分析
说明:该文章中部分代码未能完全理解透彻,可能对您造成误解,请慎读: 并建议您先阅读本博另外一篇文章:<Linux TCP套接字选项 之 SO_REUSEADDR && SO_RE ...
- accept系统调用
/* * For accept, we attempt to create a new socket, set up the link * with the client, wake up the c ...
- Python Tornado框架(TCP层)
Tornado在TCP层里的工作机制 上一节是关于应用层的协议 HTTP,它依赖于传输层协议 TCP,例如服务器是如何绑定端口的?HTTP 服务器的 handle_stream 是在什么时候被调用的呢 ...
- 从Linux源码看Socket(TCP)的accept
从Linux源码看Socket(TCP)的accept 前言 笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情. 今天笔者就从Linux源码的角度看下Serve ...
- accept系统调用内核实现
用户态对accept的标准使用方法: if ((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_siz ...
随机推荐
- 转:git上传本地项目到github
转自:https://blog.csdn.net/Lucky_LXG/article/details/77849212 将本地项目上传到Github(两种简单.方便的方法) 一.第一种方法:首先你需要 ...
- mysql 知识整理
前言 安装 使用 关于mysql程式的linux命令 启动mysqld 检查端口是否运行 查看数据库程式相关信息 查看mysql版本 查看配置文件位置 登陆mysql 修改密码 SQL命令 查看数据库 ...
- 第四篇.python的基础
目录 第四篇.python基础01 1. 变量 2. 常量 3. python变量内存管理 4. 变量的三个特征 5. 花式赋值 6. 注释 7. 数据类型基础 8. 数字类型 9. 字符串类型 10 ...
- sql分页查询(2005以后的数据库)和access分页查询
sql分页查询: select * from ( select ROW_NUMBER() over(order by 排序条件) as rowNumber,* from [表名] where 条件 ) ...
- 分布式系统读写模型中的Quorum机制
分布式系统的设计中会涉及到许多的协议.机制用来解决可靠性问题.数据一致性问题等,Quorum 机制就是其中的一种.我们通过分布式系统中的读写模型来简单介绍它. 分布式系统中的读写模型 分布式系统是由多 ...
- stackstorm docker中配置ssh免密码登录方式
在docker中配置st2的ssh登录方式折腾了好久,今天终于彻底搞懂了如何重启容器后也不丢失之前的配置,只要容器起来后就可以正常ssh 执行st2中的remote-shell-script 和rem ...
- bom and dom
bom:Broswer Object Model: 浏览器对象模型- navigator: 获取客户机的信息(浏览器的信息)document.write(navigator.appName);- sc ...
- BLE 5协议栈-安全管理层
文章转载自:http://www.sunyouqun.com/2017/04/ 安全管理(Security Manager)定义了设备间的配对过程. 配对过程包括了配对信息交换.生成密钥和交换密钥三个 ...
- Oracle11g adump目录下面.aud增长导致空间撑满无法删除导致CRS无法启动的解决方法
[root@node1 adump]# pwd /u01/app/oracle/admin/node/adump 大概有10000个文件 rm -rf * 屏幕显示: -bash: /bin/rm: ...
- TCP协议(包括TCP的连接过程,数据分段,TCP有关服务器优化)
Transmission Control Protocol/Internet Protocol 传输控制协议/因特网互联协议 TCP/IP是一个Protocol Stack(协议栈),包括TCP.IP ...