您的位置:首页 > 其它

保证一个程序在同一台PC中只运行一个实例的两种方法

2012-05-14 10:42 417 查看
最近在研究《Windows核心编程》,留意到书中涉及到的两个知识点可以解决这个问题,觉得蛮有意思的,就记录下来,和大家分享下。

第一种方法:采用线程同步中的互斥量内核对象

互斥量(mutex)内核对象用来确保一个线程独占对一个资源的访问。 --------《Windows核心编程》

互斥量对象包含一个使用计数,线程ID以及一个递归函数。 --------《Windows核心编程》

涉及到的函数

HANDLE CreateMutex(

PSECURITY_ATTRIBUTES psa,

BOOL bInitialOwner,

PCTSTR pszName,

);

psa为安全属性,只要见到PSECURITY_ATTRIBUTES这个数据类型那就说明该函数涉及内核对象,所有的内核对象的创建函数都会有这个属性。

bInitialOwner 如果该值为TRUE时,线程则立即拥有该互斥量,递归计数将被设为1,如果为FALSE,互斥量对象的线程ID和递归计数都将设置为0,互斥量处于触发状态。

pszName指定互斥体对象的名字。

BOOL ReleaseMutex(HANDLE hMutex);释放互斥量。

CloseHandle(HANDLE) 清理句柄

代码示例:

实验思路,先用VS2010创建一个win32程序,程序的主窗口以及消息循环向导程序已经创立完毕,我们只需在程序的入口处创建一个互斥量,再程序退出时释放互斥量就可以了。如果在创建过程中互斥量已经存在,则调用GetLastError()会返回ERROR_ALREADY_EXISTS



还有在程序结束前别忘记要释放互斥量以及CloseHandle();



运行结果:

运行一个实例



再运行一个实例的时候


出现这个提示,确定后程序直接退出。

第二种方法:采用内存映射文件共享数据段

当我们运行一个程序的时候,内存首先要将exe或DLL装载入内存中。.exe和DLL文件映像是由许多段组成,

每个标准的段名都以点号开始。例如。在编译程序的时候,编译器会将代码放在一个名叫.text的段中。再如

可执行文件的常用段

.bbs 未经初始化的数据

.CRT 只读的C运行时数据

.date 已初始化的数据

...............

除了这些标准的段外,Microsoft还允许我们创建自己的段。

#pragma data_seg("sectionname");

那么我们就可以创建一个自定义段, 包含一个Long变量

#pragma date_seg("Shared")

volatile LONG m_share_data=0;

#pragma date_seg("Shared")

如果将Shared这个段设置为共享的话,那么所有该程序的实例都会共享这个数据段,这样就可以通过m_sharea_date

来获得运行实例的数量。

#pragma comment(linker,"/SECTION:Shared,RWS");

R表示Read,W表示WRITE,E表示EXECUTE,S表示SHARED

代码示例:

实验思路,创建一个共享数据段,在共享数据段里声明一个long的数据m_share_data,当第一个实例运行的时候将m_share_data加1 ,每次程序运行都会检测这个值,如果大于1那就表示已经有一个实例在运行了。





运行结果:



再运行一个实例的时候



总结:

线程同步分为用户模式的线程同步以及内核模式的线程同步,互斥量只是内核模式线程同步中的一种,

而内存映射则是属于内存管理的范畴,这里提到的只是其中一个很小的知识点,也就是为大家更好的理解Windows编程起到一个抛砖引玉的作用吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: