IPC进程间通信概述
进程空间独立,但实际应用中存在数据共享或交互需求,因此需要IPC机制。IPC方式多样,根据场景选择合适方法。
IPC种类
古老通信方式
无名管道(匿名管道)
仅限有亲缘关系的进程通信(如父子进程)。
特性:- 半双工(通常用作单工)。
- 不支持文件定位操作(如
lseek)。 - 通过文件IO操作(
read/write),标准IO(如fgets)可能因缓冲区引发问题。
行为规则:
- 读端存在时,写操作超过64K会阻塞。
- 写端存在时,读空管道会阻塞。
- 读端关闭后继续写会导致管道破裂(写进程终止)。
- 写端关闭后,读空管道返回
read值为0,标志通信结束。
函数原型:
int pipe(int pipefd[2]); // pipefd[0]为读端,pipefd[1]为写端有名管道(FIFO)
允许任意进程通信,文件系统可见。
特性:- 与无名管道一致,但需显式打开(
open)。若一端未打开,open会阻塞。
函数原型:
int mkfifo(const char *pathname, mode_t mode); // 创建权限为mode的有名管道文件- 与无名管道一致,但需显式打开(
IPC对象通信(System V)
- 共享内存:高效数据共享,需同步机制(如信号量)。
- 信号量集:协调多进程对资源的访问。
Socket通信
- 网络通信:支持跨主机进程交互。
注意事项
- 管道底层实现为队列,需遵循先进先出原则。
- 编程时注意资源释放(如关闭管道描述符)。
- 信号量用于解决竞态条件,共享内存需手动同步。
代码示例(无名管道):
#include <unistd.h> int main() { int fd[2]; pipe(fd); // 创建管道 if (fork() == 0) { close(fd[0]); // 子进程关闭读端 write(fd[1], "data", 5); } else { close(fd[1]); // 父进程关闭写端 char buf[10]; read(fd[0], buf, sizeof(buf)); } return 0; }