[转]Windows 下的进程间通讯及数据共享
http://blog.codingnow.com/2005/10/interprocess_communications.html
Windows 下有很多方法实现进程间通讯,比如用 socket,管道(Pipe),信箱(Mailslot),等等。但最基本最直接的还是使用内存共享。其他方法最终还是会绕道这里。
可想而知,如果物理内存只有一份,让这份内存在不同的进程中,映射到各自的虚拟地址空间上,每个进程都可以读取同一份数据,是一种最高效的数据交换方法。下面我们就讨论如何实现它。
共享内存在 Windows 中是用 FileMapping 实现的。我们可以用 CreateFileMapping 创建一个内存文件映射对象, CreateFileMapping 这个 API 将创建一个内核对象,用于映射文件到内存。这里,我们并不需要一个实际的文件,所以,就不需要调用 CreateFile 创建一个文件, hFile 这个参数可以填写 INVALID_HANDLE_VALUE 。但是,文件长度是需要填的。Windows 支持长达 64bit 的文件,但是这里,我们的需求一定不会超过 4G , dwMaximumSizeHigh 一定是 0 ,长度填在 dwMaximumSizeLow 即可。然后调用 MapViewOfFile 映射到当前进程的虚拟地址上即可。一旦用完共享内存,再调用 UnmapViewOfFile 回收内存地址空间。
Windows 把 CreateFileMapping 和 MapViewOfFile 两个 API 分开做是有它的道理的。这是因为允许映射一个超过 4G 的文件,而地址空间最大只有 4G (实际上,一般用户的程序只能用到 2G) , MapViewOfFile 就可以指定文件的 Offset 而只映射一部分。
在 CreateFileMapping 的最后一个参数 pszName 填写一个名字,那么别的进程就可以用这个名字去调用 OpenFileMapping 来打开这个 FileMapping 对象,在新的进程内作映射。 不过,通过约定字符串的方法似乎不太优雅。
一个优雅的方法是,用 DuplicateHandle 在新进程中复制一份 FileMapping 对象出来,然后想办法把 Handle 通知新进程,比如用消息的方式传递过去。
如果需要共享内存的两个进程是父子关系,那么我们可以不用消息传递的方式来通知 FileMapping 的 Handle 。父进程可以用继承 Handle 的方式直接把 FileMapping 的 Handle 传递到子进程中。当然,在 CreateFileMapping 时就应该设置可以被继承的属性。
大约是这样:
SECURITY_ATTRIBUTES sa;
sa.nLength=sizeof(sa);
sa.lpSecurityDescriptor=NULL;
sa.bInheritHandle=TRUE;
handle=CreateFileMapping(INVALID_HANDLE_VALUE,&sa,PAGE_READWRITE,0,size,NULL);
这样,在 CreateProcess 的时候,如果 bInheritHandles 参数为 TRUE ,所有有可被继承属性的内核对象都会被复制到子进程中。
注:内核对象的继承就是在 CreateProcess 创建子进程,但是子进程的主线程尚未活动之前,内核扫描当前进程中所有内核对象,检查出有可继承属性的那些,再用 DuplicateHandle 复制一份到子进程。由于是内核对象,在内核中实质只有一份,所有只是引用记数加一,父进程和子进程对同一内核对象的 Handle 一定是相同的。
复制内核对象的过程是由 CreateProcess 内部完成的,我们可以放心的把对象 Handle (和子进程相同) 通过命令行传递给子进程。或者,用环境变量传递也可以。
值得注意的是,子进程用完了这个 FileMapping 对象后一样需要 CloseHandle 减去引用计数。
备注:
CreateProcess 调用时,pszCommandLine 不能直接填上一个不可修改的字符串。例如:
CreateProcess("test.exe","test argument",...);
这样就是错误的,因为 "test argument" 会被编译器编译放到不可修改的数据段中。正确的方法是:
char cmdline[]="test argument";
CreateProcess("test.exe",cmdline,...);
这样,命令行的字符串就被放在堆栈上,是可以被读写的。
CreateProcess 的倒数第二个参数需要填写一个 STARTUPINFOW 结构,这个结构很复杂,通常填起来很麻烦。我们可以复制一份父进程的结构,再酌情修改。方法是:
STARTUPINFO si={sizeof(si)};
PROCESS_INFORMATION pi;
GetStartupInfo(&si);
CreateProcess(...,&si,& pi);
这里, STARTUPINFO 结构的第一个长度信息通常应该填上,保证 GetStartupInfo(&si); 的正确执行。
[转]Windows 下的进程间通讯及数据共享的更多相关文章
- Windows进程间通讯(IPC)----消息队列
消息队列 windows系统是通过消息驱动的,每移动一下鼠标,点击一下屏幕都会产生一个消息.这些消息会先被放在windows的一个系统消息队列(先进先出)中,windows系统会为每一个GUI线程创建 ...
- Windows进程间通讯(IPC)----共享内存
Windows中同一个EXE文件多次加载过程 Windows中EXE文件加载是基于内存映射文件的. 当EXE文件第一次被加载. 首先系统会先创建一个进程内核对象,并创建一个新的进程地址空间. 系统调用 ...
- Windows进程间通讯(IPC)----内存映射文件
内存映射文件原理 内存映射文件是通过在虚拟地址空间中预留一块区域,然后通过从磁盘中已存在的文件为其调度物理存储器,访问此虚拟内存空间就相当于访问此磁盘文件了. 内存映射文件实现过程 HANDLE hF ...
- Windows进程间通讯(IPC)----WM_COPYDATA
WM_COPYDATA通讯思路 通过向其他进程的窗口过程发送WM_COPYDATA消息可以实现进程间通讯. 只能通过SendMessage发送WM_COPYDATA消息,而不能通过PostMessag ...
- .Net 利用消息在进程间通讯实现进程互操作
有时候我们会遇到需要在两个进程间通过某种方式实现互操作,方法有很多,例如你可以尝试让两个进程持续监视一个外部文件,由此文件记录各自进程的数据:还有可以使用网络端口实现进程间通讯.共享一片内存区域记录及 ...
- Python 第八篇:异常处理、Socket语法、SocketServer实现多并发、进程和线程、线程锁、GIL、Event、信号量、进程间通讯
本节内容: 异常处理.Socket语法.SocketServer实现多并发.进程和线程.线程锁.GIL.Event.信号量.进程间通讯.生产者消费者模型.队列Queue.multiprocess实例 ...
- 管道实现进程间通讯 、WaitNamedPipe
一.管道实现进程间通讯 主要的理论知识 1.什么是管道以及分类 管道是两个头的东西,每一个头各连接一个进程或者同一个进程的不同代码,依照管道的类别分有两种管道,匿名的和命名的:依照管道的传输方向分也能 ...
- Node.js - 阿里Egg的多进程模型和进程间通讯
前言 最近用Egg作为底层框架开发项目,好奇其多进程模型的管理实现,于是学习了解了一些东西,顺便记录下来.文章如有错误, 请轻喷 为什么需要多进程 伴随科技的发展, 现在的服务器基本上都是多核cpu的 ...
- C#进程间通讯或同步的框架引荐
这篇文章主要介绍了一个进程间通讯同步的C#框架,代码具有相当的稳定性和可维护性,随着.NET的开源也会被注入更多活力,推荐!需要的朋友可以参考下 0.背景简介 微软在 .NET 框架中提供了多种实用 ...
随机推荐
- Install and set JAVA home on MAC OS with commandline
最近需要在MAC上做一些测试,由于测试机没有安装Java,只能自己安装,由于不能通过图形化界面访问测试机,只能通过命令行的形式来安装JAVA. 1. Download the jre/jdk inst ...
- 兼容各版本浏览器,封装原生Js获取ClassName
web前端开发工作中常常会用到获取元素的className,用jQuery的$(".class")方法也可以获取className,但是有时候牵扯到数据而影响的加载顺序的原因会获取 ...
- SQL注入的常用函数和语句
1.系统函数 version() Mysql版本user() 数据库用户名database() 数据库名@@datadir 数据库路径@@version_compile_os 操 ...
- Java标识符和关键字
一.标识符 概念:就是用于给程序中的变量.类.方法命名的符号; 标识符规则:标识符可以有字母.数字.下划线_.和美元符号$组成,并且数字不能打头 ...
- .Net Core + Angular2 环境搭建
环境搭建: 1)node.js版本>5.0,NPM版本>3.0,TypeScript版本>2.0(全装最新版就好了) 2)安装NTVS 1.2(node tools for vs), ...
- MySQL知识树-支持的数据类型
本篇学习笔记的主要内容: 介绍MySQL支持的各种数据类型(常用),并讲解其主要特点. MySQL支持多种数据类型,主要包括数值类型.日期和时间类型.字符串类型. 数值类型 MySQL的数值类型包 ...
- JAVA深入研究——Method的Invoke方法。
在写代码的时候,发现Method可以调用子类的对象,但子类即使是改写了的Method,方法名一样,去调用父类的对象也会报错,虽然这是很符合多态的现象,也符合java的动态绑定规范,但还是想弄懂java ...
- 数据结构与算法分析-AVL树
1.AVL树是带有平衡条件的二叉查找树. 2.AVL树的每个节点高度最多相差1. 3.AVL树实现的难点在于插入或删除操作.由于插入和删除都有可能破坏AVL树高度最多相差1的特性,所以当特性被破坏时需 ...
- capwap协议重点分析
一. CAPWAP概述 CAPWAP由两个部分组成:CAPWAP协议和无线BINDING协议. (1)CAPWAP协议是一个通用的隧道协议,完成AP发现AC等基本协议功能,和具体的无线接入技术 ...
- Implement Trie (Prefix Tree)
Trie 树实现 Implement a trie with insert, search, and startsWith methods. class TrieNode { public: // I ...