TCP listen 系统调用过程
__sys__listen –> inet_listen –>inet_csk_listen_start–>inet_hash–>__inet_hash
1.在 inet_listen函数中,检查sock状态是否为 TCPF_CLOSE或者TCPF_LISTEN状态,只有这两个状态的sock才能listen。如果已经处于listen状态,则只修改backlog,否则需要执行inet_csk_listen_start函数将sock添加到listen hash table中
2.inet_csk_listen_start函数会改变sock状态,改为TCP_LISTEN状态。
3.inet_hash函数将sock 添加到listen hash table中,备查。如果设置了sk_reuseport标志位,则会调用inet_reuseport_add_sock函数处理reuseport
具体细节可以沿着这个调用栈看代码。
TCP listen 收到 syn包后的执行的动作
tcp_v4_rcv –> tcp_v4_do_rcv –> tcp_rcv_state_process –> tcp_v4_conn_request –> tcp_conn_request –>tcp_v4_send_synack
1.tcp_v4_rcv 函数在listen hash table中找到对应的 sock。调用 tcp_v4_do_rcv函数
2.tcp_v4_do_rcv 函数判断有没有开启tcp cookie。在收到syn 包的过程中 cookie开启不开启没有影响
3.tcp_rcv_state_process函数根据sock状态及 来包状态,决定调用tcp_connect_request函数。
4.tcp_conn_request 函数
a.如果没有开启tcp cookie和fastopen的情况下,会创建一个request_sock的sock,并将sk_state设置为 TCP_NEW_SYN_RECV状态。
b.调用inet_csk_reqsk_queue_hash_add将 req sock 添加到 establish hash table中,并发送 synack。
TCP listen 收到 ack执行动作。
tcp_v4_rcv –> tcp_check_req –> tcp_v4_syn_recv_sock–>tcp_create_openreq_child–>inet_csk_clone_lock
1.tcp_check_req 函数检查ack包是否有问题,并将tcp_v4_syn_recv_sock创建的sock 通过inet_csk_reqsk_queue_add放到 accept队列中。
2.tcp_v4_syn_recv_sock 函数创建child sock。
3. inet_csk_cloen_lock函数会设置child sock 状态为TCP_SYN_RECV
4.最后调用 tcp_child_process,对ack 进行处理,当sock正在被调用时 把包放到backlog里面,否则唤醒listen的进程。
我分析的过程中 忽略了 tcp cookie 和 fastopen。不过主线流程情况以后,这些附加功能可以慢慢通过看代码了解。