进程间通信API
概述
进程间通信(IPC)是不同进程之间交换数据的机制。Windows提供了多种IPC方式,包括管道、邮槽、共享内存、消息队列等。
管道
匿名管道
匿名管道用于父子进程间的单向通信。
CreatePipe - 创建匿名管道
| C++ |
|---|
| BOOL CreatePipe(
PHANDLE hReadPipe, // 读取句柄
PHANDLE hWritePipe, // 写入句柄
LPSECURITY_ATTRIBUTES lpPipeAttributes, // 安全属性
DWORD nSize // 缓冲区大小
);
|
示例:
| C++ |
|---|
| #include <windows.h>
#include <stdio.h>
int main() {
HANDLE hReadPipe, hWritePipe;
SECURITY_ATTRIBUTES sa = {0};
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) {
printf("CreatePipe failed: %d\n", GetLastError());
return -1;
}
// 创建子进程
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
si.cb = sizeof(si);
si.hStdOutput = hWritePipe;
si.hStdError = hWritePipe;
si.dwFlags = STARTF_USESTDHANDLES;
CreateProcess(NULL, "cmd.exe /c dir", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
CloseHandle(hWritePipe); // 关闭写入端
// 读取输出
char buffer[4096];
DWORD bytesRead;
while (ReadFile(hReadPipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL) && bytesRead > 0) {
buffer[bytesRead] = '\0';
printf("%s", buffer);
}
CloseHandle(hReadPipe);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
|
命名管道
命名管道可用于不相关进程间的双向通信。
CreateNamedPipe - 创建命名管道
| C++ |
|---|
| HANDLE CreateNamedPipe(
LPCTSTR lpName, // 管道名称
DWORD dwOpenMode, // 打开模式
DWORD dwPipeMode, // 管道模式
DWORD nMaxInstances, // 最大实例数
DWORD nOutBufferSize, // 输出缓冲区大小
DWORD nInBufferSize, // 输入缓冲区大小
DWORD nDefaultTimeOut, // 默认超时
LPSECURITY_ATTRIBUTES lpSecurityAttributes // 安全属性
);
|
管道名称格式:
打开模式:
- PIPE_ACCESS_DUPLEX:双向
- PIPE_ACCESS_INBOUND:入站
- PIPE_ACCESS_OUTBOUND:出站
- FILE_FLAG_OVERLAPPED:异步
- FILE_FLAG_WRITE_THROUGH:直写
管道模式:
- PIPE_TYPE_BYTE:字节模式
- PIPE_TYPE_MESSAGE:消息模式
- PIPE_READMODE_BYTE:字节读取
- PIPE_READMODE_MESSAGE:消息读取
- PIPE_WAIT:阻塞
- PIPE_NOWAIT:非阻塞
ConnectNamedPipe - 等待客户端连接
| C++ |
|---|
| BOOL ConnectNamedPipe(
HANDLE hNamedPipe,
LPOVERLAPPED lpOverlapped
);
|
DisconnectNamedPipe - 断开连接
| C++ |
|---|
| BOOL DisconnectNamedPipe(
HANDLE hNamedPipe
);
|
服务端示例
| C++ |
|---|
| #include <windows.h>
#include <stdio.h>
int main() {
HANDLE hPipe = CreateNamedPipe(
L"\\\\.\\pipe\\MyPipe",
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1,
1024, 1024, 0, NULL
);
if (hPipe == INVALID_HANDLE_VALUE) {
printf("CreateNamedPipe failed: %d\n", GetLastError());
return -1;
}
printf("Waiting for client...\n");
if (ConnectNamedPipe(hPipe, NULL)) {
printf("Client connected\n");
// 读取数据
char buffer[1024];
DWORD bytesRead;
ReadFile(hPipe, buffer, sizeof(buffer), &bytesRead, NULL);
buffer[bytesRead] = '\0';
printf("Received: %s\n", buffer);
// 发送响应
const char* response = "Hello from server!";
DWORD bytesWritten;
WriteFile(hPipe, response, strlen(response), &bytesWritten, NULL);
DisconnectNamedPipe(hPipe);
}
CloseHandle(hPipe);
return 0;
}
|
客户端示例
| C++ |
|---|
| #include <windows.h>
#include <stdio.h>
int main() {
HANDLE hPipe = CreateFile(
L"\\\\.\\pipe\\MyPipe",
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL
);
if (hPipe == INVALID_HANDLE_VALUE) {
printf("CreateFile failed: %d\n", GetLastError());
return -1;
}
// 发送数据
const char* message = "Hello from client!";
DWORD bytesWritten;
WriteFile(hPipe, message, strlen(message), &bytesWritten, NULL);
// 接收响应
char buffer[1024];
DWORD bytesRead;
ReadFile(hPipe, buffer, sizeof(buffer), &bytesRead, NULL);
buffer[bytesRead] = '\0';
printf("Response: %s\n", buffer);
CloseHandle(hPipe);
return 0;
}
|
邮槽
邮槽用于单向通信,适合广播消息。
CreateMailslot - 创建邮槽
| C++ |
|---|
| HANDLE CreateMailslot(
LPCTSTR lpName,
DWORD nMaxMessageSize,
DWORD lReadTimeout,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
|
邮槽名称格式:
| Text Only |
|---|
| \\.\mailslot\mailslotname
|
示例
| C++ |
|---|
| // 服务端
HANDLE hMailslot = CreateMailslot(L"\\\\.\\mailslot\\MySlot", 0, MAILSLOT_WAIT_FOREVER, NULL);
char buffer[1024];
DWORD bytesRead;
ReadFile(hMailslot, buffer, sizeof(buffer), &bytesRead, NULL);
CloseHandle(hMailslot);
// 客户端
HANDLE hMailslot = CreateFile(L"\\\\.\\mailslot\\MySlot", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
const char* message = "Hello!";
DWORD bytesWritten;
WriteFile(hMailslot, message, strlen(message), &bytesWritten, NULL);
CloseHandle(hMailslot);
|
共享内存
CreateFileMapping - 创建共享内存
| C++ |
|---|
| HANDLE CreateFileMapping(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCTSTR lpName
);
|
MapViewOfFile - 映射视图
| C++ |
|---|
| LPVOID MapViewOfFile(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap
);
|
示例
| C++ |
|---|
| // 进程1:创建共享内存
HANDLE hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, L"MySharedMemory");
LPVOID pData = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
strcpy((char*)pData, "Hello from Process 1");
UnmapViewOfFile(pData);
CloseHandle(hMap);
// 进程2:访问共享内存
HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, L"MySharedMemory");
LPVOID pData = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
printf("Read: %s\n", (char*)pData);
UnmapViewOfFile(pData);
CloseHandle(hMap);
|
内存映射文件
用于将文件映射到内存,实现文件的高效读写。
示例
| C++ |
|---|
| #include <windows.h>
#include <stdio.h>
int main() {
// 创建文件
HANDLE hFile = CreateFile(L"test.txt", GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// 创建文件映射
HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 4096, NULL);
// 映射视图
LPVOID pData = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
// 写入数据
strcpy((char*)pData, "Hello, Memory Mapped File!");
// 同步到文件
FlushViewOfFile(pData, 0);
// 清理
UnmapViewOfFile(pData);
CloseHandle(hMap);
CloseHandle(hFile);
return 0;
}
|
消息队列
PostMessage - 投递消息
| C++ |
|---|
| BOOL PostMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
|
SendMessage - 发送消息
| C++ |
|---|
| LRESULT SendMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
|
自定义消息
| C++ |
|---|
| #define WM_MYMESSAGE (WM_USER + 100)
// 发送消息
PostMessage(hWnd, WM_MYMESSAGE, 0, 0);
// 接收消息(在窗口过程中)
case WM_MYMESSAGE:
// 处理消息
break;
|
WM_COPYDATA
用于窗口间传递数据。
示例
| C++ |
|---|
| // 发送端
COPYDATASTRUCT cds;
cds.dwData = 1; // 自定义数据类型
cds.cbData = strlen(data) + 1;
cds.lpData = (PVOID)data;
SendMessage(hTargetWnd, WM_COPYDATA, (WPARAM)hMyWnd, (LPARAM)&cds);
// 接收端
case WM_COPYDATA:
PCOPYDATASTRUCT pCds = (PCOPYDATASTRUCT)lParam;
if (pCds->dwData == 1) {
char* data = (char*)pCds->lpData;
// 处理数据
}
return TRUE;
|
事件对象
用于进程间同步。
示例
| C++ |
|---|
| // 进程1
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, L"MyEvent");
WaitForSingleObject(hEvent, INFINITE); // 等待信号
printf("Event signaled\n");
// 进程2
HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, L"MyEvent");
SetEvent(hEvent); // 发送信号
CloseHandle(hEvent);
|
互斥体
用于进程间互斥访问。
示例
| C++ |
|---|
| HANDLE hMutex = CreateMutex(NULL, FALSE, L"Global\\MyMutex");
WaitForSingleObject(hMutex, INFINITE);
// 临界区代码
ReleaseMutex(hMutex);
CloseHandle(hMutex);
|
信号量
控制资源访问数量。
示例
| C++ |
|---|
| HANDLE hSem = CreateSemaphore(NULL, 3, 3, L"MySemaphore");
WaitForSingleObject(hSem, INFINITE); // 等待资源
// 使用资源
ReleaseSemaphore(hSem, 1, NULL); // 释放资源
CloseHandle(hSem);
|
参考资料