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 定义,跨平台一致。
    • epollkqueue、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 兼容程序。