一、EINTR
二、EAGAIN、EWOULDBLOCK
#define EAGAIN 11 /* Try again */
#define EWOULDBLOCK EAGAIN /* Operation would block */
- 功能:一般用到非阻塞模式下返回的错误码
- 非阻塞模式可参阅:https://blog.csdn.net/qq_41453285/article/details/89856558
- 具体什么含义就要看你调用的接口了,例如:
- recv()、recvmsg()等接收数据的函数:在非阻塞模式下,没有数据可读,那么就返回-1并将errno设置为EAGAIN或EWOULDBLOCK
- send()、sendmsg()等接收数据的函数:在非阻塞模式下,没有数据可发送,那么就返回-1并将errno设置为EAGAIN或EWOULDBLOCK
- 对某些操作来说,资源短暂不可用。例如fork函数可能返回这个错误(当没有足够的资源能够创建一个进程时),可以采取的操作是休息一段时间然后再继续操作
- 错误处理:
- 最好的办法是重试,重试一定次数后还不成功就退出操作
- 为什么不能无限重试呢?假设在通过socket发送一段数据,发送缓冲区如果一直不可写,就会出现无限循环的情况,进程卡死
情景分析①
- 例如在epoll()中,当有一个套接字事件变为EPOLLIN时,程序调用recv()去读取数据,但是recv()返回-1,并且错误码为EAGAIN,说明没有数据可读
- 为什么epoll_wait()检测到套接字事件变为EPOLLIN,但是recv()的时候数据又没有了呢?可能有多个线程调用recv()在同一个套接字上读取数据,在当前线程epoll_wait()返回与调用recv()之间,recv()的数据被另外一个线程的recv()读取完了,因此epoll_wait()检测到EPOLLIN,但是读取的时候数据却变为空
while(1)
{
int rc = epoll_wait(xxx)
if(rc > 0)
{
for(int i = 0; i < rc ; ++i)
{
rc = recv()
if(rc < 0)
{
if(errono == EAGAIN || errno == EWOULDBLOCK)
continue;
}
}
}
}