You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
while (1)
{
ret = read(sock, buf, 64);
if (ret <= 0)
{
break;
}
rt_ringbuffer_put(rx_ring_buf, buf, ret);
}
如果此时对方只发了一次数据,那么线程会一直执行,不会阻塞,导致低优先级线程无法调度。
原因是wiz_recvfrom函数里面有这样一段代码,
uint16_t recvsize = getSn_RX_RSR(socket);
/* receive last transmission of remaining data */
if (recvsize > 0)
{
rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
recv_len = wizchip_recv(socket, mem, len);
if (recv_len > 0)
{
rt_mutex_release(sock->recv_lock);
goto __exit;
}
rt_mutex_release(sock->recv_lock);
}
if (socket_state == SOCK_CLOSED)
{
return 0;
}
else if (socket_state != SOCK_ESTABLISHED)
{
LOG_E("WIZnet receive failed, get socket(%d) register state(%d) error.", socket, socket_state);
result = -1;
goto __exit;
}
while (1)
{
/* wait the receive semaphore */
if (rt_sem_take(sock->recv_notice, timeout) < 0)
{
result = -1;
/* blocking mode will prints an error and non-blocking mode exits directly */
if ((flags & MSG_DONTWAIT) == 0)
{
LOG_E("WIZnet socket (%d) receive timeout (%d)!", socket, timeout);
errno = EAGAIN;
}
goto __exit;
}
else
{
if (sock->state == SOCK_ESTABLISHED)
{
/* get receive buffer to receiver ring buffer */
rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
recv_len = wizchip_recv(socket, mem, len);
if (recv_len < 0)
{
LOG_E("WIZnet socket(%d) receive data failed(%d).", socket, recv_len);
rt_mutex_release(sock->recv_lock);
result = -1;
goto __exit;
}
rt_mutex_release(sock->recv_lock);
}
else if (sock->state == SOCK_CLOSED)
{
result = 0;
goto __exit;
}
break;
}
}
break;
}
这段代码先通过getSn_RX_RSR判断是否有数据,有的话就返回,这就导致第二次read时,getSn_RX_RSR判断到无数据,就到下面的 if (rt_sem_take(sock->recv_notice, timeout) < 0)这,因为这里信号量已经在中断里面释放过了,所以这里是不会阻塞的,从而进入到wizchip_recv函数,而这个函数里面就一直在判断getSn_RX_RSR是否有数,因为对端只发了一次,第一次已经读走了,因此getSn_RX_RSR一直返回0,从而形成无阻赛的死循环。
所以wiz_recvfrom函数应该改进,通过注释(/* receive last transmission of remaining data */)可以看出,是否防止数据读不干净,而这样做的。那么为啥不在wizchip_recv执行完后,再去判断getSn_RX_RSR是否有数,如果有,再释放一次信号量即可
环境:
RT-Thread Studio 2.1.2
wiznet latest
The text was updated successfully, but these errors were encountered:
问题:
TCP通信,当使用单独的线程去收数据时,并且线程里只使用read函数,不使用select函数配合,代码如下:
如果此时对方只发了一次数据,那么线程会一直执行,不会阻塞,导致低优先级线程无法调度。
原因是wiz_recvfrom函数里面有这样一段代码,
这段代码先通过getSn_RX_RSR判断是否有数据,有的话就返回,这就导致第二次read时,getSn_RX_RSR判断到无数据,就到下面的 if (rt_sem_take(sock->recv_notice, timeout) < 0)这,因为这里信号量已经在中断里面释放过了,所以这里是不会阻塞的,从而进入到wizchip_recv函数,而这个函数里面就一直在判断getSn_RX_RSR是否有数,因为对端只发了一次,第一次已经读走了,因此getSn_RX_RSR一直返回0,从而形成无阻赛的死循环。
所以wiz_recvfrom函数应该改进,通过注释(/* receive last transmission of remaining data */)可以看出,是否防止数据读不干净,而这样做的。那么为啥不在wizchip_recv执行完后,再去判断getSn_RX_RSR是否有数,如果有,再释放一次信号量即可
环境:
RT-Thread Studio 2.1.2
wiznet latest
The text was updated successfully, but these errors were encountered: