1. 什么是 POSIX
POSIX 全称 Portable Operating System Interface(可移植操作系统接口),是由 IEEE 定义的一系列 操作系统 API 标准。
- 它规定了 应用程序和操作系统之间的接口(主要是 C 函数调用)。
- 目的是让应用程序能在不同的类 Unix 系统(Linux、BSD、macOS…)之间移植时不用修改或只需少量修改。
- 属于 API 层面的标准,不是实现层面的。
- 举例:
fork()这个函数在 Linux 和 macOS 都能用,是因为它们都遵循 POSIX。
- 举例:
2. 举例说明
下面我用几个常见的 POSIX 接口对比说明:
(1) fork()
- POSIX 定义:
pid_t fork(void); - 作用:创建一个子进程,子进程和父进程几乎一样。
-
例子(POSIX 兼容代码):
#include <unistd.h> #include <stdio.h> #include <sys/types.h> int main() { pid_t pid = fork(); if (pid == 0) { printf("Child process\n"); } else { printf("Parent process\n"); } return 0; }- 这段代码在 Linux、macOS、FreeBSD 上都能编译运行。
- 因为
fork()的接口是 POSIX 定义的。
(2) read() / write()
-
POSIX 定义:
ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); - 作用:最基本的 I/O 接口。
-
例子:
#include <unistd.h> #include <fcntl.h> int main() { char buf[100]; int fd = open("test.txt", O_RDONLY); ssize_t n = read(fd, buf, sizeof(buf)); write(STDOUT_FILENO, buf, n); return 0; }- 这段代码在 任何 POSIX 兼容系统上都能工作。
- 因为
open/read/write的行为都由 POSIX 定义。
(3) 和非 POSIX 的对比
- POSIX 标准 API:
fork(),exec(),pipe(),pthread_create(),read(),write()…
- 非 POSIX API(系统私有扩展,跨平台不可移植):
epoll_*(Linux 专有)kqueue(BSD / macOS 专有)- Windows 的
CreateProcess()(完全不是 POSIX,除非用 Cygwin 之类的兼容层)
3. 总结
- POSIX 就是一套操作系统 API 的标准,主要以 C 函数的形式提供。
- 它保证了应用程序只要用 POSIX API,就能在不同的 Unix 系统之间移植。
- 举例:
fork()、wait()、read()、write()→ POSIX 定义,跨平台一致。epoll、kqueue、Windows API → 系统私有,不是 POSIX,移植性差。
POSIX 常见函数速查表
1. 进程管理
| 函数 | 头文件 | 功能 | 示例 |
|---|---|---|---|
fork() | <unistd.h> | 创建一个子进程 | c pid_t pid = fork(); if(pid==0){printf("child\n");} |
exec() 系列 | <unistd.h> | 在当前进程中执行新程序 | c execl("/bin/ls","ls","-l",NULL); |
wait() | <sys/wait.h> | 等待子进程退出 | c int status; wait(&status); |
getpid() | <unistd.h> | 获取当前进程 PID | c printf("%d\n",getpid()); |
getppid() | <unistd.h> | 获取父进程 PID | c printf("%d\n",getppid()); |
2. 文件 I/O
| 函数 | 头文件 | 功能 | 示例 |
|---|---|---|---|
open() | <fcntl.h> | 打开文件,返回文件描述符 | c int fd=open("file.txt",O_RDONLY); |
read() | <unistd.h> | 从 fd 读取字节 | c char buf[100]; read(fd,buf); |
write() | <unistd.h> | 向 fd 写入字节 | c write(STDOUT_FILENO,"Hi\n"); |
close() | <unistd.h> | 关闭文件描述符 | c close(fd); |
lseek() | <unistd.h> | 移动文件指针 | c lseek(fd,SEEK_END); |
3. 线程(POSIX 线程库 = pthread)
| 函数 | 头文件 | 功能 | 示例 |
|---|---|---|---|
pthread_create() | <pthread.h> | 创建线程 | c pthread_t t; pthread_create(&t,NULL,fn,NULL); |
pthread_join() | <pthread.h> | 等待线程结束 | c pthread_join(t,NULL); |
pthread_mutex_init() | <pthread.h> | 初始化互斥锁 | c pthread_mutex_t m=PTHREAD_MUTEX_INITIALIZER; |
pthread_mutex_lock() | <pthread.h> | 加锁 | c pthread_mutex_lock(&m); |
pthread_mutex_unlock() | <pthread.h> | 解锁 | c pthread_mutex_unlock(&m); |
4. 信号处理
| 函数 | 头文件 | 功能 | 示例 |
|---|---|---|---|
signal() | <signal.h> | 设置信号处理函数 | c signal(SIGINT, handler); |
kill() | <signal.h> | 向进程发送信号 | c kill(pid,SIGTERM); |
raise() | <signal.h> | 向自己发送信号 | c raise(SIGUSR1); |
sigaction() | <signal.h> | 高级信号处理 | c struct sigaction sa; sa.sa_handler=handler; sigaction(SIGINT,&sa,NULL); |
5. 其他有用函数
| 函数 | 头文件 | 功能 | 示例 |
|---|---|---|---|
sleep() | <unistd.h> | 暂停一段时间(秒) | c sleep(2); |
usleep() | <unistd.h> | 暂停微秒 | c usleep(100000); |
getcwd() | <unistd.h> | 获取当前工作目录 | c char buf[256]; getcwd(buf); |
chdir() | <unistd.h> | 改变工作目录 | c chdir("/tmp"); |
pipe() | <unistd.h> | 创建管道 | c int fd[2]; pipe(fd); |
总结
-
POSIX 保证这些 API 在类 Unix 系统(Linux、macOS、FreeBSD…)上可用,接口和语义一致。
-
如果你写的程序只用这些 POSIX API,就能很容易移植到不同的 Unix 系统。
-
但如果用 Linux 特有的 API(比如
epoll)、BSD 特有的 API(比如kqueue),那就不再是 POSIX 兼容程序。