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)----共享内存的更多相关文章

  1. QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开     本文地址:h ...

  2. High Performance Networking in Google Chrome 进程间通讯(IPC) 多进程资源加载

    小结: 1. 小文件存储于一个文件中: 在内部,磁盘缓存(disk cache)实现了它自己的一组数据结构, 它们被存储在一个单独的缓存目录里.其中有索引文件(在浏览器启动时加载到内存中),数据文件( ...

  3. Android AIDL 进行进程间通讯(IPC)

    编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3. ...

  4. java 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)

    参考文章:http://ifeve.com/java-concurrency-thread-directory/ 其中的竞态,线程安全,内存模型,线程间的通信,java ThreadLocal类小节部 ...

  5. 【转】JAVA 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)

    原文地址:https://www.cnblogs.com/edenpans/p/6020113.html 参考文章:http://ifeve.com/java-concurrency-thread-d ...

  6. Windows进程间通讯(IPC)----内存映射文件

    内存映射文件原理 内存映射文件是通过在虚拟地址空间中预留一块区域,然后通过从磁盘中已存在的文件为其调度物理存储器,访问此虚拟内存空间就相当于访问此磁盘文件了. 内存映射文件实现过程 HANDLE hF ...

  7. Windows进程间通讯(IPC)----消息队列

    消息队列 windows系统是通过消息驱动的,每移动一下鼠标,点击一下屏幕都会产生一个消息.这些消息会先被放在windows的一个系统消息队列(先进先出)中,windows系统会为每一个GUI线程创建 ...

  8. Windows进程间通讯(IPC)----WM_COPYDATA

    WM_COPYDATA通讯思路 通过向其他进程的窗口过程发送WM_COPYDATA消息可以实现进程间通讯. 只能通过SendMessage发送WM_COPYDATA消息,而不能通过PostMessag ...

  9. 服务 远程服务 AIDL 进程间通讯 IPC

    Activity aidl接口文件 package com.bqt.aidlservice;  interface IBinderInterface {     /* 更改文件后缀为[.aidl]去掉 ...

随机推荐

  1. Spring笔记(三)

    Spring AOP 一.AOP(概念) 1. 什么是AOP 面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各个部分之间的耦合度降低,提高程序的可重用性,同时提高了 ...

  2. Web 前端 - 优雅地 Callback 转 Promise :aw

    前言 当今 ES7 标准大行其道,使用 async + await 将异步逻辑同步书写已经普及,但是却有许多旧库或旧代码尚未完全 Promise 化,急需一个小工具去挖去这代码中藓疾. 设计和实现 由 ...

  3. windows平台 cloin +rust 开发环境搭建

    rust 安装请看上一篇 clion 下载地址 破解 教程 1.先执行reset_jetbrains_eval_windows.vbs 2.打开软件选择免费使用 将ide-eval-resetter- ...

  4. 201871030125-王芬 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告

    实验三 软件工程结对项目 项目 内容 课程班级博客链接 https://edu.cnblogs.com/campus/xbsf/2018CST 这个作业要求链接 https://www.cnblogs ...

  5. OOUnit2Summary

    一.前三次作业内容分析 前言 第二单元的作业以多线程为主题,以电梯调度为背景,分三次要求逐步增加,难度逐步提高.这三次作业,更新了我对于面向对象编程的认知,也进一步提高了我编程和调试的能力. 一下是我 ...

  6. 周爱民带你深入剖析JavaScript核心原理

    作为前端工程师必备技能,JavaScript 的重要性不言而喻.虽然易上手,但却有着诸多复杂微妙的机制,想要真正掌握绝非易事. 专栏面向JavaScript语言的实际应用者与深度爱好者,以讲述Java ...

  7. Java后端进阶-网络编程(Netty责任链Pipeline)

    设计模式-责任链模式 一个责任链模拟demo package com.study.hc.net.netty.demo; // -----链表形式调用------netty就是类似的这种形式 publi ...

  8. 【Android实习】20场面试斩获大厂offer,我学会了什么

    前言 很高兴遇见你~ 先说一下笔者春招实习的情况:从三月初到四月半,经历了近20场面试,一共面试了五家企业,通过了腾讯.字节.蚂蚁.美团的面试,虎牙在一面之后拒了二面邀请. 金三银四,笔者不是在面试中 ...

  9. 1.jsp-out和response输出的区别

    jsp中代码: out.write("out输出1 <br/>"); out.write("out输出2 <br/>"); respon ...

  10. 设计原则:接口隔离原则(ISP)

    接口隔离原则的英文是Interface Segregation Principle,缩写就是ISP.与里氏替换原则一样其定义同样有两种 定义1: Clients should not be force ...