进程间通信,InterProcess Communication, IPC,是进程之间交换信息的途径。

管道

管道是 UNIX 系统 IPC 的最古老的形式。有两种局限性:

  1. 历史上,它们是半双工的,为了最佳的可移植性,不能预先假定系统支持全双工管道。
  2. 管道只能在具有公共祖先的两个进程之间使用。通常,一个管道由一个进程创建,在进程调用 fork 之后,这个管道就能在父进程和子进程之间使用了。
#include <unistd.h>

int pipe(int fd[2]);

经由 fd 返回两个文件描述符:fd[0] 为读而打开,fd[1] 为写而打开。fd[1] 的输出是 fd[0] 的输入。

#include "apue.h"

int main()
{
  int n;
  int fd[2];
  pid_t pid;
  char line[MAXLINE];

  if (pipe(fd) < 0)
    err_sys("pipe error");
  if ((pid = fork()) < 0) {
    err_sys("fork error");
  } else if (pid > 0) { // parent
    close(fd[0]);
    write(fd[1], "hello world\n", 12);
  } else { // child
    close(fd[1]);
    n = read(fd[0], line, MAXLINE);
    write(STDOUT_FILENO, line, n);
  }

  exit(0);
}

popen & pclose

为了简化创建管道的过程,标准库提供了 popen 和 pclose 函数。

#include <stdio.h>

FILE *popen(const char *cmdstring, const char *type);

int pclose(FILE *fp);

如果 type 是 r,则文件指针连接到 cmdstring 的标准输出;如果 type 是 w,则文件指针连接到 cmdstring 的标准输入。

FIFO

FIFO 有时候被称为命名管道,未命名的管道只能在两个相关的进程之间使用,而且这两个相关的进程还要有一个共同的创建了它们的祖先进程。但是,通过 FIFO,不相关的进程也能交换数据。

#include <sys/stat.h>

int mkfifo(const char *path, mode_t mode);
int mkfifoat(int fd, const char *path, mode_t mode);