Windows下进程间通信

记录一下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;
}

能通信就好了,剩下的,想干什么,就自己做吧。
感觉管道啥的远不如信号量来得痛快啊。

posted @ 2022-03-22 20:07  念秋  阅读(634)  评论(0编辑  收藏  举报