阻塞读
ssize_t ret;
vhile (len != 0 && (ret = read(fd, buf, len))!=0) {
if (ret = -1) {
if (errno == EINTR)
continue;
perror("read");
break;
}
len -= ret;
buf += ret;
}
这里处理了5种情况,可以封装为一个新的read函数。
read调用原型
ssize_t read(int fd, void *buf, size_t len);
- 如果返回值 == 0,说明已经达到文件末尾(EOF)[情况1]
- 如果没有数据可读,调用回阻塞(sleep),直到有数据可读
- 如果返回值 < 0,说明读取过程中出错。例如:
- EINTR,表示在读取任何字节之前接收到信号。read调用可以重新执行 [情况2]
- 非EINTR,表示更严重错误,不能重新执行read调用 [情况3]
- 如果返回值 == len,读取的所有len个字节都被保存到buf中 [情况4]
- 如果返回值 > 0 且 < len,有可能:
- 读取过程中信号中断/读取中出错;
- 可读数据大于0字节小于len字节;
- 在读取len之前到达了EOF
- 可以再次执行read调用,把剩余字节读入缓冲区或者给出错误信息 [情况5]
非阻塞读
非阻塞读可以避免没有数据可读时阻塞在哪里,而是立即返回,表示没有数据可读。需要额外检查errno值是否为EAGIN
char buf[BUFFSIZE];
ssize_t nr;
start:
nr = read(fd, buf, BUFFSIZE];
if (nr == -1) {
if (errno == EINTR)
goto start;
if (errno == EAGAIN)
/* resubmit later*/
else
/* error */
}