dev_queue_xmit 函数完成其本层的处理后,调用发送设备device结构的hard_start_xmit指针指向的具体硬件数据发送函数,该函数首先将数据从内核缓冲区复制到网卡设备的硬件缓冲区,操作具体的硬件相关寄存器,由硬件完成最终的发送工作。
以上大致就是系统网络协议栈初始化过程及发送通道和接收通道的建立过程了。
我们最后再捋一捋发送通道和接收通道的区别:
先看下图(显示的目的主机接收到数据包然后到达应用程序的过程,反过来就是从应用程序发送到目的主机物理层网卡设备的过程):
细看这个这个结构,是不是很像一棵倒立的树,如果正立这各结构,这就是成了一棵标准树的结构,每个树节点只有一个父节点,父节点可以有多个子节点。
但这跟网络栈传输数据包有啥关联呢?
ok,我们先看数据包的接收过程(物理层->应用层),从上图,以及结合前面的接收通道分析,由下往上,相当于一棵树从根节点出发到某个叶子节点,中间的某个节点可能有多个子节点,我们就得选择其中一个节点作为途径向下走,同理,协议栈也是这样。
看图,进入的帧经过以太网驱动程序,出现了三条通道,此时就需要证据帧首部中的类型选择走哪个通道(如IP),到了IP层,又出现了四条通道,此时又得根据IP首部中的传输层协议号进行选择,到了传输层就可通过端口号定位到对应应用程序了。所以由下往上有一个根据对应类型进行选择通道的过程;
反过来,数据包的发送则不需要这么麻烦了,因为任意一个子节点都只会有一个父节点,应用程序发送的数据就已经知道是属于哪个协议了,直接进入对应协议的传输层,然后层层往下,不需要一个通道选择的过程了。
较为牵强的白话表述,就是一棵树,从根节点到叶子节点有多条路径,但从叶子节点到根节点是唯一路径。
参考资料《Linux内核网络栈源代码情景分析》