说明:本文主要是对man 帮助文档和《linux程序设计》第四版的摘录,部分理解来源于个人,请酌情参考。
接着上一篇的write,我们来学习一下read。
Read
系统调用read的作用是:从与文件描述符fd相关联的文件中读取 n bytes个字节的数据。并把它放入到数据区buf中。
概要:
read函数在<unistd.h>
头文件中定义。
原型是:ssize_t read(int fd, void *buf, size_t count);
说明:
read()函数尝试从文件描述符fd中读取count个字节到buf开头的缓冲区中。
如果count=0;read返回0,并且没有其他结果,如果count>SSIZE_MAX,结果未指定。
ssize_t:有符号整型,与long类似。typedef long size_t
size_t:无符号的ssize_t,:typedef unsigned long size_t
返回值
调用成功返回读取的字节数,文件指示符指到对应的位置。这个返回值可能会比count,比如以下情况:
当文件的整体字节比count小时,读到文件尾。
我们从管道或者终端读取
我们读取时被一个信号打断了等等情况。
调用失败的时候返回-1;并且errno会被设置,这时候文件的指示符位置变化与否是未知的。
可能出现的错误值有:
EAGAIN:文件描述符指向一个非套接字的文件,并且已经被标记为非阻塞。这时候如果读阻塞,返回这个错误。
EAGAIN /EWOULDBLOCK:文件描述符指向一个套接字的文件,并且已经被标记为非阻塞。然后发生读阻塞。这两个错误码都有可能会被设置,所以在检查的时候应该二者都检查。
EBADF:fd不是一个有效的文件描述符,或者没有打开。
EFAULT :buf在你可以访问的地址空间之外
EINTR :读取被一个信号打断。
EINVAL:fd指向的文件是一个不稳定的读取对象,或者文件在打开的时候带有O_DIRECT标志,或者buf,count指定的值,当前文件的便宜位置没有适当的对齐。
如果文件是通过timerfd_create()创建的,并且buf的大小错。
EIO:I/O错误。例如,当进程处于后台进程组中,试图从它的控制tty读取时,或者忽略SIGTTIN时,阻塞SIGTTIN时,或者它的进程组成为孤儿时,就会发生这种情况。当从磁盘或磁带读取时存在低级I/O错误时,也可能发生这种情况。
EISDIR:fd指向一个目录。
其他错误可能会发生,这取决于连接到FD的对象。POSIX允许在读取某些数据之后中断的read()返回-1(errno设置为EINTR)或返回已经读取的字节数。
测试代码
1 |
|
1 | test.txt的内容: |
1 | 运行结果: |