POSIX Intro

POSIX(Portable Operating System Interface for Unix)是由IEEE(电气和电子工程师协会)定义的一组操作系统接口标准。 旨在提高不同Unix系统之间的兼容性和可移植性。它们开发人员提供了一套标准化的API(应用程序接口),使得软件在符合POSIX标准的操作系统之间 可以无缝运行。这个标准最初的目标是为了使不同厂商的Unix操作系统之间能够互操作,后来也扩展到其他类Unix系统,如Linux、BSD、macOS等。

POSIX的历史背景

POSIX的起源可以追溯到1980年代,当时Unix操作系统的实现开始多样化,且每个系统的接口差异较大。为了减少这些差异并推动Unix的普及,IEEE发起了POSIX标准化工作。POSIX第一个版本是POSIX.1,发布于1988年。随着时间的推移,POSIX标准不断扩展和修订,成为了现代类Unix操作系统的重要基准。

POSIX的主要内容

POSIX标准覆盖了操作系统的多个方面,设计文件系统、进程控制、线程、信号、I/O操作等。其主要内容包括一下几个重要领域:

进程管理与控制(Process Management)

如 fork 用于创建一个子进程,当前进程的副本

pid_t pid = fork();
if (pid == 0) {
    // 子进程代码
} else if (pid > 0) {
    // 父进程代码
} else {
    // fork失败
}

exec 用指定的程序替换当前进程的映像。

execlp("ls", "ls", "-l", (char *)NULL);

wait 使父进程等待子进程结束。

int status;
pid_t pid = wait(&status);

exit 终止当前进程并返回状态。

exit(0);

线程管理(Thread Management)

pthread_create:创建一个新的线程。

pthread_t thread;
pthread_create(&thread, NULL, thread_func, NULL);

pthread_join:等待线程完成。

pthread_join(thread, NULL);

pthread_mutex_lockpthread_mutex_unlock 锁定和解锁互斥锁(mutex)来实现线程同步。

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mutex);
// 临界区代码
pthread_mutex_unlock(&mutex);

文件操作(File Operations)

open:打开一个文件。

int fd = open("file.txt", O_RDONLY);
if (fd == -1) {
    perror("open failed");
}

read:从文件中读取数据。

char buffer[128];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer));

write:向文件写入数据。

ssize_t bytes_written = write(fd, "Hello, world!", 13);

close:关闭文件描述符。

close(fd);

lseek:设置文件指针的位置。

off_t offset = lseek(fd, 0, SEEK_SET);

信号处理(Signal Handling)

signal:注册信号处理函数。

void handler(int signum) {
    printf("Received signal %d\n", signum);
}

signal(SIGINT, handler);  // 注册SIGINT信号的处理函数

kill:向指定进程发送信号。

kill(pid, SIGTERM);  // 向进程pid发送SIGTERM信号

sigaction:更加灵活的信号处理机制,可以替代signal。

struct sigaction sa;
sa.sa_handler = handler;
sigaction(SIGINT, &sa, NULL);

输入输出(I/O)

read:读取文件或设备的数据。

ssize_t bytes_read = read(fd, buffer, sizeof(buffer));

write:写数据到文件或设备。

ssize_t bytes_written = write(fd, buffer, bytes_to_write);

close:关闭打开的文件描述符。

close(fd);

fsync:将文件描述符的缓冲区数据强制写入磁盘。

fsync(fd);

dup:复制文件描述符。

int new_fd = dup(fd);

时间与日期(Time and Date)

time:返回当前时间(自1970年1月1日起的秒数)。

time_t current_time = time(NULL);

gettimeofday:获取当前的时间(秒和微秒)。

struct timeval tv;
gettimeofday(&tv, NULL);

clock:获取程序执行时间。

clock_t start_time = clock();
// 程序执行
clock_t end_time = clock();

sleep:使当前线程休眠指定时间。

sleep(5);  // 休眠5秒

用户和权限管理(User and Group Management)

getuid:获取当前进程的用户ID。

uid_t uid = getuid();

setuid:设置当前进程的用户ID。

setuid(new_uid);

getgid:获取当前进程的组ID。

gid_t gid = getgid();

setgid:设置当前进程的组ID。

setgid(new_gid);

getpwuid:根据用户ID获取用户信息。

struct passwd *pw = getpwuid(uid);

命令行工具和脚本(Shell and Utilities)

find:查找文件。

find /path/to/search -name "filename"

xargs:构建并执行命令行。

find . -name "*.txt" | xargs cat

POSIX的版本和演变

POSIX标准有多个版本,不同版本扩展了原有的功能或对原有接口进行了改进。以下是一些主要的POSIX版本:

POSIX的应用与兼容性

由于POSIX标准提供了一套通用的接口规范,它被广泛应用于各类Unix和类Unix操作系统(如Linux、macOS、FreeBSD、AIX等)中。即使这些操作系统在实现上有所不同,它们通常都遵循POSIX标准,因此应用程序可以在多个平台上进行移植和运行。

例如,许多Linux发行版(如Ubuntu、Debian、Red Hat)都符合POSIX标准,因此许多基于Linux的应用程序可以很容易地移植到其他类Unix系统中,如macOS。

POSIX与Linux

Linux本身并不是POSIX标准的完全实现者,但它支持POSIX标准的大部分功能。大多数Linux发行版都遵循POSIX的一些核心部分,尤其是在系统调用、进程管理、线程管理和文件I/O等方面。因此,很多Linux开发者编写的程序可以在遵循POSIX标准的其他Unix系统上运行。

POSIX与其他操作系统的关系

除了Linux和传统的Unix系统外,POSIX标准还影响了其他操作系统的设计和接口,如: