互斥量的使用,是应用程序只运行一次

转载 2012年09月18日 21:52:27

转载:http://hi.baidu.com/jenfmo/blog/item/d5a298543da5b35ad009060b.html

正常情况下,一个进程的运行一般是不会影响到其他正在运行的进程的。但是对于某些有特殊要求的如以独占方式使用串行口等硬件设备的程序就要求在其进程运行期间不允许其他试图使用此端口设备的程序运行的,而且此类程序通常也不允许运行同一个程序的多个实例。这就引出了进程互斥的问题。

  实现进程互斥的核心思想比较简单:进程在启动时首先检查当前系统是否已经存在有此进程的实例,如果没有,进程将成功创建并设置标识实例已经存在的标记。此后再创建进程时将会通过该标记而知晓其实例已经存在,从而保证进程在系统中只能存在一个实例。具体可以采取内存映射文件、有名事件量、有名互斥量以及全局共享变量等多种方法来实现。下面就分别对其中具有代表性的有名互斥量和全局共享变量这两种方法进行介绍:
  // 创建互斥量
HANDLE m_hMutex = CreateMutex(NULL, FALSE, "Sample07");
// 检查错误代码
if (GetLastError() == ERROR_ALREADY_EXISTS) {
 // 如果已有互斥量存在则释放句柄并复位互斥量
 CloseHandle(m_hMutex);
 m_hMutex = NULL;
 // 程序退出
 return FALSE;
}

  上面这段代码演示了有名互斥量在进程互斥中的用法。代码的核心是CreateMutex()对有名互斥量的创建。CreateMutex()函数可用来创建一个有名或无名的互斥量对象,其函数原型为:

HANDLE CreateMutex(
 LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全属性的指针
 BOOL bInitialOwner, // 初始化互斥对象的所有者
 LPCTSTR lpName // 指向互斥对象名的指针
);

  如果函数成功执行,将返回一个互斥量对象的句柄。如果在CreateMutex()执行前已经存在有相同名字的互斥量,函数将返回这个已经存在互斥量的句柄,并且可以通过GetLastError()得到错误代码ERROR_ALREADY_EXIST。可见,通过对错误代码ERROR_ALREADY_EXIST的检测可以实现CreateMutex()对进程的互斥。


建立互斥体,用来同步。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。 
    参数 
    lpMutexAttributes   
    指向一个SECURITY_ATTRIBUTES结构的指针,这个结构决定互斥体句柄是否被子进程继承。    
    bInitialOwner
    布尔类型,决定互斥体的创建者是否为拥有者 
    lpName   
    指向互斥体名字字符串的指针。互斥体可以有名字。 
    互斥体的好处是可以在进程间共享.

//---------------------------------------------------------------------------------------双击程序不提示已经运行而是将窗口置顶------------------------------

1.使用CreateMutex检查程序已经运行

2.如果已经执行使用::FindWindow(NULL, "窗口的名称")获取窗口句柄

3.在使用 函数原型:BOOL SetForegroundWindow()
SetForegroundWindow  函数功能:该函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。系统给创建前台窗口的线程分配的权限稍高于其他线程。
备注:前台窗口是z序顶部的窗口,是用户的工作窗口。在一个多任务优先抢占环境中,应让用户控制前台窗口。
  Windows NT 5.0:当用户在另一个窗口中工作时,应用程序不能强行设置一个窗口到前台。相反,SetForeground函数将会激活窗口并且调用FlashWindowEx函数通知用户。
  Windows CE:拥有窗口的线程不具有优先启动权。


  速查:Windows NT;3.1以上版本;Windows;95以上版本;Windows CE:1.0以上版本;头文件:winuser.h;库文件:user32.lib。


SetWindowPlacement  函数功能:该函数设置指定窗口的显示状态和恢复,最大化,最小化位置。
  函及原型;BOOL SetWindowPlacement(HWND hWnd,CONST WINDOWPLACEMENT★lpwndpl);
  参数:
  hWnd:窗口句柄。
  lpwndpl:指向一个WINDOWPLACEMWNT结构的指针,该结构给出了新的显示状态和窗口位置。
  在调用函数SetWindowPlacement之前,将WINDOWPLACEMWNT结构的长度单元置为sizeof(WINDOWPLACEMENT)。如果lpwndpl->length设置不正确,函数SetWindowPlacement将失败。
  返回值:如果函数成功,返回值为非零。如果函数失败,返回值为零。若想获得更多错误信息,请调用callGetLastErro函数。
  备注:如果在WIDNOWPLACEMENT中指定的信息使窗口完全显示在屏幕之外,系统自动调整坐标以使窗口可见,兼顾屏幕设置和多种监视器配置。
  WINDOWPLACEMENT的长度成员信息设置为sizeof(WINDOWPLACEMENT),如果设置不正确,函数将返回FLASE。查看窗口位置坐标的信息,参看WINDOWPLACEMENT。


  速查:Windows NT:3.1以上版本;Windows;95以上版本;Windows CE:不支持;头文件;winuser.h;库文件:user32.lib。


SetForegroundWindow()

SetActiveWindow()

SetFocus()

自己的理解:每个gui线程都有自己的活动窗口,而目前被用户点中那个线程活动窗口叫前台窗口(或叫前景窗口)。而创建前台窗口的线程叫做前台线程(或叫前景线程),前台线程拥有比其它非前景线程更高的优先级,会被windows操作系统优先处理。而所谓的焦点窗口,可以是前台窗口或者是前台窗口的子窗口(控件),如果用户按下键盘按键,windows操作系统会将键盘按键消息发送到当前的焦点窗口。


-------------------------------------

如何将一个某个窗口提到最顶层?网上搜索了一些文章大致有以下几种方法,做个备忘.

问题:有个界面,想定期让其提前(**并显示在用户面前),但又不想用TOPMOST那种置顶方法.我用了SetForegroundWindow,SetActiveWindow,SHOW_WINDOW都不行:程序运行后再打开记事本,时间到我的程序只会在任务栏上闪几下,界面根本出不来怎么办!!(不用顶极窗口,不用鼠标模拟点击)

方法一:
使用定时器,然后在定时器响应函数中定时调用,SetWindowPos()函数,第一个参数写HWND_TOPMOST

方法二:
因为2000/XP改变了SetForegroundWindow的执行方式,不允许随便把窗口提前,打扰用户的工作。可以用附加本线程到最前面窗口的线程,从而欺骗windows。

AttachThreadInput(GetWindowThreadProcessId(::GetForegroundWindow(),NULL), GetCurrentThreadId(),TRUE);
SetForegroundWindow();
SetFocus();
AttachThreadInput(GetWindowThreadProcessId(::GetForegroundWindow(),NULL), GetCurrentThreadId(),FALSE);


方法三:

如何激活指定的窗口事件    ●   
           我们知道,Windows    9x/2000中SetForegroundWindow函数当用户正在操作其他窗口时是不能强制某个窗口为前景窗口的,而是激活窗口并调用FlashWindowEx函数来通知用户。但是很多实际情况要求将激活窗口的同时将创建这个窗口的线程置为前景状态。碰到这种情况我们可以使用USER32.DLL中的几个未公开API函数。   
   void    SwitchToThisWindow    (   
   HWND    hWnd,        //    被激活的窗口句柄   
   BOOL    bRestore    //    如果被极小化,则恢复窗口   
   );   
   必须动态加载这个函数。   
   typedef    void    (WINAPI    *PROCSWITCHTOTHISWINDOW)    (HWND,    BOOL);   
   PROCSWITCHTOTHISWINDOW    SwitchToThisWindow;   
   HMODULE    hUser32    =    GetModuleHandle("user32");   
   SwitchToThisWindow    =    (    PROCSWITCHTOTHISWINDOW)   
   GetProcAddress(hUser32,    "SwitchToThisWindow");       
   接下来只要用任何现存窗口的句柄调用这个函数即可,第二个参数指定如果窗口极小化,是否恢复其原状态。   
   SwitchToThisWindow(hWnd,    TRUE);  

 

 

 

DEMO:

HANDLE hMutex=::CreateMutex( NULL,FALSE,"ImpImg");
  if ( ::GetLastError()==ERROR_ALREADY_EXISTS ) 
  {
  HWND FindWnd = ::FindWindow(NULL,"ImpImg");
  if ( FindWnd )
  { ::SetWindowPos( FindWnd,HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE ); 
  ::ShowWindow( FindWnd,SW_SHOW ); ::SetFocus( FindWnd ); }
  return FALSE;
  }

函数原型:  BOOL SetWindowPos(const CWnd* pWndInsertAfter, int x, int y,int cx, int cy, UINT nFlags);

函数功能

  该函数改变一个子窗口,弹出式窗口或顶层窗口的尺寸,位置和Z序。

  子窗口,弹出式窗口,及顶层窗口根据它们在屏幕上出现的顺序排序、顶层窗口设置的级别最高,并且被设置为Z序的第一个窗口。

C++程序互斥方法

C++程序互斥方法
  • u011261430
  • u011261430
  • 2016年10月12日 14:16
  • 614

FreeRTOS学习笔记——互斥型信号量

在嵌入式操作系统中互斥型信号量是任务间资源保护的重要手段。
  • xukai871105
  • xukai871105
  • 2015年02月27日 08:50
  • 10052

Win32多线程之互斥器(Mutexes)

http://blog.csdn.net/wjj715211/article/details/16899667 Win32的Mutex用途和critical section非常类似,但是它牺牲速度以...
  • l799623787
  • l799623787
  • 2014年01月14日 11:51
  • 2146

1线程同步:互斥量,死锁

1线程为什么要同步 A:共享资源,多个线程都可对共享资源操作。 B:线程操作共享资源的先后顺序不确定。 C:处理器对存储器的操作一般不是原子操作。 2互斥量 mutex操作原语 pthre...
  • toto1297488504
  • toto1297488504
  • 2014年09月25日 16:44
  • 1744

linux多线程下互斥量与信号量的区别

互斥量(Mutex)   互斥量表现互斥现象的数据结构,也被当作二元信号灯。一个互斥基本上是一个多任务敏感的二元信号,它能用作同步多任务的行为,它常用作保护从中断来的临界段代码并且在共享同...
  • ycc541
  • ycc541
  • 2015年05月08日 16:23
  • 1830

C++多线程-第二篇-Mutex(互斥量)

//Boost #include #define BOOST_THREAD_VERSION 4 //使用最新版本,含有1,2,3但只是为了兼容之前程序。 Thread库丰富强大的扩展功能但不在Thre...
  • hffhjh111
  • hffhjh111
  • 2016年11月12日 16:10
  • 6017

信号量和互斥量(锁)的区别

信号量:那是多线程同步用的,一个线程完成了某一个动作就通过信号告诉别的线程,别的线程再进行某些动作。 互斥量:这是多线程互斥用的,比如说,一个线程占用了某一个资源,那么别的线程就无法访问,知道这个线...
  • fuqiaoyimeng
  • fuqiaoyimeng
  • 2014年08月01日 15:24
  • 4614

详解UCOS中的互斥信号量

二值信号量主要用于进行共享资源的独占式访问,比如我们用一个变量来标志一个资源是否可用,当这个变量为1的时候表示资源可用,当这个资源为0的时候表示资源不可用,但是二值信号量容易产生优先级反转,影响系统的...
  • Creator_csu
  • Creator_csu
  • 2014年04月23日 09:09
  • 3011

C++11多线程编程之互斥量

C++11多线程编程之互斥量
  • u012333003
  • u012333003
  • 2014年05月07日 15:55
  • 1122

Windows互斥量内核对象

互斥量内核对象用来确保一个线程独占一个资源的访问。 互斥量对象包含了一个使用计数、线程ID以及一个递归计数。互斥量与关键段的行为完全相同,但是互斥量是内核对象,而关键段是用户模式下的同步对象,因此互...
  • luojian5900339
  • luojian5900339
  • 2015年05月28日 16:55
  • 460
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:互斥量的使用,是应用程序只运行一次
举报原因:
原因补充:

(最多只允许输入30个字)