什么是 unistd.h?
unistd.h 是一个在 POSIX (Portable Operating System Interface) 标准中定义的头文件,POSIX 是一套为 Unix 和类 Unix 操作系统(如 Linux, macOS, BSD 等)设计的 API 规范。

unistd.h 的名字来源于 "Unix Standard",它提供了一组标准的、与 Unix 系统调用相关的函数、宏和常量,这个头文件是 C 语言在 Unix-like 环境下进行底层编程的基石之一。
核心要点:
- 平台相关: 它主要存在于 Unix-like 系统中,在 Windows 系统上,你找不到这个头文件(Windows 有自己的 API,如
windows.h)。 - 提供系统调用接口: 它封装了操作系统内核提供的许多基本功能,如文件 I/O、进程控制、内存管理、用户信息等。
为什么需要 unistd.h?
在 C 语言标准库(如 stdio.h)出现之前,程序与操作系统的交互直接通过系统调用完成。unistd.h 将这些系统调用封装成了更易于使用的 C 函数。
当你想从文件中读取数据时:

- 底层方式: 使用
read()系统调用(由unistd.h提供)。 - 高层方式: 使用
fread()函数(由stdio.h提供)。
fread() 内部最终还是调用了 read(),但 fread 提供了缓冲机制,效率更高,接口更友好。unistd.h 提供的是更“原生”、更“底层”的访问方式。
unistd.h 中包含哪些常用内容?
unistd.h 内容非常丰富,这里列出一些最常用和最重要的函数和宏。
文件 I/O
-
int close(int fd);- 功能: 关闭一个文件描述符。
fd是一个非负整数,代表一个打开的文件、管道或套接字。 - 示例:
close(1);会关闭标准输出。
- 功能: 关闭一个文件描述符。
-
ssize_t read(int fd, void *buf, size_t count);
(图片来源网络,侵删)- 功能: 从文件描述符
fd中读取最多count个字节到缓冲区buf。 - 返回值: 成功返回读取的字节数(可能小于
count),到达文件尾返回 0,出错返回 -1。
- 功能: 从文件描述符
-
ssize_t write(int fd, const void *buf, size_t count);- 功能: 从缓冲区
buf中写入最多count个字节到文件描述符fd。 - 返回值: 成功返回写入的字节数,出错返回 -1。
- 功能: 从缓冲区
-
off_t lseek(int fd, off_t offset, int whence);- 功能: 移动文件指针的当前位置。
whence可以是SEEK_SET(从文件头开始),SEEK_CUR(从当前位置开始),SEEK_END(从文件尾开始)。- 返回值: 成功返回新的文件指针位置,出错返回 -1。
进程控制
-
pid_t fork(void);- 功能: 创建一个新进程(称为子进程),这是 Unix 系统中实现多进程的关键。
- 返回值:
- 在父进程中,返回子进程的 PID (Process ID)。
- 在子进程中,返回 0。
- 如果失败,返回 -1。
- 示例: 经典的 "Hello, world!" 多进程程序。
-
pid_t getpid(void);- 功能: 获取当前进程的 PID。
-
pid_t getppid(void);- 功能: 获取当前父进程的 PID。
-
void _exit(int status);- 功能: 立即终止当前进程,并将
status返回给父进程(通过wait()或waitpid()捕获)。注意:_exit不会执行标准 I/O 库的清理工作(如刷新缓冲区),而exit()会。
- 功能: 立即终止当前进程,并将
-
unsigned int sleep(unsigned int seconds);- 功能: 让当前进程挂起(休眠)至少
seconds秒。 - 返回值: 返回剩余的秒数(如果被信号中断),或者 0(如果休眠了完整的时间)。
- 功能: 让当前进程挂起(休眠)至少
目录和文件系统操作
-
int chdir(const char *path);- 功能: 更改当前工作目录到
path。 - 返回值: 成功返回 0,失败返回 -1。
- 功能: 更改当前工作目录到
-
char *getcwd(char *buf, size_t size);- 功能: 获取当前工作目录的绝对路径,并将其存入
buf缓冲区。 - 返回值: 成功返回
buf指针,失败返回 NULL。
- 功能: 获取当前工作目录的绝对路径,并将其存入
用户和用户组信息
-
uid_t getuid(void);- 功能: 获取当前进程的真实用户 ID。
-
uid_t geteuid(void);- 功能: 获取当前进程的有效用户 ID (Effective User ID),这通常与文件权限检查相关。
-
gid_t getgid(void);- 功能: 获取当前进程的真实组 ID。
-
gid_t getegid(void);- 功能: 获取当前进程的有效组 ID。
杂项
-
int access(const char *pathname, int mode);- 功能: 检查文件
pathname的访问权限。 mode可以是R_OK(读),W_OK(写),X_OK(执行),F_OK(文件存在) 的组合。- 返回值: 如果有权限,返回 0;否则返回 -1。
- 功能: 检查文件
-
int unlink(const char *pathname);- 功能: 删除一个文件或解除一个符号链接,注意,对于正在被进程使用的文件,它并不会真正释放磁盘空间,直到所有使用它的进程都关闭了它。
-
char *getenv(const char *name);- 功能: 获取名为
name的环境变量的值。
- 功能: 获取名为
一个简单的 C 语言示例
下面是一个使用 unistd.h 中 fork(), getpid(), getppid(), write() 和 _exit() 的经典示例。
#include <stdio.h> // 为了 printf
#include <unistd.h> // 为了 fork, getpid, getppid, write, _exit
#include <sys/wait.h> // 为了 waitpid
int main() {
pid_t pid;
int status;
printf("Parent process (PID: %d) is about to fork.\n", getpid());
pid = fork();
if (pid == -1) {
// fork 失败
perror("fork failed");
return 1;
}
if (pid == 0) {
// --- 子进程代码 ---
printf("Child process (PID: %d) started. My parent is (PID: %d).\n", getpid(), getppid());
// 使用 write 向标准输出 (文件描述符 1) 写入
write(1, "Hello from the child process!\n", 30);
// 子进程正常退出,状态码为 0
_exit(0);
} else {
// --- 父进程代码 ---
printf("Parent process (PID: %d) created a child with PID: %d.\n", getpid(), pid);
// 父进程等待子进程结束
waitpid(pid, &status, 0);
if (WIFEXITED(status)) {
printf("Parent: Child process %d exited with status %d.\n", pid, WEXITSTATUS(status));
}
}
return 0;
}
编译和运行 (在 Linux 或 macOS 上):
gcc -o unistd_example unistd_example.c ./unistd_example
预期输出:
Parent process (PID: 1234) is about to fork.
Parent process (PID: 1234) created a child with PID: 1235.
Child process (PID: 1235) started. My parent is (PID: 1234).
Hello from the child process!
Parent: Child process 1235 exited with status 0.
(注意:PID 每次运行都会不同)
| 特性 | 描述 |
|---|---|
| 名称 | unistd.h (Unix Standard) |
| 标准 | POSIX 标准 |
| 平台 | Unix-like 系统 (Linux, macOS, BSD 等) |
| 作用 | 提供对底层操作系统功能的访问,封装了系统调用。 |
| 重要性 | 是进行 Unix/Linux 系统编程、编写服务器、工具脚本等任务的基础。 |
当你需要直接与操作系统内核交互,或者进行性能要求极高的编程时,unistd.h 是你不可或缺的工具,对于大多数常规应用,标准 C 库(如 stdio.h, stdlib.h)已经足够,但了解 unistd.h 能让你更深入地理解程序是如何在 Unix 系统上运行的。
