sys_stat (调用号为4)、sys_fstat (调用号为5)和 sys_lstat (调用号为6)是 Linux 系统中的三个基本文件状态查询系统调用,用于获取文件的元信息(如大小、权限、时间戳等)。
这三个系统调用虽然都用于获取文件元信息,但三者仍然存在明显的不同。sys_stat 和sys_lstat都是通过文件的路径对文件进行访问的,而sys_fstat 却是通过文件描述符fd 对某一文件进行访问。与sys_stat相比,sys_lstat 虽然也通过文件的路径对文件进行访问,但在处理符号链接的方式上有很大的区别。前者查询到符号链接时,会对其所指向的那个目标文件进行查询;而后者则会对符号链接这个文件本身进行查询,并不会重定向至符号链接所指向的那个文件。
无论是这三者中的哪一个,返回元信息的结构体struct stat 的定义都是一致的。struct stat 被定义为:
1 | struct stat { |
sys_stat函数原型
1
int stat(const char *pathname, struct stat *statbuf);
参数
pathname: 要查询的文件路径(字符串)statbuf: 指向struct stat结构的指针,用于存储文件信息
返回值
- 成功时返回
0 - 失败时返回
errno(如ENOENT,EACCES,ENOTDIR)
- 成功时返回
sys_fstat函数原型
1
2int fstat(int fd, struct stat *statbuf);
参数
fd: 已打开文件的文件描述符statbuf: 指向struct stat结构的指针,用于存储文件信息
返回值
- 成功时返回
0 - 失败时返回
errno(如EBADF,EFAULT)
- 成功时返回
sys_lstat函数原型
1
2int lstat(const char *pathname, struct stat *statbuf);
参数
pathname: 要查询的文件路径(字符串)statbuf: 指向struct stat结构的指针,用于存储文件信息
返回值
- 成功时返回
0 - 失败时返回
errno(如ENOENT,EACCES,ENOTDIR)
- 成功时返回
用例
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
31
32
33
34
35
36
37.equ SYS_STAT, 4 # sys_stat 系统调用号
.equ SYS_FSTAT, 5 # sys_fstat 系统调用号
.equ SYS_LSTAT, 6 # sys_lstat 系统调用号
.section .data
filename:
.ascii "/tmp/test.txt"
statbuf:
.space 144 # struct stat 通常为 144 字节(x86-64)
.section .text
.globl _start
_start:
# 使用 sys_stat 查询文件状态
mov $SYS_STAT, %rax
lea filename(%rip), %rdi
lea statbuf(%rip), %rsi
syscall
# 使用 sys_fstat 查询已打开文件描述符状态
# 假设文件描述符保存在 %r8
mov $SYS_FSTAT, %rax
mov %r8, %rdi
lea statbuf(%rip), %rsi
syscall
# 使用 sys_lstat 查询符号链接状态
mov $SYS_LSTAT, %rax
lea filename(%rip), %rdi
lea statbuf(%rip), %rsi
syscall
# 退出
mov $60, %rax
xor %rdi, %rdi
syscall分析:
sys_stat根据文件路径获取目标文件的状态信息,如果路径是符号链接,它返回链接指向文件的信息。sys_fstat直接通过文件描述符获取文件状态,不依赖文件路径。sys_lstat类似于stat,但如果路径是符号链接,它返回链接本身的信息而不是目标文件。
在汇编中,这三个系统调用都通过
%rax指定系统调用号,文件路径或文件描述符通过%rdi,struct stat结构指针通过%rsi,调用syscall指令执行系统调用,返回值存放在%rax:成功为0,失败为-errno。