2007年11月27日 星期二 09:56
2007.1.28
lwip提供三种API:1)RAW API 2)lwip API 3)BSD API。
RAW API把协议栈和应用程序放到一个进程里边,该接口基于函数回调技术,使用该接口的应用程序可以不用进行连续操作。不过,这会使应用程序编写难度加大且代码不易被理解。为了接收数据,应用程序会向协议栈注册一个回调函数。该回调函数与特定的连接相关联,当该关联的连接到达一个信息包,该回调函数就会被协议栈调用。这即有优点也有缺点。优点是既然应用程序和TCP/IP协议栈驻留在同一个进程中,那么发送和接收数据就不再产生进程切换。主要缺点是应用程序不能使自己陷入长期的连续运算中,这样会导致通讯性能下降,原因是TCP/IP处理与连续运算是不能并行发生的。这个缺点可以通过把应用程序分为两部分来克服,一部分处理通讯,一部分处理运算。
RAW API把接收与处理放在一个线程里面。这样只要处理流程稍微被延迟,接收就会被阻塞,直接造成频繁丢包、响应不及时等严重问题。因此,接收与协议处理必须分开。LwIP的作者显然已经考虑到了这一点,他为我们提供了tcpip_input()函数来处理这个问题,虽然他并没有在rawapi一文中说明。讲到这里,读者应该知道tcpip_input()函数投递的消息从哪里来的答案了吧,没错,它们来自于由底层网络驱动组成的接
收线程。我们在编写网络驱动时,其接收部分以任务的形式创建。数据包到达后,去掉以太网包头得到IP包,然后直接调用tcpip_input()函数将其投递到mbox邮箱。投递结束,接收任务继续下一个数据包的接收,而被投递得IP包将由TCPIP线程继续处理。这样,即使某个IP包的处理时间过长也不会造成频繁丢包现象的发生。这就是lwip API。
BSD API提供了基于open-read-write-close模型的UNIX标准API,它的最大特点是使应用程序移植到其它系统时比较容易,但用在嵌入式系统中效率比较低,占用资源多。这对于我们的嵌入式应用有时是不能容忍的。
基于以上的考虑,我决定采用lwip API。嵌入式应用讲求效率高和资源省。谁让我的内存只有32K:-(
2007.1.28
在看懂lwip的工作流程之前我的理解:1.以太网数据的接收作为一个单独的进程,用消息传递的方式通知tcpip进程处理数据。接收进程采用中断触发的方式工作。2.tcpip作为一个进程,连接底层进程和应用层进程。3.每个应用程序作为单独的进程。
尚未理解的地方:1.是否每次接收到数据都创建一个tcpip进程对数据进行处理,在处理完毕之后销毁。还是接收进程把 数据放到lwip缓冲区里,等待tcpip进程处理。
2. 把多个应用程序和lwip采用rawAPI的形式是否能够放到一个进程里面。3.接收进程和tcpip进程能否放入一个进程,可以的话对性能有什么影响??4.lwip对每个网络进程都创建一个定时器结构,它们怎样工作?并且定时器的时钟来源是什么?
2007.1.29
为了节省内存空间,不使用IP碎片的重组。
lwip对存储区的管理堪称经典,其实可以用作操作系统的内存管理,等移植完成后要好好研究,呵呵~~。lwip的存储管理是这样的:收到的pbufs是PBUF POOL类型,发送出的pbufs是PBUF ROM或PBUF RAM类型。PBUF ROM由memp分配struct pbuf,而PBUF RAM和PBUF POOL在它们占用的内存中分配!
2007.1.30
用嵌入式操作系统最难把握的时进程堆栈的大小,要求程序员能较准确地估算,如果在任务中使用递归,必须能够预料最坏情况下的递归层数!最理想的是能够通过一种方法测试出系统占用堆栈的大小,等移植完成可以考虑写一个这样的程序。
2007.3.20
程序老出现预取指错误,我怀疑是信号量或者邮箱的移植出现问题。
2007.3.22
ARP can work now!!ICMP can work now!TCP can work now!lwip终于在我的板子上成功运行了!硬件设计没有任何问题!但从现在ping的数据看来,它的速度还差很远!下一步的工作是对lwip进行优化,让它达到更好的性能!
一个值得高兴的日子!
2007.4.18
配置,还是配置!lwipopts.h!os_cfg.h!
调试程序的时候你一定要做这样的假设:lwip是没有错误的,就算协议栈不能工作也一定是你的配置有问题!
lwip经过无数人的试用,它能保证可以完成你的工作!
2007.4.24
lwip协议栈有自己的内存区,用于协议栈相关变量对内存的使用.因此,在协议栈相关的应用程序中,我们尽量使用这一部分内存. 避免造成内存空间的浪费!并且注意:用完之后一定要释放,否则你不是一个合格的程序员!
为了保护内存缓冲区的完整性,防止因多个进程同时访问破坏数据,lwip使用ucos提供的OS_ENTER_CRITICAL和OS_EXIT_CRITICAL来保护临界资源!当然也可以用信号量来实现,但其效能不如前者!
今天还修正了网上移植代码的一个bug,lwip要求每5秒钟调用一次arp_timer对ARP缓存表中的信息进行更新。但网上的移植代码都没有实现此功能。我通过把arp_timer加入协议栈进程的定时事件中来实现arp_timer事件的定时调用!
2007.4.28:单片机具有I2C功能的管脚是开漏输出,用作GPIO时要加上拉电阻。
TODOs:
1.测试出tcpip进程的堆栈大小。由于我们的内存只有32K,必须充分利用内存,并保证内存不会溢出。
2.测试系统负荷并分配信号量和消息队列的大小。如
果信号量和消息队列用完程序会不会失去响应?
3.测试系统的性能。并发处理能力?
4.sys_arch_mbox_fetch()函数中对OSQPend()进行修改。
5.sys_arch_sem_wait()和sys_arch_mbox_fetch()的返回值应该是多少,这取决于lwip怎样对两者的返回值进行处理,
6.OS_CRITICAL_METHOD宏,将其值改为3,这样与lwip的要求一致。现在OS_CRITICAL_METHOD的值为2.
7.测试驱动程序的性能。
8.解决使用外部中断触发接收数据时的程序死掉的问题。
9.对25P80的访问用信号量来保护,并且由于写操作占用时间比较长,我们可以在系统空闲的时候再进行此操作.有待思考.
10.加入对DHCP的实现.
11.实现双网络接口的冗余切换功能.