Windows进程间通讯(IPC)----共享内存
Windows中同一个EXE文件多次加载过程
Windows中EXE文件加载是基于内存映射文件的。
当EXE文件第一次被加载。
- 首先系统会先创建一个进程内核对象,并创建一个新的进程地址空间。
- 系统调用CreateFile打开对应的exe文件。
- 根据PE文件的路径创建文件映射对象,调用CreateFileMapping的参数fdwProtect传入SEC_IMAGE表示映射的文件是一个PE文件,这样系统会按照PE文件头中指定的信息在进程空间指定的地址处预留指定大小的区域,接着调用MapViewOfFileEx将内存映射文件映射到指定的进程地址空间处,因为映射的是一个用SEC_IMAGE属性创建的PE文件的内存映射文件所以系统会根据PE文件头中的信息将PE文件的内存映射文件映射到进程地址空间的各个地址处,并指定此区域的物理存储器来自于磁盘上的EXE文件。
- 这时PE文件并未真正加载到物理内存中,接着会根据PE文件中的输入表中的DLL信息加载DLL。
- 同样会按照DLL文件头的信息在进程空间中指定的地址处预留指定大小的区域,但因为其涉及到重定位所以地址可以改变,且指定预留区域的物理存储器来自于磁盘上的DLL文件和页交换文件。
- 当所有的DLL文件也都预留完区域后,会将EXE文件的第一张代码页加载到内存中,这时CPU运行程序。
- 当CPU运行到内存中不存在的代码页时会发生缺页中断,中断处理程序会将对应的页从磁盘中的EXE文件或DLL文件中加载到内存中。
当EXE文件第二次被加载。
- 因为其会判断此文件已经创建了文件映射对象,所以其不会再次创建文件映射对象了。
- 其直接利用已创建的文件映射对象来调用接着调用MapViewOfFileEx创建新的映射(映射到自己的进程空间中),因为其与第一次运行的程序实例使用的是同一个文件映射对象,因此其与第一次运行的程序实际使用同一块物理内存。
不使用共享内存
因为同一个EXE的多个实例使用的是同一物理内存,当在一个实例的进程空间中更改全局变量或者是局部变量时其他进程也应会做出相应变化。但是实际并没有,也就是全局变量和静态变量并不能在同一个EXE的多个实例进程间共享。原因是因为存在写时复制机制,当尝试更改全局变量或者是静态变量时系统会将物理内存对应的内存页复制到页交换文件中,并修改页交换文件中的内容。此后进程对应的区域就会映射到页交换文件处而不是物理内存处。这样不同的进程映射到不同的页交换文件中所以其不会更改物理内存中的数据,同样无法实现进程间通讯。
使用共享内存
在EXE中使用
使用共享内存实际就是屏蔽写时复制机制,如果指定内存为共享内存则在不同的进程实例中对其更改时,其不会发生写时复制而是直接更改对应物理内存中的数据,所以可以实现进程间通讯。
#pragma data_seg("区块名")
DWORD dwData = 0;
#pragma data_seg()
在源程序中使用如上代码告诉编译器创建一个区块,并且在区块中定义一个变量,此变量必须初始化否则编译器不会将其放在此区块中而是放在其他区块中。
#pragma comment(linker, "/SECTION:区块名,RWS")
在源程序中使用如上代码告诉链接器,更改指定区块的属性,R表示读,W表示写,E表示执行,S表示共享。
在DLL中使用
因为如果一个DLL被多个EXE加载,那么其也只是对此DLL的文件映射对象多建立了几个映射,实际在物理内存中只会存在一块DLL的内存,所以我们可以通过在DLL中使用共享内存而在不同的进程中加载此DLL,利用此DLL的共享内存实现进程间通讯。
#pragma data_seg("区块名")
DWORD dwData = 0;
#pragma data_seg()
#pragma comment(linker, "/SECTION:区块名,RWS")
//导出函数
DWORD GetData()
{
return dwData;
}
void SetData(DWORD dwNum)
{
dwData = dwNum;
}
在DLL中使用共享内存与在EXE中使用共享内存相似,因为DLL被其他进程加载不能直接访问到共享内存中的变量,所以通过对DLL导出函数实现对DLL共享内存的访问。
Windows进程间通讯(IPC)----共享内存的更多相关文章
- QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开 本文地址:h ...
- High Performance Networking in Google Chrome 进程间通讯(IPC) 多进程资源加载
小结: 1. 小文件存储于一个文件中: 在内部,磁盘缓存(disk cache)实现了它自己的一组数据结构, 它们被存储在一个单独的缓存目录里.其中有索引文件(在浏览器启动时加载到内存中),数据文件( ...
- Android AIDL 进行进程间通讯(IPC)
编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3. ...
- java 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)
参考文章:http://ifeve.com/java-concurrency-thread-directory/ 其中的竞态,线程安全,内存模型,线程间的通信,java ThreadLocal类小节部 ...
- 【转】JAVA 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)
原文地址:https://www.cnblogs.com/edenpans/p/6020113.html 参考文章:http://ifeve.com/java-concurrency-thread-d ...
- Windows进程间通讯(IPC)----内存映射文件
内存映射文件原理 内存映射文件是通过在虚拟地址空间中预留一块区域,然后通过从磁盘中已存在的文件为其调度物理存储器,访问此虚拟内存空间就相当于访问此磁盘文件了. 内存映射文件实现过程 HANDLE hF ...
- Windows进程间通讯(IPC)----消息队列
消息队列 windows系统是通过消息驱动的,每移动一下鼠标,点击一下屏幕都会产生一个消息.这些消息会先被放在windows的一个系统消息队列(先进先出)中,windows系统会为每一个GUI线程创建 ...
- Windows进程间通讯(IPC)----WM_COPYDATA
WM_COPYDATA通讯思路 通过向其他进程的窗口过程发送WM_COPYDATA消息可以实现进程间通讯. 只能通过SendMessage发送WM_COPYDATA消息,而不能通过PostMessag ...
- 服务 远程服务 AIDL 进程间通讯 IPC
Activity aidl接口文件 package com.bqt.aidlservice; interface IBinderInterface { /* 更改文件后缀为[.aidl]去掉 ...
随机推荐
- HDFS设置配额的命令
1 文件个数限额 #查看配额信息 hdfs dfs -count -q -h /user/root/dir1 #设置N个限额数量,只能存放N-1个文件 hdfs dfsadmin -setQuota ...
- java面试一日一题:rabbitMQ的工作模式
问题:请讲下rabbitMQ的工作模式 分析:该问题纯属概念题,需要掌握rabbtiMQ的基础知识,同时该题也是切入MQ的一个引子: 回答要点: 主要从以下几点去考虑, 1.rabbitMQ的基本概念 ...
- [图论]牛的旅行 Cow Tours :Floyed-Warshall
牛的旅行 Cow Tours 目录 牛的旅行 Cow Tours 题目描述 输入格式 输出格式 输入输出样例 输入 #1 输出 #1 解析 代码 题目描述 农民 John的农场里有很多牧区.有的路径连 ...
- windows认证解读
0x00 本地认证 本地认证基础知识 在本地登录Windows的情况下,操作系统会使用用户输入的密码作为凭证去与系统中的密码进行验证,但是操作系统中的密码存储在哪里呢? %SystemRoot%\sy ...
- --系统编程-网络-tcp客户端服务器编程模型、socket、htons、inet_ntop等各API详解、使用telnet测试基本服务器功能
PART1 基础知识 1. 字节序 网络字节序是大端字节序(低地址存放更高位的字节), 所以,对于字节序为小端的机器需要收发网络数据的场景,要对这些数据进行字节序转换. 字节序转换函数,常用的有四个: ...
- Kubernetes Secrets
Secrets 背景信息 Kubernetes版本 [09:08:04 yhf@test ~]$ kubectl version Client Version: version.Info{Major: ...
- 1. Intellij IDEA导入,主题修改,布局界面+部分工具栏菜单介绍
Project 和module 的区别 module 相当与eclispe的项目project 相当与eclpise的工作空间 主题的修改 Setting的快捷键:Ctrl+shift+S
- 【Redis破障之路】三:Redis单线程架构
众所周知,Redis是一个单线程架构的NoSQL数据库,但是是单线程模型的Redis为什么性能如此之高?这就是我们接下来要探究学习的内容. 1.Redis的单线程架构 1.1.Redis单线程简介 首 ...
- 无所不能的PowerMock,mock私有方法,静态方法,测试私有方法,final类
1.为什么要用mock 我的一本书的解释: (1)创建所需的DB数据可能需要很长时间,如:调用别的接口,模拟很多数据 (2)调用第三方API接口,测试很慢, (3)编写满足所有外部依赖的测试可能很复杂 ...
- 1027 Colors in Mars
People in Mars represent the colors in their computers in a similar way as the Earth people. That is ...