💻 Hello World, 我是 予枫。
代码不止,折腾不息。作为一个正在升级打怪的 Java 后端练习生,我喜欢把踩过的坑和学到的招式记录下来。 保持空杯心态,让我们开始今天的技术分享。
一、管道 (Pipe)
管道是最古老也是最常见的 IPC 方式,它本质上是内核中的一块缓存。
-
工作原理: 数据以字节流的形式传输。一个进程向管道的一端写入数据,另一个进程从另一端读取数据。
-
分类:
-
匿名管道 (Anonymous Pipe ): 只能在有"亲缘关系"的进程间使用(比如父子进程)。我们在 Linux 命令行常用的
|就是这种(例如ps aux | grep java)。 -
命名管道 (FIFO/Named Pipe ): 可以在无亲缘关系的进程间使用,因为它在文件系统中有一个对应的文件名。
-
-
特点:
-
单向/ 半双工 : 数据通常只能单向流动。如果需要双向通信,通常需要建立两个管道。
-
同步阻塞: 如果管道空了,读进程会阻塞;如果管道满了,写进程会阻塞。
-
简单类比: 就像一根水管。水(数据)从一头流进,从另一头流出。你不能从出水口往回灌水,且水流过去就不见了(读完即删)。
二、消息队列 (Message Queue)
消息队列是保存在内核中的消息 链表。
-
工作原理: 进程把数据打包成一个"消息"体(包含类型和数据),扔进内核的消息队列中。另一个进程可以根据消息类型有选择地读取消息。
-
与管道的区别:
-
数据格式 : 管道是无格式的字节流,消息队列是有格式的(可以区分是"文本"还是"图片"数据)。
-
独立性: 消息队列独立于发送和接收进程存在。进程终止后,只要不删除,消息队列里的内容依然存在。
-
-
缺点: 数据需要在用户态和内核态之间进行拷贝,如果传输的数据量非常大,开销会比较高。
简单类比: 就像一个公告栏 或信箱。A 写了一张便利贴(消息)贴上去,B 有空的时候过来取走。A 和 B 不需要同时在场,而且 B 可以只挑自己感兴趣的便利贴看。
三、共享内存 (Shared Memory)
这是所有 IPC 方式中速度最快的一种。
-
工作原理: 操作系统拿出一块物理内存,将其映射到多个进程的虚拟地址空间中。这样,A 进程往这块内存写数据,B 进程立刻就能看到,不需要像管道或消息队列那样在内核和用户空间之间来回拷贝数据。
-
核心挑战: 因为多个进程可以同时读写,就像多个人同时在一张纸上写字,容易乱套(竞态条件)。因此,共享内存通常需要配合信号量 ( Semaphore ) 或互斥锁等同步机制来使用。
简单类比: 就像会议室里的白板。A 在上面写了字,B 抬头就能看见,不需要传纸条。但是,A 写的时候,B 最好别去擦,得大家商量好规则(同步)。
四、信号 (Signal)
信号是一种异步通信方式,也是一种比较"暴力"的通信方式。
-
工作原理: 用于通知接收进程"发生了某个事件"。它不传输复杂数据,只传输一个信号编号。
-
常见场景:
-
用户按
Ctrl+C,系统发送SIGINT信号通知进程终止。 -
命令行执行
kill -9 PID,发送SIGKILL强制杀死进程。
-
-
特点: 接收进程无法预测信号何时到达,必须随时准备处理(或由系统默认处理)。
简单类比: 就像红绿灯 或者裁判的哨声。哨声一响(信号到达),你就知道该停下或者犯规了,但哨声里并不包含具体的对话内容。
总结对比
为了方便记忆,我将这四种方式做了一个对比表:
|--------|-----------|----------------------|----------------------|-------------|
| 特性 | 管道 (Pipe) | 消息队列 (Message Queue) | 共享内存 (Shared Memory) | 信号 (Signal) |
| 数据传输效率 | 一般(需拷贝) | 一般(需拷贝) | 极高(无拷贝) | 低(仅传递状态) |
| 数据量 | 适中 | 适中 | 大 | 极小 |
| 同步机制 | 自带(阻塞) | 自带 | 无(需配合信号量) | 异步 |
| 应用场景 | 简单数据流、命令行 | 频繁交换特定格式数据 | 大数据量交换、高性能场景 | 进程控制、异常通知 |
🌟 关注【予枫】,获取更多技术干货
📅 身份:一名热爱技术的研二学生
🏷️ 标签:Java / 算法 / 个人成长
💬 Slogan:只写对自己和他人有用的文字。