在C++中,进程间通信(IPC)是让多个独立进程交换数据和协调操作的机制。以下详细介绍三种常见的IPC方式:
管道是一种半双工的通信方式,数据只能单向流动,分为匿名管道和命名管道。
pipe(int fd[2])
创建,返回两个文件描述符:fd[0]
(读端)和fd[1]
(写端)。#include
#include
int main() {
int fd[2];
char buffer[100];
if (pipe(fd) == -1) {
perror("pipe failed");
return 1;
}
pid_t pid = fork();
if (pid < 0) {
perror("fork failed");
return 1;
}
if (pid == 0) { // 子进程:写数据
close(fd[0]); // 关闭读端
const char* msg = "Hello from child!";
write(fd[1], msg, strlen(msg) + 1);
close(fd[1]);
} else { // 父进程:读数据
close(fd[1]); // 关闭写端
read(fd[0], buffer, sizeof(buffer));
std::cout << "Parent received: " << buffer << std::endl;
close(fd[0]);
}
return 0;
}
mkfifo
创建),可用于无亲缘关系的进程。// 写进程
#include
#include
int main() {
int fd = open("myfifo", O_WRONLY);
write(fd, "Hello from writer!", 18);
close(fd);
return 0;
}
// 读进程
#include
#include
#include
int main() {
int fd = open("myfifo", O_RDONLY);
char buffer[100];
read(fd, buffer, 100);
std::cout << "Reader received: " << buffer << std::endl;
close(fd);
return 0;
}
mkfifo myfifo
。共享内存允许多个进程直接访问同一块物理内存,是最快的IPC方式。
shmget
)。shmat
)。shmdt
)并删除(shmctl
)。#include
#include
#include
#include
int main() {
// 创建共享内存段(键值为1234,大小1024字节)
int shmid = shmget(1234, 1024, 0666 | IPC_CREAT);
if (shmid == -1) {
perror("shmget failed");
return 1;
}
// 映射到当前进程
char* shared_memory = (char*)shmat(shmid, nullptr, 0);
if (shared_memory == (char*)-1) {
perror("shmat failed");
return 1;
}
// 写入数据
std::strcpy(shared_memory, "Hello from shared memory!");
// 解除映射
if (shmdt(shared_memory) == -1) {
perror("shmdt failed");
return 1;
}
// 读取数据的进程类似,只需将写入操作改为读取
return 0;
}
消息队列是内核管理的链表,进程通过发送/接收消息进行通信。
msgget
)。msgsnd
)和接收消息(msgrcv
)。msgctl
)。#include
#include
#include
struct Message {
long mtype; // 消息类型(必须大于0)
char mtext[100]; // 消息内容
};
int main() {
// 创建消息队列(键值为5678)
int msgid = msgget(5678, 0666 | IPC_CREAT);
if (msgid == -1) {
perror("msgget failed");
return 1;
}
// 发送消息
Message msg;
msg.mtype = 1;
std::strcpy(msg.mtext, "Hello from message queue!");
if (msgsnd(msgid, &msg, sizeof(msg.mtext), 0) == -1) {
perror("msgsnd failed");
return 1;
}
// 接收消息
Message received;
if (msgrcv(msgid, &received, sizeof(received.mtext), 1, 0) == -1) {
perror("msgrcv failed");
return 1;
}
std::cout << "Received: " << received.mtext << std::endl;
// 删除队列
if (msgctl(msgid, IPC_RMID, nullptr) == -1) {
perror("msgctl failed");
return 1;
}
return 0;
}
方式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
管道 | 简单易用,自动同步 | 单向,容量有限 | 父子进程间少量数据传输 |
共享内存 | 速度最快,适合大量数据 | 需手动同步,管理复杂 | 高性能计算,图形处理 |
消息队列 | 异步通信,按类型分类 | 效率低于共享内存 | 分布式系统,事件驱动架构 |