Windows核心编程_数据段共享

数据段共享

数据段共享起源于Windows16位的时代,在Win16操作系统时代下,dll全局变量数据段是共享的,比如有同一个dll,名为sll.dll16位动态库,里面有一个全局变量

Int num;

有两个操作函数:

void setnum(int newnum){

num = newnum;

}

Int getnum(void){

return num;

}

当两个16位的进程加载这个动态库时,它们的数据段是共享的!

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

Asetnum(16);

B进程中调用getnum获取:

Bint b = getnum();

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

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

但是到了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会严格帮我们区分开!

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


猜你喜欢

转载自blog.csdn.net/bjbz_cxy/article/details/80762763