sys_read(即调用号为0的read系统调用)是 Linux 中的一个基本系统调用,用于从文件描述符中读取数据,并存储在一段指定的内存区域中,返回值为读取到的字节数。
sys_read函数原型
1
ssize_t read(int fd, void *buf, size_t count);
参数
fd: 文件描述符,即指定读取的“源”之所在buf: 缓冲区指针,数据将被读取到这里count: 要读取的最大字节数
返回值
- 成功时返回实际读取的字节数
- 返回0表示已到达文件末尾(
EOF) - 失败时返回
-errno(如EINTR,EBADF)
用例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30.section .data
buffer:
.space 128
.section .text
.globl _start
_start:
# 调用 sys_read 读取数据
mov $0, %rax # 系统调用号 (0 = sys_read)
mov $0, %rdi # 文件描述符 (0 = stdin)
lea buffer(%rip), %rsi # 使得 void * buf = &buffer
mov $128, %rdx # count = 128 (前面定义 buffer 的长度)
syscall # 执行系统调用
# 数据读取完毕,存储在 buffer 中
# 返回值 %rax 为读取的字节长度
mov %rax, %r12 # 备份 %rax 至 %r12
# 调用 sys_write 将刚刚输入的数据打印出来
mov $1, %rax # 系统调用号 (1 = sys_write)
mov $1, %rdi # 文件描述符 (1 = stdout)
lea buffer(%rip), %rsi # 使得void * buf = &buffer
mov %r12, %rdx # 使得 sys_write 输出的长度为前面读取的字节长度
syscall
# 退出程序
mov $60, %rax # 系统调用号 (60 = sys_exit)
xor %rdi, %rdi # return 0
syscall分析:
上述代码演示了如何使用
sys_read系统调用从标准输入(stdin,文件描述符0)读取数据。程序首先定义了一个
128字节的buffer作为存储读取数据的缓冲区。在_start标签处,程序将系统调用号0(sys_read)存入%rax寄存器,将文件描述符0(stdin)存入%rdi,将buffer的地址加载到%rsi,并设置要读取的最大字节数为128。此即为以下代码所指的调用:1
read(0, &buffer, 128);
执行
syscall指令后,系统调用会从标准输入读取用户输入的数据,并将实际读取的字节数存储在%rax中。随后,程序将返回值(读取的字节数)备份到
%r12寄存器,然后准备调用sys_write(系统调用号为1)将读取的数据输出到标准输出(stdout,文件描述符1)。最后,程序调用sys_exit(系统调用号为60)退出,返回值为0表示成功执行。