read() 函数
的介绍
Linux 的 read()
函数简介
read()
是一个 POSIX 标准的系统调用,用于从文件或文件描述符中读取数据。它是用户空间与内核空间交互的重要接口之一。
函数原型
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
fd
: 文件描述符,表示要读取的文件或设备,通常由open()
或其他函数返回。buf
: 缓冲区的指针,用于存储读取到的数据。count
: 要读取的最大字节数。
返回值
- 成功时:
- 返回实际读取的字节数。
- 如果返回值为
0
,表示文件已到达末尾(EOF)。
- 失败时:
- 返回
-1
,并设置errno
,可以通过perror()
或strerror(errno)
查看错误信息。
- 返回
read()
的功能
- 文件读取:
- 从普通文件中读取内容,逐字节传输数据到缓冲区。
- 设备读取:
- 可从设备文件(如
/dev/
下的文件)读取数据,处理硬件事件或状态。
- 可从设备文件(如
- 管道读取:
- 在管道或套接字通信中,
read()
用于接收数据。
- 在管道或套接字通信中,
- 标准输入读取:
- 通过文件描述符
0
,read()
可读取标准输入的数据。
- 通过文件描述符
常见错误及其原因
EINTR
:调用被信号中断,需重试。EBADF
:无效的文件描述符。EFAULT
:buf
指向的内存地址无效。EINVAL
:无效的参数,如文件描述符未配置为可读。EIO
:I/O 错误,通常与硬件问题相关。
注意事项
- 字节数不一定等于请求的字节数:
- 网络、设备文件等读取可能返回比
count
小的字节数,需循环调用read()
读取完整数据。
- 网络、设备文件等读取可能返回比
- 多线程环境:
- 确保线程间对文件描述符的访问互斥。
- 与非阻塞 I/O 配合:
- 如果文件描述符是非阻塞模式,
read()
可能返回0
或-1
(errno
为EAGAIN
或EWOULDBLOCK
),需要检查并重试。
- 如果文件描述符是非阻塞模式,
小结
read()
是 Linux 系统中基本的 I/O 操作接口,用于从文件描述符中读取数据。通过合理使用它,可以完成对文件、设备和网络数据的高效读取。
实例1
ret = read(ts->fd, &ev, sizeof(struct input_event));
这行代码涉及Linux中的 read()
函数,用于从文件描述符中读取数据。让我们逐步拆解其含义:
-
ret
:- 变量
ret
用于接收read()
函数的返回值,表示实际读取到的字节数。如果读取失败,read()
会返回-1
,并设置errno
以指示错误类型。
- 变量
-
read(ts->fd, &ev, sizeof(struct input_event))
:read()
是一个系统调用,用于从文件描述符(fd
)中读取数据。ts->fd
:这是一个文件描述符,通常代表一个已打开的文件、设备或其他资源。在这个例子中,可能是一个输入设备文件(例如/dev/input/eventX
),与 Linux 输入子系统相关。&ev
:这是一个指向内存缓冲区的指针,用于存储读取到的数据。sizeof(struct input_event)
:指定了读取的数据大小,这里等于struct input_event
的大小。
-
struct input_event
:- 这是 Linux 输入子系统中的一个标准结构,定义在头文件
<linux/input.h>
中,通常用于描述输入事件。 - 它的常见字段包括:
struct timeval time
:事件发生的时间戳。__u16 type
:事件的类型,例如按键、鼠标移动等。__u16 code
:事件的具体代码,表示哪个按键或动作。__s32 value
:事件的值,例如按键按下、松开或鼠标位置的变化。
- 这是 Linux 输入子系统中的一个标准结构,定义在头文件
-
代码逻辑的含义:
- 通过调用
read()
,从文件描述符ts->fd
中读取一个输入事件的数据,并存储在ev
结构体中。 - 返回值
ret
:- 如果
ret > 0
:表示成功读取了ret
字节,通常应该等于sizeof(struct input_event)
。 - 如果
ret == 0
:表示文件已到达末尾(对于某些设备文件,这种情况可能不会发生)。 - 如果
ret == -1
:表示发生错误,应检查errno
以获取错误原因。
- 如果
- 通过调用
-
应用场景:
- 这种代码通常出现在处理 Linux 输入设备的程序中,用于读取键盘、鼠标或其他输入设备的事件。
总结:
这行代码的作用是从一个输入设备(通过文件描述符 ts->fd
)读取一个输入事件,将其存储到 ev
变量中,并通过返回值 ret
指示读取结果。