记录一下windows下进程间通信
1.通过线程同步一样的操作进行进程同步,然后同步的内容换成了共享内存段
本人还是习惯信号量的方式。
场景:主进程需要调用子进程的一个函数。利用共享内存进行输入输出。利用信号量进行数据同步。
代码1,子进程。手动运行也行,让父进程创造也行,根据需要把。
#include<iostream>
#include<windows.h>
using namespace std;
//实际工作是利用进程通信,让这个进程一直监听消息,有消息就利用这个函数处理,然后返回。
string linetomulti(string data)
{
cout<<"modify data = "<<data<<endl;
return "finish";
}
int main()
{
HANDLE fileMap = CreateFileMappingA(INVALID_HANDLE_VALUE,NULL,PAGE_EXECUTE_READWRITE,0,256,"lineData");//注意这些名称都是一样的才行。
LPVOID address = MapViewOfFile(fileMap,FILE_MAP_ALL_ACCESS,0,0,0);
HANDLE handle1 = CreateSemaphore(NULL,0,1,"sem1");
HANDLE handle2 = CreateSemaphore(NULL,0,1,"sem2");
while(true)
{
WaitForSingleObject(handle1,INFINITE);
string s = (char*)address;
s = linetomulti(s);
memcpy(address,s.c_str(),s.length());
ReleaseSemaphore(handle2,1,NULL);
}
}
代码2.主进程。
#include<iostream>
#include<windows.h>
#include<time.h>
using namespace std;
int main()
{
HANDLE fileMap = CreateFileMappingA(INVALID_HANDLE_VALUE,NULL,PAGE_EXECUTE_READWRITE,0,256,"lineData");
LPVOID address = MapViewOfFile(fileMap,FILE_MAP_ALL_ACCESS,0,0,0);
HANDLE handle1 = CreateSemaphore(NULL,0,1,"sem1");
HANDLE handle2 = CreateSemaphore(NULL,0,1,"sem2");
clock_t t1 = clock();
string data = "hello";
char clearData[256] = {0};
while(true)//实际工作是需要不阻塞通信很多次,然后多次调用一个函数与之通信。
{
int len = data.length();
cout<<"before data = "<<data<<endl;
memcpy(address,data.c_str(),len);
ReleaseSemaphore(handle1,1,NULL);
WaitForSingleObject(handle2,INFINITE);
data = (char*)address;
cout<<"after data = "<<data<<endl;
memcpy(address,clearData,128);//因为输入长度不定,可能有残留数据,还是主动清除的好。
break;
}
clock_t t2 = clock();
cout<<(t2-t1)<<endl;
//关闭子进程,再考虑回收句柄吧
// CloseHandle(fileMap);
// UnmapViewOfFile(address);
}
运行结果:
未完待续。进程通信的方法很多,但是一般来讲很少需要,利用信号量已经足够满足需求了。没有需求,死记硬背其他方法也很费劲啊。
2.父子进程利用匿名管道(继承句柄)
操作几乎差不多,这里需要注意的就是怎么让子进程知道自己继承的句柄。
所以采用父进程创建子进程,并通过传参给main函数,传递句柄。其实就是整数字符串和整数之间的转换。
注:代码部分来源于网上,并经过自己的修改。
代码:5.cpp,子进程。
#include<iostream>
#include <Windows.h>
using namespace std;
int main(int argc,char* argv[])
{
HANDLE hParentRead, hParentWrite, hChildRead, hChildWrite; //创建4个句柄
int num = atoi(argv[0]);
hParentRead = (HANDLE)num;
num = atoi(argv[1]);
hParentWrite = (HANDLE)num;
num = atoi(argv[2]);
hChildRead = (HANDLE)num;
num = atoi(argv[3]);
hChildWrite = (HANDLE)num;
//下面这个输出和父进程里面输出句柄是一样的。
cout<<"Child: hParentRead = "<<hParentRead<<" hParentWrite = "<<hParentWrite<<" hChildRead = "<<hChildRead<<" hChildWrite = "<<hChildWrite<<endl;
char buffer[1024];
memcpy(buffer,"hello world",1024);
//写点数据给父进程,证明句柄可用
WriteFile(hChildWrite,buffer,1024,0,NULL);
return 0;
}
代码 6.cpp ,父进程。
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include<iostream>
using namespace std;
int main()
{
HANDLE hParentRead, hParentWrite, hChildRead, hChildWrite; //创建4个句柄
STARTUPINFO si = { 0 }; //启动信息结构体
si.cb = sizeof(si);
PROCESS_INFORMATION pi = { 0 }; //进程信息结构体
DWORD dwWritedBytes = 0;
DWORD dwReadedBytes = 0;
DWORD dwBytesRead = 0;
DWORD dwTotalBytesAvail = 0;
DWORD dwBytesLeftThisMessage = 0;
SECURITY_ATTRIBUTES sa = { 0 }; //安全属性描述符
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE; //设置句柄可继承
//创建管道1. 父进程读 -> 子进程写入
BOOL bRet = CreatePipe(&hParentRead,
&hChildWrite,
&sa,
0);
//创建管道2. 子进程读->父进程写.
bRet = CreatePipe(&hChildRead,
&hParentWrite,
&sa,
0);
//这里将子进程写重定向到 stdout中. 子进程读取重定向到stdinput中
// si.hStdInput = hChildRead;
// si.hStdOutput = hChildWrite;
si.dwFlags = STARTF_USESTDHANDLES; //设置窗口隐藏启动
string cmdLine = to_string((int)hParentRead) + " " + to_string((int)hParentWrite) + " " + to_string((int)hChildRead) + " " + to_string((int)hChildWrite);
bRet = CreateProcess(
"5.exe", //创建cmd进程.默认寻找cmd进程.
(LPSTR)cmdLine.c_str(),
NULL,
NULL,
TRUE,
CREATE_NO_WINDOW,
NULL,
NULL,
&si,
&pi);
// char szBuffer[15] = "path \n";
// WriteFile(hParentWrite, szBuffer, 15, NULL, 0);//使用writeFile操作管道,给cmd发送数据命令.
char data[1024] = {0};
ReadFile(hParentRead,data,1024,NULL,0);
cout<<"Child: hParentRead = "<<hParentRead<<" hParentWrite = "<<hParentWrite<<" hChildRead = "<<hChildRead<<" hChildWrite = "<<hChildWrite<<endl;
cout<<data<<endl;
return 0;
}
能通信就好了,剩下的,想干什么,就自己做吧。
感觉管道啥的远不如信号量来得痛快啊。