read()系统调用的原型:ssize_t read(int fd, void *buf, size_t count);
功能:从指定的文件描述符中读取最多count个字节的数据到指定的buf中去。如果传入的count是0,这个系统调用什么都不干,直接返回0。如果指定的count大于0,而且返回值也大于0,则表示函数执行成功,返回值表示成功读取的字节数,同时被读取的文件的当前数据指针会相应后移。如果返回值为0,表示遇到了文件结尾。如果读取失败,read()会返回-1,并设置errno。
但是有时候,返回-1并不一定表示文件坏了读不了了,比如:
如果在套接字上设置了O_NONBLOCK属性(非阻塞),而当前套接字上又没有数据可读,那么read()系统调用就会返回EAGAIN或者EWOULDBLOCK,表示暂时读不到东西,稍后再来试吧。
再比如,虽然当前套接字是阻塞模式的,但是设置了发送或接收超时时间,那么read()就会阻塞在套接字上等待数据过来,如果在超时时间内没有拿到任何数据,那么也会收到一个EAGAIN或者EWOULDBLOCK的errno,这时也应该稍后再来重新尝试读取。
另外还要注意,POSIX标准中并没有规定在上面两种情况下应该把errno设置为EAGAIN还是EWOULDBLOCK,实现中设置这两个错误代码都是可以的,所以一个程序要具有更好的适用范围,应该总是把这两个errno放在一起检查。
除此之外,还有一个errno,叫EINTR,表示在读取过程中,在读到数据之前被信号打断了,这时也应该当做正常情况处理,信号处理程序执行完成之后,只要程序还能再回来,就应该当没事一样继续正常的逻辑,重新读一次。
其他一些错误代码就要表示读取失败了,如EBADF,EFAULT,EINVAL,EIO等,具体就请参见帮助手册吧。
用read()系统调用读取本地磁盘设备上的文件时,通常可以认为读取速度是足够快的,因此通常不会设置O_NONBLOCK标志。在有些系统的实现上,设置会让非阻塞标志在处理本地磁盘文件是不生效。
==================== 以下是广告 ====================
更多系统详尽的Linux系统编程内容,欢迎订阅GitChat专栏 《攻克Linux系统编程》