阅读和理解用户手册里的函数文档,尤其是像 man 2 stat 这样的系统调用手册,是 Linux/Unix 系统编程的基本功。下面给一套通用方法 + man 2 stat 实例拆解,学会读懂这类文档
一、先搞清楚 man 手册的分区
Linux 的 man 手册分章节,不同章节编号代表不同类型的文档:
| 章节 | 内容类型 | 示例 |
|---|---|---|
| 1 | 用户命令 | man 1 ls |
| 2 | 系统调用(内核API) | man 2 stat |
| 3 | 库函数(C标准库) | man 3 printf |
| 4 | 设备文件 | man 4 tty |
| 5 | 文件格式/协议 | man 5 passwd |
| 7 | 概述、杂项 | man 7 glob |
| 8 | 系统管理命令 | man 8 mount |
man 2 stat 表示查第 2 章 (系统调用)的 stat 函数。
二、通用阅读步骤(以 man 2 stat 为例)
1. 先看 NAME 部分(函数名和基本作用)
STAT(2) Linux Programmer's Manual STAT(2)
NAME
stat, fstat, lstat, fstatat - get file status
- 作用:一句话概括函数功能------获取文件的状态信息(元数据:大小、权限、修改时间等)。
- 这里列出了 4 个相关函数:
stat、fstat、lstat、fstatat,它们的功能类似但适用场景不同。
2. 看 SYNOPSIS 部分(函数原型)
SYNOPSIS
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);
...
- 头文件 :必须包含这些头文件才能使用该函数(
sys/types.h定义类型,sys/stat.h定义struct stat,unistd.h是系统调用惯例)。 - 函数原型 :每个函数的参数和返回值一目了然:
stat:参数是文件路径 (pathname)和存放结果的缓冲区 (statbuf)。fstat:参数是文件描述符 (fd)和缓冲区。lstat:类似stat,但对符号链接的处理不同(后面讲区别)。
3. 看 DESCRIPTION 部分(详细说明)
这是核心,会解释:
- 函数功能细节 :比如
stat返回的是路径名对应的文件 (如果是符号链接,会追踪到目标文件),而lstat返回的是符号链接本身的信息。 - 参数含义 :
pathname:要查询的文件路径(字符串)。statbuf:指向struct stat结构体的指针,函数会把文件状态信息写入这个结构体。
- 返回值 :成功返回 0,失败返回 -1 并设置
errno(错误码)。 - 关键区别 :
statvslstatvsfstat:stat(path, buf):追踪符号链接(如果 path 是软链接,返回目标文件的状态)。lstat(path, buf):不追踪符号链接(返回软链接本身的状态)。fstat(fd, buf):通过已打开的文件描述符fd获取状态(不需要路径)。
4. 看 struct stat 结构体定义(重点!)
在 DESCRIPTION 中会给出结构体成员,或者在手册的其他部分(有时需要往下翻):
The stat structure is defined as follows:
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* file type and mode */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* time of last access */
struct timespec st_mtim; /* time of last modification */
struct timespec st_ctim; /* time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
- 每个字段的含义 :比如
st_size是文件大小(字节),st_mode包含文件类型和权限(需要用宏判断文件类型,如S_ISREG(st_mode)判断是否为普通文件)。 - 时间戳 :
st_atim是最后访问时间,st_mtim是最后修改时间,st_ctim是最后状态改变时间(如权限修改)。
5. 看 RETURN VALUE 部分(返回值说明)
RETURN VALUE
On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
- 成功 → 0;失败 → -1,并通过
errno告知错误原因(如文件不存在、权限不足)。
6. 看 ERRORS 部分(可能的错误码)
ERRORS
EACCES Search permission is denied for one of the directories in the path prefix of pathname.
EBADF fd is not a valid open file descriptor.
EFAULT Bad address.
ELOOP Too many symbolic links encountered while traversing pathname.
ENAMETOOLONG
pathname is too long.
ENOENT A component of pathname does not exist.
...
- 列举了所有可能的错误情况,比如
ENOENT表示文件不存在,EACCES表示权限不足。 - 调试时可以根据
errno的值判断错误原因(用perror或strerror打印)。
7. 看 EXAMPLES 部分(示例代码,有的手册有)
有些函数的 man 页会提供使用示例,比如 stat 可能会有一个简单的 demo:打开文件、调用 stat、打印文件大小。
如果没示例,可以参考网上或自己写测试代码。
8. 看 SEE ALSO 部分(相关参考)
列出相关的函数或手册,比如 stat(2) 的 SEE ALSO 可能有 lstat(2)、fstat(2)、inode(7)(inode 介绍)等,方便深入学习。
三、关键技巧:如何高效抓重点?
- 先看 SYNOPSIS 知道怎么用(函数原型、头文件)。
- 再看 DESCRIPTION 懂功能和参数 (尤其是和其他类似函数的区别,如
statvslstat)。 - 重点看 struct 定义(要知道能获取哪些信息,比如文件大小、权限、时间)。
- 记住 RETURN VALUE 和 ERRORS(写代码时处理成功和失败的情况)。
- 不懂的术语查 SEE ALSO (比如
inode是什么,可以去man 7 inode看)。
四、以 man 2 stat 为例的小练习
假设你要写一个程序,获取当前目录下 test.txt 的大小和修改时间:
- 包含头文件:
#include <sys/stat.h>、#include <unistd.h>。 - 定义
struct stat sb;和char *path = "test.txt";。 - 调用
stat(path, &sb);(检查返回值是否为 -1,处理错误)。 - 用
sb.st_size获取大小,用sb.st_mtim获取修改时间(st_mtim.tv_sec是秒,st_mtim.tv_nsec是纳秒)。
通过这样的步骤,你就能系统地理解任何一个函数手册,并且能正确使用它。核心是不要被大段英文吓到,分模块拆解,抓关键信息。