一、为什么需要进程间通信?
-
数据交换:进程间传递数据,例如一个客户端和服务器。
-
资源共享:多个进程共享系统资源。
-
事件通知:一个进程需要通知另一个进程某个事件已发生。
-
进程控制:父子进程之间协调操作,如进程创建、终止等。
二、进程间通信的主要方式
1. 管道(Pipe)
1.1 无名管道(Unnamed Pipe)
-
特点:
-
只能用于具有亲缘关系的进程(如父子进程)。
-
单向通信。
-
-
API:
-
pipe(int pipefd[2])
-
-
优缺点:
-
简单、易于使用。
-
只能在本地使用,通信方向单一。
-
1.2 命名管道(Named Pipe,FIFO)
-
特点:
-
可以用于无亲缘关系的进程通信。
-
仍然是单向的。
-
-
API:
-
mkfifo()
,open()
,read()
,write()
-
-
优缺点:
-
可用于非亲缘进程。
-
使用上较复杂,需要显式创建与管理。
-
2. 信号(Signal)
-
特点:
-
用于通知进程事件发生(如终止、挂起等)。
-
异步通信。
-
-
常用信号:
-
SIGINT
、SIGTERM
、SIGKILL
、SIGCHLD
等。
-
-
优缺点:
-
简单高效,但传递信息量有限(主要用于事件通知)。
-
3. 消息队列(Message Queue)
-
特点:
-
基于内核,支持无亲缘关系进程通信。
-
结构化消息(有类型)。
-
-
API:
-
msgget()
,msgsnd()
,msgrcv()
,msgctl()
-
-
优缺点:
-
灵活、支持有序通信。
-
管理和同步较复杂。
-
4. 共享内存(Shared Memory)
-
特点:
-
多个进程共享同一块物理内存区域。
-
是最快速的通信方式。
-
通常需借助信号量或互斥锁同步访问。
-
-
API:
-
shmget()
,shmat()
,shmdt()
,shmctl()
-
-
优缺点:
-
高效。
-
需要额外同步机制,管理复杂。
-
5. 信号量(Semaphore)
-
特点:
-
用于实现进程间同步与互斥。
-
可用于保护共享资源。
-
-
API:
-
semget()
,semop()
,semctl()
-
-
优缺点:
-
不用于数据传输,而是控制同步。
-
通常与共享内存结合使用。
-
6. 套接字(Socket)
-
特点:
-
可用于网络通信(跨主机)或本地通信(UNIX域套接字)。
-
面向字节流或数据报。
-
-
种类:
-
SOCK_STREAM
(TCP) -
SOCK_DGRAM
(UDP) -
AF_INET
(IPv4网络)/AF_UNIX
(本地通信)
-
-
优缺点:
-
功能强大,可进行本地或远程通信。
-
编程复杂度较高。
-
7. 内存映射文件(Memory-Mapped File)
-
特点:
-
把文件映射到内存,通过访问内存实现进程间通信。
-
多用于共享内存的变体。
-
-
API:
-
mmap()
,munmap()
-
-
优缺点:
-
效率高。
-
需要文件系统支持,适用于大量数据通信。
-
三、进程间通信方式对比总结表
通信方式 | 是否可跨进程 | 是否需亲缘关系 | 通信效率 | 数据同步 | 特点说明 |
---|---|---|---|---|---|
无名管道 | 否 | 是 | 中 | 不需 | 简单、单向、父子通信 |
命名管道 | 是 | 否 | 中 | 不需 | 单向、需显式创建 |
消息队列 | 是 | 否 | 中 | 需 | 有类型、结构化、较灵活 |
共享内存 | 是 | 否 | 高 | 需 | 快速、高效、需同步机制 |
信号 | 是 | 否 | 低 | 不适用 | 通知机制、无数据传输 |
信号量 | 是 | 否 | 高 | 是 | 同步工具,无数据传输 |
套接字 | 是 | 否 | 中 | 不需 | 网络通信首选,可跨主机 |
内存映射文件 | 是 | 否 | 高 | 需 | 文件+共享内存,效率高 |
四、选择通信方式的建议
-
本地小量数据通信:管道、消息队列。
-
大数据高速通信:共享内存 + 信号量。
-
同步与互斥:使用信号量或互斥锁。
-
网络进程通信:使用 Socket。
-
需持久化共享内容:考虑内存映射文件。