进程间通信(IPC)是操作系统中不同进程之间交换数据的机制,广泛用于多进程应用(如客户端-服务器模型、系统服务通信)。以下对比五种常见 IPC 方式:LocalSocket
(Unix 域套接字)、管道、消息队列、共享内存和信号。
SOCK_STREAM
,类似 TCP)和数据报(SOCK_DGRAM
,类似 UDP)模式。#include
#include
#include
#define SOCKET_PATH "/tmp/mysocket"
int server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un addr = {AF_UNIX, SOCKET_PATH};
bind(server_fd, (struct sockaddr*)&addr, sizeof(addr));
listen(server_fd, 5);
int client_fd = accept(server_fd, nullptr, nullptr);
char buf[1024] = {0};
recv(client_fd, buf, sizeof(buf), 0);
pipe
系统调用创建,数据通过内核缓冲区传输。#include
int fd[2];
pipe(fd); // 创建匿名管道
if (fork() == 0) { // 子进程
close(fd[0]);
write(fd[1], "Hello", 5);
} else { // 父进程
close(fd[1]);
char buf[1024];
read(fd[0], buf, sizeof(buf));
}
#include
mqd_t mq = mq_open("/myqueue", O_CREAT | O_RDWR, 0644, nullptr);
char buf[1024] = "Hello";
mq_send(mq, buf, strlen(buf), 0); // 发送
char recv_buf[1024];
mq_receive(mq, recv_buf, sizeof(recv_buf), nullptr); // 接收
#include
int shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0666);
char* shared_mem = (char*)shmat(shmid, nullptr, 0);
strcpy(shared_mem, "Hello"); // 写
printf("%s\n", shared_mem); // 读
shmdt(shared_mem);
SIGUSR1
)触发特定动作。#include
void handler(int sig) { printf("Received signal %d\n", sig); }
signal(SIGUSR1, handler);
pid_t pid = fork();
if (pid == 0) {
kill(getppid(), SIGUSR1); // 子进程发送信号
}
特性 | LocalSocket | 管道 | 消息队列 | 共享内存 | 信号 |
---|---|---|---|---|---|
性能 | 高(内核缓冲区,接近共享内存) | 中等(内核缓冲区) | 中等(内核队列) | 最高(直接内存访问) | 低(仅传递信号) |
通信方向 | 双向 | 单向(匿名管道)/双向(FIFO) | 双向 | 双向 | 单向(通知) |
可靠性 | 流式可靠,数据报不可靠 | 可靠 | 可靠 | 可靠(需同步机制) | 不可靠(可能丢失) |
复杂性 | 中等(需管理连接/地址) | 低(简单 API) | 中等(需管理队列) | 高(需同步机制) | 低(简单通知) |
数据量 | 适合中小数据,支持文件描述符 | 适合中小数据 | 适合中小数据 | 适合大数据 | 仅适合事件通知 |
适用场景 | 本地客户端-服务器通信、Android 系统服务 | 父子进程通信、简单数据流 | 复杂消息传递 | 高性能大数据共享 | 异步事件通知 |
权限控制 | 文件权限/SELinux | 文件权限(FIFO) | 队列权限 | 内存权限 | 进程权限 |
跨设备支持 | 否 | 否 | 否 | 否 | 否 |
read
、write
、send
),处理连接中断或超时。sendmsg
)或非阻塞 IO(select
/epoll
)。fork
和 exec
实现进程间流水线。mq_open
)支持优先级。sem_open
)或互斥锁实现同步。sigset_t
)处理多种信号。