• 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;
    }
    
    

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

  • 相关阅读:
    Windows server 2008 R2充当路由器实现网络的互联(转)
    sqlserver内存释放心得
    收藏一个好用的base64编解码网址
    最后一篇,说好的开源来了!
    python五子棋
    flask使用原生ajax、不使用表单(Form)上传文件
    使用keras的LSTM进行预测----实战练习
    keras神经网络三个例子
    【强化学习】用pandas 与 numpy 分别实现 q-learning, saras, saras(lambda)算法
    【转】【强化学习】Deep Q Network(DQN)算法详解
  • 原文地址:https://www.cnblogs.com/dayq/p/16041094.html
Copyright © 2020-2023  润新知