LWIP接收数据阻塞问题
问题现象:
LWIP大概运行一段时间反应就变慢,比如刚开始ping是<1ms, 越到后面就越慢,接近3000ms以上。
有人说内存泄漏的问题。也有人说是移植后驱动的问题。
其实这两种情况都是存在的。
首先实际项目函数参数还是要修改的。 LwIP变慢,很大一部分原因是内存分配的原因。
建议所有与WAITTIME相关的代码都要理解调整下。在实际应用中,WAITTIME跟应用是由很大关系的。有的超时,有的阻塞有的占内存。
第一是ethernetif.c里面的ethernetif_input 函数
{
struct pbuf *p;
for( ;; )
{
if(xSemaphoreTake(s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE)/*此处需要修改*/
{
TRY_GET_NEXT_FRAGMENT:
p = low_level_input( s_pxNetIf );
if (p != NULL) /*此处需要修改*/
{
if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf))
{
pbuf_free(p);
p=NULL;
}
else
{
xSemaphoreTake( s_xSemaphore, 0);
goto TRY_GET_NEXT_FRAGMENT;
}
}
}
}
}
LWIP
1 、所创建的连接的类型,可以取NETCONN_INVALID:NETCONN_TCP、NETCONN_UDP、
NETCONN_UDPLITE、NETCONN_UDPNOCHKSUM、NETCONN_RAW
proto:RAW IP pcb的IP协议
callback:当物理链路有数据接收或发送时调用的回调函数
*2 netconn_peer()和 netconn_addr(),分别
用于获取远程主机的 IP地址信息和本地主机的 IP地址信息
*3 conn: 指定的连接
addr: 该参数为结果参数,存放获取连接的IP地址
port: 该参数为结果参数,存放获取连接的端口号(对于RAW,存放协议类型)
local: 为1表示获取本地主机的IP地址及端口号;为0表示获取远程主机的IP地址及端口号
*4 conn: 准备发送数据的TCP连接
dataptr:指向发送数据缓冲区的指针
size:发送数据的长度。这里对数据长度没有任何限制。这个函数不需要应用程序明确地分配缓冲
区(buffers),因为这可由协议栈来负责
apiflags:可以取 NETCONN_NOCOPY 、NETCONN_COPY 和 NETCONN_MORE 中的一个。当flags值为NETCONN_COPY时, dataptr指针指向的数据将被复制到为这些数据分配的内存缓冲区。这就允许这些数据在函数调用后可以直接修改,但是这会在执行时间和内存使用率方面有所降低。如果 flags 值为 NETCONN_NOCOPY,则数据不会复制而是直接使用 dataptr 指针来引用。这些数据在函数调用后不能被修改,因为这些数据可能会被放在当前指定连接的重发队列,并且会在里面逗留一段不确定的时间。 当要发送的数据在ROM中因而数据不可变时很有用。 而参数NETCONN_MORE则指向上次发送的那个数据段,适用于连续发送数据的情况。。
*5 ERR_OK: 表示查询成功,函数正常返回。
ERR_MEM:内存错误,稍后会重试,重新查询。
ERR_ARG:DNS客户端未初始化或者没有找到合适的主机名。
ERR_VAL:DNS服务器无响应。
*6#define IP4_ADDR (ipaddr, a,b,c,d) \
(ipaddr)->addr = htonl(((u32_t)((a) & 0xff) << 24) | \
((u32_t)((b)& 0xff) << 16) | \
((u32_t)((c)& 0xff) << 8) | \
(u32_t)((d)& 0xff))
lwip的mac地址设定是很重要的,一定要根据地区进行分配。不是随便的一串数字。同局域网MAC地址一定不能重复。不然你ping都可能不通,无法进行通信。