read函数详解

说明:本文主要是对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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
int res=0;
char buffer[64] ="";
int fp = open("./test.txt", O_RDONLY);//只读模式打开文件
res=read(fp,buffer,60);
printf("read %d bits,they are %s\n",res,buffer);
printf("%s\n",strerror(errno));
close(fp);
return 0;
}
1
2
test.txt的内容:
123
1
2
3
4
运行结果:
read 4 bits,they are 123

Success