Giter VIP home page Giter VIP logo

github_pages's Introduction

ViewCount

I'm a graduate student at ustc. Currently I'm taking Web Systems class and learning rust go etc. I write logs about opinions, guides, and tutorials about various technologies on my blog.

2024 Resolution is to learn Functional Programming, and get better hold of Linux kernel.

github_pages's People

Watchers

 avatar

github_pages's Issues

TCP/IP协议栈源码分析

inet_init是如何被调用的?从start_kernel到inet_init调用路径

start_kernel 函数在 init/main.c 文件中定义,它是内核启动的入口点。
在 start_kernel 中,会调用 rest_init,这是一个初始化函数,它在 kernel/init.c 文件中定义。
rest_init 会调用 kernel_init_freeable,这是另一个初始化函数,它在 kernel/init.c 文件中定义。
kernel_init_freeable 中会调用 net_init,这是网络初始化的入口点,它在 net/core/sock.c 文件中定义。
net_init 会调用 inet_init,这是初始化TCP/IP协议栈的函数,它在 net/ipv4/af_inet.c 文件中定义。

跟踪分析TCP/IP协议栈如何将自己与上层套接口与下层数据链路层关联起来的?

协议上下都通过TCP/ IP相关联。
TCP/IP协议栈通过一系列的数据结构和函数调用来实现与上层套接口(如应用层)和下层数据链路层的关联。以下是TCP/IP协议栈中一些关键组件和它们如何相互关联的概述:

  1. 套接口(Socket)

    • 套接口是应用层与网络协议栈之间的接口。在Linux中,套接口通常通过系统调用 socket 创建。
    • 套接口提供了一组API,如 bind, listen, connect, accept, send, recv 等,这些API允许应用层发送和接收数据。
  2. 协议族(Protocol Family)

    • 当创建套接口时,需要指定协议族,如 AF_INET(IPv4)或 AF_INET6(IPv6)。
    • 协议族定义了数据包的格式和地址结构。
  3. 协议(Protocol)

    • 在创建套接口时,还需要指定协议,如 SOCK_STREAM(TCP)或 SOCK_DGRAM(UDP)。
    • 协议定义了数据传输的方式,如可靠性、顺序等。
  4. 网络核心API

    • 网络核心API,如 inet_sendmsginet_recvmsg,提供了与套接口API交互的接口。
    • 这些API处理套接口数据的发送和接收,并将数据传递给相应的协议层。
  5. 协议层处理

    • TCP/IP协议栈中的每个协议层(如TCP、IP)都有自己的处理函数。
    • 当数据从应用层通过套接口发送时,它会经过协议层的处理,如TCP层的 tcp_sendmsg,然后传递给IP层。
    • 在接收数据时,数据首先由IP层处理,然后传递给TCP层的 tcp_recvmsg,最后传递给应用层。
  6. 数据链路层

    • IP层将数据封装成IP数据包,然后传递给网络设备驱动程序。
    • 网络设备驱动程序将IP数据包封装成数据链路层的帧,并发送到物理网络上。
  7. 路由和ARP

    • 在发送数据包之前,内核会查询路由表以确定数据包的下一跳。
    • 如果下一跳不在本地网络中,内核会通过ARP协议解析下一跳的MAC地址。
  8. 网络设备驱动程序

    • 网络设备驱动程序负责与物理网络接口通信,发送和接收数据包。

通过这些组件和它们的交互,TCP/IP协议栈实现了从应用层到数据链路层的完整通信路径。在实际的Linux内核源代码中,这些组件的实现可能会更加复杂,并且涉及到更多的细节。

TCP的三次握手源代码跟踪分析

TCP三次握手涉及的函数通常在 net/ipv4/tcp_ipv4.c 文件中。
tcp_v4_connect 函数处理连接请求,它调用 tcp_create_openreq_child 创建一个新的连接请求。
tcp_create_openreq_child 创建一个新的 struct request_sock 实例,并调用 tcp_v4_send_syn 发送SYN包。
tcp_v4_send_syn 设置SYN标志位并发送SYN包。
tcp_v4_send_synack 在接收到SYN包后发送SYN-ACK包。
tcp_v4_do_rcv 处理接收到的TCP段,根据状态机进行状态转换。

send在TCP/IP协议栈中的执行路径

send 函数在用户空间通过系统调用 sys_sendto 或 sys_sendmsg 实现。
在内核空间,sys_sendto 或 sys_sendmsg 调用 inet_sendmsg。
inet_sendmsg 调用 tcp_sendmsg,然后是 tcp_write_xmit。
tcp_write_xmit 封装数据成TCP段,并通过 ip_local_out 发送。

recv在TCP/IP协议栈中的执行路径

recv 函数在用户空间通过系统调用 sys_recvfrom 或 sys_recvmsg 实现。
在内核空间,sys_recvfrom 或 sys_recvmsg 调用 inet_recvmsg。
inet_recvmsg 调用 tcp_recvmsg,然后是 tcp_prequeue_process。
数据被接收后,通过 sk_filter_trim_cap 等函数进行过滤,然后传递给应用层。

路由表的结构和初始化过程

路由表由 struct fib_table 和 struct fib_info 表示,这些结构体在 net/ipv4/fib_semantics.h 文件中定义。
初始化过程在 fib_net_init 函数中进行,这个函数在 net/ipv4/fib_main.c 文件中定义。

通过目的IP查询路由表的到下一跳的IP地址的过程

在Linux网络核心中,查询路由表以找到目的IP地址的下一跳IP地址的过程涉及以下几个关键步骤:

  1. 路由表查找

    • 当数据包到达网络核心时,内核会首先查找路由表以确定数据包的下一跳。
    • 路由表是由struct fib_table结构体表示的,它包含了一系列的路由规则,每个规则由struct fib_info结构体表示。
  2. 最长前缀匹配(LPM)

    • 内核使用最长前缀匹配算法来查找与目的IP地址匹配的最长前缀。
    • 这个过程通常在fib_lookup函数中完成,该函数在net/ipv4/fib_semantics.c文件中定义。
  3. 路由选择

    • 如果找到了匹配的路由,内核会根据路由规则选择下一跳的IP地址。
    • 路由规则可能包括直接连接的网络接口、远程网络的网关地址等。
  4. ARP解析

    • 如果下一跳是远程网络,内核会通过ARP协议解析下一跳的MAC地址。
    • ARP请求由arp_send_request函数发送,该函数在net/ipv4/arp.c文件中定义。
  5. 数据包封装

    • 一旦确定了下一跳的IP地址和MAC地址,数据包就会被封装成适当的数据链路层帧。
    • 在IPv4中,这通常涉及到dev_hard_headerskb_push等函数。
  6. 数据包发送

    • 最后,封装好的数据包会被发送到网络接口,由网络设备驱动程序处理。

这个过程涉及到多个内核模块和函数,它们协同工作以确保数据包能够正确地路由到目的地。在实际的Linux内核源代码中,这些步骤可能会更加复杂,并且涉及到更多的细节和错误处理逻辑。

##ARP缓存的数据结构及初始化过程

ARP缓存使用 struct arp_table 数据结构表示,这个结构体在 net/ipv4/arp.h 文件中定义。
初始化过程在 arp_init 函数中进行,这个函数在 net/ipv4/arp.c 文件中定义。

如何将IP地址解析出对应的MAC地址

将IP地址解析为MAC地址的过程涉及发送ARP请求,这在 net/ipv4/arp.c 文件中的 arp_send 函数中实现。

void arp_send(int type, int ptype, __be32 dest_ip,
	      struct net_device *dev, __be32 src_ip,
	      const unsigned char *dest_hw, const unsigned char *src_hw,
	      const unsigned char *target_hw)
{
	arp_send_dst(type, ptype, dest_ip, dev, src_ip, dest_hw, src_hw,
		     target_hw, NULL);
}

可以看到相应的封装

跟踪TCP send过程中的路由查询和ARP解析的最底层实现

在 tcp_write_xmit 中,数据被封装成TCP段。
然后调用 ip_local_out 进行路由查询,这在 net/ipv4/ip_output.c 文件中的 ip_local_out 函数中实现。
如果目标IP地址不在本地网络中,内核会调用 arp_send_request 来解析目标IP地址对应的MAC地址,这在 net/ipv4/arp.c 文件中的 arp_send_request 函数中实现。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.