进程间通信概述
本质与目的
进程间通信(IPC, Inter-Process Communication)指的是两个或多个进程之间进行信息传递的过程。由于进程具有独立性,一个进程的数据直接发送给另一个进程并非易事。
虽然父子进程在 fork 后能访问父进程的全局变量,但这不算严格的 IPC,因为这种关系是单向的且不可持续。真正的 IPC 需要满足以下核心需求:
- 数据传输:一个进程将数据发送给另一个进程。
- 资源共享:多个进程共享同一份资源。
- 通知事件:进程间发送消息通知状态变化(如子进程终止)。
- 进程控制:控制进程拦截并监控另一进程的执行状态。
实现 IPC 的本质前提是让不同的进程看到同一份资源,这通常需要操作系统提供系统调用支持。
发展标准
相对于网络协议的标准严格性,IPC 标准的发展经历了一个过程。System V 标准是早期的重要规范,定义了共享内存、消息队列和信号量等机制。尽管部分机制在现代应用中逐渐被网络通信替代,但理解其原理对于掌握底层系统编程依然至关重要。
管道通信
匿名管道特点
匿名管道基于文件描述符,具有以下显著特点:
- 单向通信:设计之初仅允许单向数据传输。
- 血缘限制:通常用于具有亲缘关系的进程(如父子进程)。
- 生命周期:管道随进程退出而关闭,文件的生命周期依附于进程。
- 同步机制:内部实现了进程间的同步。
- 字节流:面向字节流,读写次数不匹配可能导致阻塞或数据丢失。
常见场景分析
- 写慢读快:以写端节奏为准,读端等待数据就绪。
- 写快读慢:读端一次性读取所有写入数据。
- 写端关闭:若写端未写且关闭,读端会收到 EOF。
- 读端关闭:若读端关闭,写端继续写入会触发 SIGPIPE 信号。
命名管道
命名管道(FIFO)解决了匿名管道只能用于有亲缘关系进程的局限,允许毫不相干的进程通过文件系统路径进行通信。
关键细节
- 创建方式:使用
mkfifo创建管道文件。 - 打开行为:读端打开时若没有写端,会阻塞;反之亦然。这天然形成了一种同步机制。
- 字符串处理:不需要像 C 语言字符串那样手动添加
\0结束符,按字节读写即可。 - 权限管理:需设置合适的文件权限(如
0666)。
代码示例
服务器端 (server.cc)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#
{
((FIFO_NAME, ) == ) {
();
(errno != EEXIST) ();
}
();
fd = (FIFO_NAME, O_RDONLY);
(fd == ) {
();
();
}
();
buf[];
n;
((n = (fd, buf, (buf))) > ) {
buf[n] = ;
(, buf);
(stdout);
}
(n == ) ();
(fd);
(FIFO_NAME);
;
}


