公开学习文档

公开学习文档


accept

<h2>概述</h2> <p>1、从全连接队列中取出队头的连接,并返回对应的子 sk,并释放 request_sock 对象</p> <h2>分析</h2> <p>应用原型:</p> <pre><code class="language-c">int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);</code></pre> <p>系统调用代码:</p> <pre><code class="language-c">// file: net/socket.c SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr, int __user *, upeer_addrlen) { return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0); } </code></pre> <h2>核心</h2> <p>中间源码没有找到,直接分析核心逻辑吧:</p> <pre><code class="language-c">// file: net/ipv4/inet_connection_sock.c /* * This will accept the next outstanding connection. */ struct sock *inet_csk_accept(struct sock *sk, int flags, int *err) { struct inet_connection_sock *icsk = inet_csk(sk); struct request_sock_queue *queue = &amp;amp;icsk-&amp;gt;icsk_accept_queue; // 接收队列 struct sock *newsk; struct request_sock *req; int error; lock_sock(sk); /* We need to make sure that this socket is listening, * and that it has something pending. */ error = -EINVAL; if (sk-&amp;gt;sk_state != TCP_LISTEN) // 状态检查 goto out_err; /* Find already established connection */ if (reqsk_queue_empty(queue)) { long timeo = sock_rcvtimeo(sk, flags &amp;amp; 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); // 从队头取出一个连接 newsk = req-&amp;gt;sk; // 这是子连接。在第 3 次握手时添加到全连接队列时设置的 sk_acceptq_removed(sk); // 即 sk-&amp;gt;sk_ack_backkog--; if (sk-&amp;gt;sk_protocol == IPPROTO_TCP &amp;amp;&amp;amp; queue-&amp;gt;fastopenq != NULL) { spin_lock_bh(&amp;amp;queue-&amp;gt;fastopenq-&amp;gt;lock); if (tcp_rsk(req)-&amp;gt;listener) { /* We are still waiting for the final ACK from 3WHS * so can't free req now. Instead, we set req-&amp;gt;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-&amp;gt;sk = NULL; req = NULL; } spin_unlock_bh(&amp;amp;queue-&amp;gt;fastopenq-&amp;gt;lock); } out: release_sock(sk); if (req) __reqsk_free(req); // 释放 request_sock 对象 return newsk; // 返回子 sk out_err: newsk = NULL; req = NULL; *err = error; goto out; } EXPORT_SYMBOL(inet_csk_accept); </code></pre>

页面列表

ITEM_HTML