进程间通信(IPC)是操作系统中不同进程之间交换数据和信号的一种机制。以下是一些常见的进程间通信方法:
-
管道(Pipes):
- 管道是一种半双工通信方式,数据只能在一个方向上流动。
- 通常用于父子进程间的通信。
-
消息队列(Message Queues):
- 消息队列允许进程发送和接收消息,消息可以是任何数据类型。
- 消息队列可以设置为持久的,即消息可以存储在磁盘上。
-
共享内存(Shared Memory):
- 共享内存允许多个进程访问同一块内存区域。
- 这是最快的IPC方法之一,但需要同步机制来避免竞态条件。
-
套接字(Sockets):
- 套接字用于进程间通过网络进行通信。
- 支持面向连接和无连接的通信。
-
信号(Signals):
- 信号是一种简单的通信方式,用于通知进程某个事件已经发生。
-
信号量(Semaphores):
- 信号量用于控制对共享资源的访问。
-
文件映射(Memory-mapped Files):
- 文件映射允许进程将文件内容映射到内存中,从而实现共享。
在MFC(Microsoft Foundation Classes)框架下的C++中,可以使用一些特定的类和函数来实现进程间通信。以下是一些示例:
示例1:使用管道进行进程间通信
#include <windows.h>
#include <iostream>
int main() {
// 创建匿名管道
HANDLE hPipeRead, hPipeWrite;
if (!CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0)) {
std::cerr << "CreatePipe failed" << std::endl;
return 1;
}
// 子进程写入管道
DWORD dwWritten;
const char* message = "Hello from child process!";
if (!WriteFile(hPipeWrite, message, strlen(message), &dwWritten, NULL)) {
std::cerr << "WriteFile failed" << std::endl;
CloseHandle(hPipeWrite);
CloseHandle(hPipeRead);
return 1;
}
// 父进程读取管道
char buffer[256];
DWORD dwRead;
if (!ReadFile(hPipeRead, buffer, sizeof(buffer), &dwRead, NULL)) {
std::cerr << "ReadFile failed" << std::endl;
}
std::cout << "Received: " << buffer << std::endl;
// 关闭句柄
CloseHandle(hPipeWrite);
CloseHandle(hPipeRead);
return 0;
}
示例2:使用消息队列进行进程间通信
#include <windows.h>
#include <string>
#include <iostream>
int main() {
// 创建或打开消息队列
HANDLE hQueue = CreateFile("\\\\.\\pipe\\MyMessageQueue",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hQueue == INVALID_HANDLE_VALUE) {
std::cerr << "CreateFile failed" << std::endl;
return 1;
}
// 发送消息
const std::string message = "Hello from IPC!";
DWORD dwWritten;
if (!WriteFile(hQueue, message.c_str(), message.size(), &dwWritten, NULL)) {
std::cerr << "WriteFile failed" << std::endl;
}
// 接收消息
char buffer[256];
DWORD dwRead;
if (!ReadFile(hQueue, buffer, sizeof(buffer), &dwRead, NULL)) {
std::cerr << "ReadFile failed" << std::endl;
}
std::cout << "Received: " << buffer << std::endl;
// 关闭句柄
CloseHandle(hQueue);
return 0;
}