首页 > 系统相关 >IPC(进程间通信)

IPC(进程间通信)

时间:2023-03-24 12:24:28浏览次数:37  
标签:IPC 映射 EventHandle 句柄 间通信 BufferData 进程 NULL

IPC有以下方式:
1.文件映射(内存映射)
2.邮件槽
3.管道
4.剪切板
5.父子进程
6.网络TCP

1.文件映射(数据量大,本地进程间)
a.命名映射
A进程:打开文件,获得文件句柄,创建文件映射,获得映射句柄,将文件映射对象映射到当前地址空间,进行读写操作,卸载映射、关闭句柄
hFile = CreateFile()
hMapHandle = CreateFileMapping(hFile,MappingAttributes,flProtect,SizeHigh,SizeLow,lpName)
MapViewOfFile(hMapHandle,DesiredAccess,offset.HighPart,offset.LowPart, 0)
UnmapViewOfFile(pFilePtr)
CloseHandle(hFile and hMapHandle)
B进程:打开文件映射,将文件映射对象映射到当前地址空间,进行读写操作,卸载映射,关闭句柄
OpenFileMapping(dwDesiredAccess,bInheritHandle,Name)
MapViewOfFile(hMapFile, DesiredAccess, offset.HighPart, offset.LowPart, 0)
UnmapViewOfFile(p)
CloseHandle(hFile and hMapHandle)
b.匿名映射
A进程:创建匿名文件映射,得到映射句柄,将文件映射对象映射到当前地址空间,进行读写操作,卸载映射、关闭句柄
hMapHandle = CreateFileMapping(hFile,MappingAttributes,flProtect,SizeHigh,SizeLow,lpName)
MapViewOfFile(hMapHandle,DesiredAccess,offset.HighPart,offset.LowPart, 0)
UnmapViewOfFile(pFilePtr)
CloseHandle(hFile and hMapHandle)
B进程:输入A进程的进程ID和映射句柄,得到A进程句柄,将目标进程的映射句柄复制到当前进程,将文件映射对象映射到当前地址空间,进行读写操作,卸载映射、关闭句柄
DuplicateHandle(ProcessHandle, MappingHandle, GetCurrentProcess(), &v1, 0, FALSE, DUPLICATE_SAME_ACCESS);
VirtualAddress = (ULONG_PTR)MapViewOfFile(v1,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0)
UnmapViewOfFile(p)
CloseHandle(hFile and hMapHandle)

2.邮件槽(mailslot,服务端只能接收、客户端只能发送,利用主存的一个临时虚拟文件)
单向、广播、数据报
基于广播通信设计出来的,采用UDP数据传输协议
Server端(读消息)创建邮件槽,服务端获取邮件槽数据(邮件槽句柄、最大消息限制、下一条消息的大小、消息个数、无限时),根据消息个数遍历读取消息信息,关闭句柄
Handle Mailslot = CreateMailslot(mailslotName,MaxMessageSize)
GetMailslotInfo(m_MailSlotHandle, NULL, &NextSize, &MessageCount, NULL)
ReadFile(this->m_MailSlotHandle, BufferData, NextSize, &ReturnLength, NULL);
Close(Mailslot)
Client端(写消息)打开邮件槽,写入数据,关闭句柄
MailSlotHandle = CreateFile(MAIL_SLOT_NAME,GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
WriteFile(MailSlotHandle, BufferData, BufferLength*sizeof(TCHAR), &ReturnLength, NULL);
Close(Mailslot)

3.管道(匿名管道、命名管道)
a.匿名管道(本机父子进程,基于字符,半双工/单向,一般用于输入重定向)
父进程:创建匿名管道,创建子进程,通过管道发送数据,接受管道数据,关闭句柄
CreatePipe(hReadPipe,hWritePipe,LPSECURITY_ATTRIBUTES lpPipeAttributes,PipeSize);
CreateProcess(_T("SubProcess.exe"), (LPTSTR)BufferData, NULL, NULL, TRUE/允许继承句柄/, CREATE_NEW_CONSOLE/让子进程拥有一个黑窗口/, NULL, NULL,&StartupInfo, &ProcessInfo);
WriteFile(m_hPipeWrite, (LPCTSTR)data, data.GetLength()2, &data_write, NULL)
ReadFile((HANDLE)(
PipeRead), data, 4096, &data_read, NULL)
Close(Pipe)
子进程:从父进程获得管道句柄,发送和接受数据,关闭句柄
m_hPipeRead = GetStdHandle(STD_INPUT_HANDLE);
m_hPipeWrite = GetStdHandle(STD_OUTPUT_HANDLE);
Read Or Write
Close(Pipe)

b.命名管道(网络,允许异步操作,面向消息和全双工,服务器和客户端都可以发送和接收数据)
异步Io结构,(该结构体内有一个event事件,当有客户端进行连接时变为有信号)
多个管道可以由同一个命名,几个客户端使用相同名称的管道和同一个服务器通信
Server端:创建命名管道,创建事件对象,等待客户端连接,检测I/0是否已经完成,从管道中读取或写入信息,断开连接,关闭句柄
PipeHandle = CreateNamedPipe(PipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,PIPE_TYPE_BYTE|PIPE_READMODE_BYTE | PIPE_WAIT, ConnectCount, 0, 0, 1000, NULL);
EventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
ConnectNamedPipe(UserData.PipeHandle, &Overlapped);
WaitForSingleObject(UserData.EventHandle, INFINITE);
GetOverlappedResult(UserData.PipeHandle, &Overlapped, &ReturnLength, true)
ReadFile(UserData.PipeHandle, BufferData, 0x1000sizeof(TCHAR), &ReturnLength, NULL)
WriteFile(UserData.PipeHandle, BufferData, _tcslen(BufferData)
sizeof(TCHAR), &ReturnLength, NULL);
DisconnectNamedPipe(UserData.PipeHandle);
Close(Pipe)
Client端:等待链接,打开管道,读写数据,关闭句柄
WaitNamedPipe()
NamedPipeHandle = CreateFile(_T("\\.\Pipe\Shine"), GENERIC_READ | GENERIC_WRITE,0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(NamedPipeHandle, BufferData, _tcslen(BufferData)sizeof(TCHAR), &ReturnLength, NULL);
ReadFile(NamedPipeHandle, BufferData, 0x1000
sizeof(TCHAR), &ReturnLength, NULL);
Close(Pipe)

4.剪切板(本机,属于系统维护的公共区域)
系统所有进程都可以无限制的访问剪切板,是不可靠的通信方式
A进程:打开剪切板,申请可移动内存,锁定该内存,写入数据,解锁该内存,设置剪切板内容,关闭剪切板,释放移动内存
OpenClipboard(GetDesktopWindow())
ClipboardHandle = GlobalAlloc(GMEM_MOVEABLE, (strlen(v1) + 1));
VirtualAddress = (TCHAR)GlobalLock(ClipboardHandle);
memcpy(VirtualAddress, v1,(strlen(v1) + 1)
sizeof(char));
GlobalUnlock(ClipboardHandle);
SetClipboardData(CF_TEXT, ClipboardHandle);
CloseClipboard();
GlobalFree(ClipboardHandle);
B进程:打开剪切板,获得剪切板里的信息,通过句柄锁定内存,读剪切板数据,解锁内存,关闭剪切板
OpenClipboard(GetDesktopWindow())
ClipboardHandle = GetClipboardData(CF_TEXT);
VirtualAddress = (TCHAR*)GlobalLock(ClipboardHandle);
ViewSize = GlobalSize(ClipboardHandle);
memcpy(v5, VirtualAddress, ViewSize);
GlobalUnlock(ClipboardHandle);
CloseClipboard();

5.父子进程间通信
a.句柄继承
父进程:创建一个安全描述结构体并设置允许句柄被继承,创建一个事件对象(作为数据和通知),创建一个子进程并将当前进程中数据以命令行参数(或环境变量)形式传递到子进程
SECURITY_ATTRIBUTES SecurityAttributes;
SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
SecurityAttributes.bInheritHandle = TRUE; //允许句柄继承
SecurityAttributes.lpSecurityDescriptor = NULL;
EventHandle = CreateEvent(&SecurityAttributes,TRUE,FALSE,NULL);//EventHandle到BufferData需要字符串格式转换
CreateProcess(_T("SubProcess.exe"), (LPTSTR)BufferData, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL,&StartupInfo, &ProcessInfo);//命令行参数
CreateProcess(_T("SubProcess.exe"), NULL, NULL, NULL, TRUE,CreateFlags | CREATE_NEW_CONSOLE,/表示环境参数的格式。如果设置了此标志,lpEnvironment所指向的环境块将使用Unicode字符。否则,环境块使用ANSI字符/(LPVOID)BufferData,/新的环境变量内存块/NULL, &StartupInfo, &ProcessInfo);//环境变量
WaitForSingleObject(EventHandle, INFINITE);
CloseHandle(EventHandle);
子进程:接受命令行参数(或环境变量),设置授信状态,关闭句柄
_stscanf_s((TCHAR*)argv[0], _T("%d"), &EventHandle);//获得命令行参数
BufferLength = GetEnvironmentVariable(BufferData, NULL, 0);
GetEnvironmentVariable(BufferData, v5, BufferLength + 1);
_stscanf_s(v5, _T("%d"), &EventHandle);//获得环境变量
SetEvent(EventHandle);//授信状态
CloseHandle(EventHandle);
b.父子进程通信:父进程等待子进程完成初始化,父进程可以将一条信息发送或发布到由子进程中的一个进程创建的窗口
父进程:(一些准备工作,如上)创建子进程,给子进程初始化的时间,通过窗口标题名称获得窗口句柄,向目标窗口发送信息,等待触信,关闭句柄
CreateProcess(_T("SubProcess.exe"),NULL, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInfo);
WaitForInputIdle(ProcessInfo.hProcess, 1000);
SendMessage(v1, UM_SEND, NULL, (LPARAM)EventHandle);
WaitForSingleObject(EventHandle, INFINITE);
CloseHandle(EventHandle);
子进程:创建一个模态对话框,判断消息类型,接受父进程传递的消息,显示在界面上,授信,关闭句柄
DialogBoxParam(Instance, MAKEINTRESOURCE(IDD_DIALOG), NULL, (DLGPROC)CallBackRoutine, NULL);
__EventHandle = (HANDLE)ParameterData2;
TCHAR BufferData[20] = { 0 };
_stprintf(BufferData, _T("0x%p"), ParameterData2);
SetDlgItemText(Hwnd, IDC_STATIC_SHOW, BufferData);
SetEvent(__EventHandle);
CloseHandle(EventHandle);
c.改变句柄标志,控制继承的子进程
(父进程生成了一个内核对象,得到了一个可继承的句柄,生成了两个子进程,但是父进程只希望其中的一个子进程继承内核对象句柄。)
父进程:获得当前进程伪句柄,将伪句柄转为真句柄,关闭句柄继承标志,创建子进程A,打开句柄继承标志,创建子进程B,关闭句柄
PseudoProcessHandle = GetCurrentProcess();
DuplicateHandle(GetCurrentProcess(), PseudoProcessHandle, GetCurrentProcess(), &RealProcessHandle,0, FALSE, DUPLICATE_SAME_ACCESS);
SetHandleInformation(RealProcessHandle, HANDLE_FLAG_INHERIT, NULL)
CreateProcess(_T("SubProcess(A).exe"),BufferData, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInfo);
//用SetHandelInformation函数修改了句柄继承标志,即使在创建进程的时候将继承设置为True,子进程也无法继承父进程的句柄。
SetHandleInformation(RealProcessHandle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)
CloseHandle(RealProcessHandle);
子进程A不能接收到父进程传送的数据,子进程B可以

6.网络TCP
Server端:初始化网络环境,创建Socket,绑定端口号IP地址,监听,接受客户端连接,接受信息,向客户端发送信息,关闭套接字
WSADATA data{0};
WSAStartup(MAKEWORD(2,2), &data);
SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//①
sockaddr_in serverAddr{0};
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8888);
inet_pton(AF_INET,"127.0.0.1",&serverAddr.sin_addr);
bind(server, (SOCKADDR)&serverAddr,sizeof(serverAddr));//②
listen(server,SOMAXCONN);//③
SOCKET client = accept(server, (SOCKADDR
)&clientAddr, &size);//④
recv(client, buff, 0x100, 0);//⑤
send(client, "有本早奏,无本退朝!", 20, 0);//⑥
closesocket(server);
Client端:初始化网络环境,创建SOCKET,绑定端口号IP地址,连接服务器,发送信息,接受信息
SOCKET client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
result=connect(client, (SOCKADDR*)&serverAddr,sizeof(serverAddr));
send(client,"臣刘墉有本要奏!\n",16,0);
recv(client, buff,0x100,0);

标签:IPC,映射,EventHandle,句柄,间通信,BufferData,进程,NULL
From: https://www.cnblogs.com/hanpto/p/17251143.html

相关文章

  • R3枚举进程模块的方法
    R3层枚举进程模块的方法有以下三种:1.ToolHelp库2.PsApi库3.遍历Peb中的Ldr链表1.ToolHelp库:点击查看代码HANDLEhSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAP......
  • 进程的创建过程
    创建进程共有六个阶段:I:打开目标映像文件Ⅱ:创建Windows的(内核)管理层进程对象,即“进程控制块”EPROCESS数据结构及相应的句柄Ⅲ:创建该进程的初始(第一个)线程,包括其堆栈、上......
  • Python多进程代码调试工具
    https://github.com/Lightning-AI/forked-pdbimportsysimportpdbclassForkedPdb(pdb.Pdb):"""PDBSubclassfordebuggingmulti-processedcodeSug......
  • 请写一个用python3.x pool.map多进程下载文件的示例代码
    自己改了一下要下载的url,一个网页,一个exe,一个PDFimportrequestsimportmultiprocessingdefdownload_file(url):local_filename=url.split('/')[-1]with......
  • Cadence入门笔记(十):IPC文件、坐标文件、装配图和打样
    IPCIPC文件用于生产时工厂检查生产出来的PCB线路是否导通,导出方法如下:选择导出IPC356文件一般默认配置即可坐标文件坐标文件用于工厂SMT贴片时候用,导出方法如下:点......
  • 系统间通信方式之 RPC的基本概念
    1、概述经过了详细的信息格式、网络IO模型的讲解,并且通过JAVARMI的讲解进行了预热。从这篇文章开始我们将进入这个系列博文的另一个重点知识体系的讲解:RPC。在......
  • Python multiprocessing 多进程
    进程:process线程:threadPython多进程和多线程哪个快由于GIL的存在,很多人认为Python多进程编程更快,针对多核CPU,理论上来说也是采用多进程更能有效利用资源。但这不是......
  • 进程管理 一 进程与线程
    为什么要引入进程?多道程序环境下,程序之间因共享资源而相互制约着运行,因此体现出间断性的特征。传统的程序是一组指令的集合,体现不出其在内存中的运行情况(间断性导致的何......
  • 进程管理 三 同步与互斥问题
    同步与互斥多道程序环境下,进程并发执行,不同进程之间存在不同的相互制约关系。同步——直接制约关系互斥——间接制约关系临界区互斥的实现方法软件实现方法单标志法标......
  • 进程管理 二 处理机调度问题
    调度的三个层次多道批处理系统中大多配有作业调度,而其他系统中通常不需要配置作业调度。中级调度实际上就是存储器管理中的对换功能。进程正在进行I/O操作时不能换......