RT_Thread下的LWIP传递机制

最近在移植新网卡驱动的时候学习了下TCP/IP的协议栈的框架模型做一个总结
1、硬件相关:硬件使用Emac+DMA
2、软件相关:RTT+LWIP

测试环境搭建:使用一台PCIP地址为192.168.1.5,板子IP地址搞成192.168.1.60,路由器为192.168.1.1在一个子网下进行通信。使用wireshark 抓包,PC ide JATG接口进行 DEBUG。追踪一个UDP报文的输入,以此窥见整体的软件框架架构。

构造数据发送接收流程:PC->网卡到路由器->路由器转发之->板子接收。
数据如下:



首先是中断,以太网最最底层的物理层中断,提示以太网接收到数据包,这时候数据报文是最完整的一帧如下:

所上面所谓的Frame就是这一层接收到的,从上面可见TCP/IP是严格的分层处理的, 下面也会从代码上看出来,确实是分层的。这一层接收到的数据是RAW数据,这完全取决于驱动层是否稳定可靠,有很多人在这里就栽跟头,最后搞的什么PING 不通啦,死机啦等等我也栽跟头了,最近的就是ARP广播的问题。所以驱动层是整个协议栈的的基石。最好建议使用大神写的代码或者固件库来弄,自己那两下子,就别比比了。OK只要你能正确的接收网络上的包这一层就OK,
下面是流程:

一、网络接口层的处理

start A :
{
1、以太网中断,证明有数据包到来,这时候第一件事是读取数据包,由于有操作系统支撑,那好建立一个RX线程来处理这个事件。

以太网的中断处理
{
ETH_IRQHandler
1、post a RXmbox to RX thread
}

接收线程
{
1、挂起到 RXmbox 上(if 没有邮箱到来--死等)
2、调用物理层读取报文到pbuf中,这里注意pbuf是从内存中动态开辟出来的。还有一点就是收发是俩线程记得加互斥锁哦。返回指针P
这个指针P承载着所有的收进来的数据,完全copy到内存中了,长度就是数据包的长度。也就是系统给分配内存了。这个数据包开始在系统中生存。这很重要,标志这这就是一头猪要杀掉吃肉了。光有指针不够,必须有个结构来记录,所以就是pbuf来记录进来的包。
3、交给TCPIP协议栈的物理层进行处理。物理层其实做的活很简单:




物理层就是判断是什么类型的包,是ARP的话交给ARP处理,是IP的话交给IP层处理,什么也不是就释放掉Pbuf记录的包,UDP数据是IP的类型,所以执行


:更新ARP表的。
这个是去除MAC地址的,也就是
这一层里面描述的,其实也不是去掉,只是指针向后移动了避开了这些字段,也就是所谓的 指针。修改了长度字段等,这样上层就可以只处理上面的了。
这个才是最终的数据包去向哦!!!那么他去哪里了呢?继续

显然他来到了一个边界,线程的边界,可以看出他分配了一个 类型的消息,然后用 加载了PBUF的所有数据(哪有数据啊,其实就是指向那个BUF的指针而已,说白了他传递的就仅仅是是指针而已,通过指针的索引可以找到所有的数据)最后用 投递了出去。

这就是接收线程的最后了,他做完这些就又回到原来的邮箱等待了。等待下一个数据的到来,然后做重复的动作,就是这样。
他承担了底层数据的读取,和简单的封装分拣,然后投递到邮箱中通知TCPIP的主线程准备工作。

end A

二:TCPIP线程的处理
start B:
是时候进入TCPIP主线程了,所有的调度都在这里进行。他的工作室这样的
首先是挂起到这里,因为A段说到已经post了一个邮箱,所以这里立马激活运行,乡下
这个类型一定是 所以
执行到这里

从上面可见TCPIP线程取出来了先前加入的原始数据报文的指针P和网络接口的记录。这个netif不用理会,想想为网卡的一种抽象即可.关键是P指针。
输入进 ,最后 释放掉了这则消息。因为已经用完了,这里中断是进入了网络层了。也就是IP层
就是这一层哦。
这里面各种检测判断,各种的检查啊,主要是第一检测这个IP报文的IP地址是不是给我们,是就传给山层,不是就转发,还有一些校验和的判断也在这里进行。还有一点在这里执行的是释放了一部分pbuf,节省了内存,这个不是和上次单纯移动指针,而是真的去除用不到的buf,只保留IP和以上层的数据。
这个里面处理多了去了,DHCP.ICMP,IGMP,RAW,一堆的最终归宿一定是这个 输入的是个UDP包。所以就是继续向下
哎呀我去,这个 里面又来了,各种的判断,各种的异常处理,各种的检测,不过简而言之就是一句话只要不是我的我不要,是我的当然我还要看看校验和对不对,对那好,又会来了一个最终的归宿这里
这个是什么?显然像个函数,实际上是个指针函数,他指向哪里了?。。。。。 旺旺~~~冒金星了。不知道他指向哪里了,
实际上这些指针也好结构也罢,你要知道他去哪里就要找到他的源头,他的源头句柄是PCB,那么PCB在哪里?PCB和SOCKET有什么联系肯定有联系,然后转而去找pcb的建立,从socket开始找最后找到一个这个玩意

然后在向里面就是 这下找到啦
最终

这个函数就是上面的下一步哦,goon ....
在这里面又会分配
这个玩意出来,

对他进行了这些操作,
啊,原来他是来描述接收到的这个UDP数据包的呀。看下面传递上来的指针P又被赋给了他,庄户人拉呱:倒三把了。
在向下就是这一端的终点了哦

这个就是TCPIP和应用层的交互邮箱,著名的 邮箱了,据说很多大神对此都很有研究。我这菜比也见了见,不错不错。
这只是见了见,你知道他在哪里?于是乎还得找,他在这里


这个邮箱实在conn初始化的时候被创建了,围绕着这个邮箱的size,我认为邮箱尺寸要尽量的大一点才好呢。


end B
三、应用层处理
start C
至于应用线程,直接说他是挂起在 这个邮箱上的,他会做自动的数据COPY,把UDP描述记录中的内容自动复制你提供的内存中,然后结束PBUF的使命,杀掉他。释放内存,然后你从你指定的那块缓存中取出数据就可以完成一个UDP数据包的接收,就这么简单,这就是事实,事实就是这样!


接收到32字节的数据,处理吧!!!!!!!!!!!!!!!!!!!!!!#¥!@#%¥%¥……
end C



发送是主动的会简单一些,和接收互逆,只是添加构建一些头,主要还是接收这一块,通过分析可见,TCPIP协议栈对接收到的数据报文进行层层的剥皮,检查,就像剥一个鸡蛋一样,一层层的去掉,最后取出蛋黄放在口里。那个recv就是回调。其他的mbox和recvbox是承上启下的。
TCP的要复杂一些,不过根本框架是一样的哦。
ICMP报文,到不了这里到IP层就会被自动转发出去了,
ARP层直接到不了IP层在早就转发走了。

TCPIP协议栈传递的就是一个pbuf指针,直到应用程序copy完毕数据,当然其他的异常什么的除外了。
对TCPIP协议的我们可以用到其他的一些通信中,主要是学习他的这种框架,和机制。是程序就有BUG,只能说是水太深,我太菜,没有什么了!

你可能感兴趣的:(实时操作系统RT_Thread)