数据段共享

数据段共享起源于Windows16位的时代,在Win16操作系统时代下,16位windows用一个全局堆和局部堆来管理内存,每一个应用程序或dll装入内存时,代码段被装入全局堆,而系统又为每个实例从全局堆中分配了一个64kb的数据段作为该实例的局部堆,用来存放应用程序的堆栈和所有全局或静态变量。而LocalAlloc/GlobalAlloc就是分别用于在局部堆或全局堆中分配内存。

由于每个进程的局部堆很小,所以在局部堆中分配内存会受到空间的限制。但这个堆是每个进程私有的,相对而言分配数据较安全,数据访问出错不至于影响到整个系统。  而在全局堆中分配的内存是为各个进程共享的,每个进程只要拥有这个内存块的句柄都可以访问这块内存,但是每个全局内存空间需要额外的内存开销,造成分配浪费。而且一旦发生严重错误,可能会影响到整个系统的稳定。

不过在Win32中,每个进程都只拥有一个缺省的私有堆(默认的私有堆),它只能被当前进程访问。应用程序也不可能直接访问系统内存。所以在Win32中全局堆和局部堆都指向进程的省缺堆。用LocalAlloc/GlobalAlloc分配内存没有任何区别。甚至LocalAlloc分配的内存可以被GlobalFree释放掉。所以在Win32下编程,无需注意Local和Global的区别。

可以说是LocalAlloc分配的堆只能被当前进程下所拥有,GlobalAlloc分配的堆,只要其它进程拥有首地址都均可以访问,GlobalAlloc分配的内存空间区段上拥有的权限一般为:RWS,而LocalAlloc分配的内存区段一般为:RW

S代表特权,任何文件或进程都可以访问这个空间

注意每从堆中分配一次内存,这个内存都会携带一个区段用于表明此内存空间的作用,前40个字节为区段!

综上所述,堆在早期Windows下,可分配内存一律称为堆,没有栈可言,栈的的概念来自于局部变量或全局变量,这些变量的内存空间也是从堆中索取来的,当为这些基本类型比如int char分配的内存一律称为栈,而主动使用malloc或new分配的内存称之为堆,并且栈的大小是有限制的!

这里用dll做个比喻:

dll全局变量数据段是不共享的,我们不能直接对它进行访问和操作,比如有同一个dll,名为sll.dll的16位动态库,里面有一个全局变量

int num;

但是有两个操作函数(这两个函数(代码段)会被放入全局堆):

void setnum(int newnum){num = newnum;}int getnum(void){return num;}

当两个16位的进程加载这个动态库时

当A进程调用setnum设置新值以后:

A:setnum(16);

B进程中调用getnum获取:

B:int b = getnum();

那么此时B进程获取到的是A进程刚刚修改的值:16

双方可以很快完成进程间的通讯!

在win16下每个进程只能被加载到内存一次,但dll不一样,dll也只能被加载到内存一次,但是当其它进程想要在加载这个dll时将会引用这个dll内存,因为早期的dll是有自己的内存的,而不是加载到进程空间下,早期的dll是有自己的实列内存空间的!

但是到了win32以后,这种方法被删除了,但是被保留到编译器命令当中了!

#pragma data_seg

预处理指令

#pragma data_seg的使用方法如下:

#pragma data_seg(“mydate”)

Int num = 0;

#pragma data_seg()

注意必须是全局的,并且变量必须显示初始化,如果不初始化,编译器会自动帮你赋值0然后放到.BSS段里去,这样就不会放到共享内存段中去了!

并且也可以使用#pragma comment预处理指令里的linker来显示规定此共享数据段的连接方法:

#pragma comment(linker,”/SECTION:mydate,RWS")

R可读性

W可写

S任意程序/文件都可以使用此共享数据段

注意前面一定要加上/SECTION:这是来表明区段的,不然编译器不认!

而且此方法还可以用来检测当前程序在同一电脑上运行了多少个!

#pragma data_seg("flag_data")int app_count = 0;#pragma data_seg()#pragma comment(linker,”/SECTION:flag_data,RWS")BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL, // 指向自身的句柄_In_ DWORD fdwReason, // 调用原因_In_ LPVOID lpvReserved // 隐式加载和显式加载){if(app_count>0) // 如果计数大于0,则退出应用程序。{//MessageBox(NULL, "已经启动一个应用程序", "Warning", MB_OK); //printf("no%d application", app_count);return FALSE;}else{//计数+1app_count++;}}

有的dll可能不用dllmain函数,所以可以增加两个接口:

#pragma data_seg("flag_data")int app_count = 0;#pragma data_seg()#pragma comment(linker,”/SECTION:flag_data,RWS”)void add(){app_count++;}int returnapp(){return app_count;}

然后在应用程序入口使用:

int main(){if(returnapp() > 0){//MessageBox(NULL, "已经启动一个应用程序", "Warning", MB_OK); //printf("no%d application", app_count);return FALSE;}else{add();}}

或者用来判断当前系统下运行了多个此程序:

int main(){add();printf(“当前程序运行数量:%d”,returnapp);}

只要你显示的调用dll动态库里的函数,那么根据windows内核规则,动态库一定会被加载进来!

并且共享的数据段,不属于任何一个进程,Windows会把它独立放在一个内存段里,并维护它,然后有新的进程加载动态库时,Windows会检查dll里的共享数据段名是否已经存在,如果已经存在,则不在开辟,并且此动态库共享此段!那么问题来了,如果有两个新的动态库,并且段名一样怎么办?

答:操作系统是根据动态库名来区分此段属于那个动态库的,所以此问题无需我们关心,Wdindows会严格帮我们区分开!

使用此方法可以很轻松的实现进程间的共享数据!

最后值得提一下的是上面这些方法在进程中也是有效的!

Windows核心编程_代码段共享_LocalAlloc/GlobalAlloc区别相关推荐

  1. Windows核心编程_设置Windows开机自动登录

    设置自动登录的方法在Windows中已经给出了非常方便的方法,当Windows内核进入登入界面时会检查HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\ ...

  2. Windows核心编程_获取鼠标指定位置的RGB颜色值

    Windows核心编程_获取鼠标指定位置的RGB颜色值 大家平常会见到很多屏幕取色工具,其原理都是获取鼠标位置的屏幕像素点颜色! 一般思路都是:获取鼠标位置,然后取出鼠标指向的屏幕像素点颜色! Get ...

  3. Windows核心编程_提权

    在Windows下编程有些涉及到硬件或者跨内存的API会发现失效了,原因是因为权限问题,这也是Windows出于安全的保护,但是事物都有两面性的,Windows又为我们提供了提权的API! 1.Adj ...

  4. Windows核心编程_修改其它进程里的内存值+示例:修改游戏分数

    最近一直忙于Opencv图像处理方面的学习,以及工作,没有更新C/C++专栏方面的博客了,所以今天就给大家写个应用层方面的编程代码,可用于参考学习,本篇博客将运用WindowsSDK库所提供的API来 ...

  5. windows核心编程之进程间共享数据

    有时候我们会遇到window进程间共享数据的需求,例如说我想知道系统当前有多少某个进程的实例. 我们能够在程序中定义一个全局变量.初始化为0.每当程序启动后就加1.当然我们我们能够借助第三方介质来储存 ...

  6. Windows核心编程_静态编译和动态编译的区别

    1.静态编译 静态就是将需要的系统dll打包进PE文件(关于PE文件的深刻介绍博主会在后面对其进行介绍)中,编译器会将这些模块码,或资源文件的数据,全部添加到可执行文件中,存放在可执行文件的模块区或资 ...

  7. Windows核心编程_窗口透明组件不透明

    经过前几篇对界面编程的学习,已经对Windows窗口消息有了更加深刻的理解,今天就教大家写一个窗口透明而组件却不透明的小示列! 这个demo并不难,而且还非常的简单,如果你看过我的前几篇针对界面编程写 ...

  8. Windows核心编程_窗口蒙版效果

    首先先看一下界面效果: 遮罩窗口: 模糊模态窗口: 保留特定控件 模糊保留特定控件: 遮罩+模糊效果: 遮罩模态效果: 怎么样是不是很炫酷,非常适合在提示用户新信息或者其它需要模态窗口时候展现的效果, ...

  9. Windows核心编程_重绘ListBox样式(仿QQListBox)

    今天教大家如何重绘ListBox,其中涉及到的相关知识点也一一解释了 效果图: 是不是和QQ的列表框非常相似?那么这里就一步一步教大家如何使用Win32SDK来完成这项工作! 创建Win32窗口 #i ...

最新文章

  1. Guid和Int还有Double、Date的ToString方法的常见格式
  2. 【pyQuery】抓取startup news首页
  3. 一到关于js函数的前端面试题引发的血案
  4. 世界杯直播背后:腾讯云极速高清技术部署实录
  5. SSO单点登录之跨域问题
  6. 经典排序算法(十一)--堆排序Heap Sort
  7. 【Android】NanoHttpd学习(一)
  8. hc 05 蓝牙c语言程序,ATK-HC05 运用在STM32平台上的HC05蓝牙通信代码用C语言编写 - 下载 - 搜珍网...
  9. 网络翻译-利用有道接口
  10. oracle中的rownumber,oracle中row_number和rownum的区别和联系(翻译)
  11. 年月日、年积日、简化儒略日、GPS周之间相互转换(C++)
  12. Arm V8内存管理架构.学习笔记
  13. 电脑右下角的扬声器出现了红叉
  14. 十种最令人讨厌的编程语言,你使用的语言上榜了吗?
  15. 那些著名的网络攻击事件 一
  16. centos7FastDFS分布式安装部署
  17. 什么是IDC?IDC基础知识
  18. Iphone幻灯片效果+背景音乐
  19. C语言 统计英语文章单词的数目
  20. 一个面试回来的程序员的感想

热门文章

  1. 二维数组初始化_0基础学习C语言第七章:数组(2)
  2. 最积阴德的4件事,哪怕做过一件,也会累积大功德!
  3. vue大屏可视化布局
  4. docker 删除包含关键字的镜像_Docker 架构及工作原理
  5. 企业付款php 接口,微信企业付款接口PHP开发需要注意的两个地方
  6. wtc java 代码 tpcall(servicename_通过wtc使tuxedo及weblogic通信开发.doc
  7. java resultset 映射到实例_Java中,将ResultSet映射为对象和队列及其他辅助函数
  8. java中获取链表的第一个节点,两个链表中的第一个公共节点(java)
  9. pix4d怎么查看点云数据_PIX4D的两种像控点刺点方式探讨
  10. Java线程与Android线程,Android线程篇(三):深入理解Java线程池(一)