POSIX标准
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 兼容程序。