白话windows内核对象共享之命名对象

来源:互联网 发布:知乎封号 编辑:程序博客网 时间:2024/05/16 06:50

引子:话说三国时期蜀国猛将张飞在汉中时于宕渠与魏国猛将张郃大战,酣战十个回合,张飞佯败退走,躲在隐蔽处。其目的是等待增援部队的到来。张飞等啊等,终于看到前方有一支军队,但是他立马傻眼了,前方军队没有旗号,不知是敌是友。于是张飞开始骂娘了,狗日的尼玛军队连旗子也没有。我们假设一下情景:如果张飞没有看到增援部队他是不会轻举妄动的;如果看到增援部队,而且是打的是他的旗号,他会立马毫不迟疑的杀回去;如果看到前方有军队,但是打的不是他的旗号,他会按兵不动,继续等待增援部队。。。今天要讲的命名内核对象共享,也是这个道理,只有遇到旗号一致的军队时才会有所行动,否则一直按兵不动。

下面给出代码,以互斥量的名字作为旗号。关于互斥量可以参考前面的博客:白话windows多线程同步之互斥变量

第一个进程:

#include "stdafx.h"#include <Windows.h>#include <process.h>#include <time.h>HANDLE g_hMutext = NULL ;DWORD WINAPI Fun(LPVOID lp){WaitForSingleObject(g_hMutext, INFINITE) ;printf("%d doing something now in Process Id %d\n", GetCurrentThreadId(), GetCurrentProcessId()) ;Sleep(1000 * 20) ;printf("%d has Finished in Process Id %d\n", GetCurrentThreadId(), GetCurrentProcessId()) ;time_t ct ;tm *ctm ;time(&ct) ;ctm = localtime(&ct) ;printf("The Current time is %02d:%02d:%02d\n", ctm->tm_hour, ctm->tm_min, ctm->tm_sec) ;ReleaseMutex(g_hMutext) ;return 0 ;}int _tmain(int argc, _TCHAR* argv[]){g_hMutext = CreateMutex(NULL, FALSE, _T("ShonmMutext")) ;CreateThread(NULL, 0, Fun, NULL, 0, NULL) ;while(TRUE){}return 0;}
第二个进程:

#include "stdafx.h"#include <Windows.h>#include <process.h>#include <time.h>HANDLE g_hMutext = NULL ;DWORD WINAPI Fun(LPVOID lp){WaitForSingleObject(g_hMutext, INFINITE) ;printf("Because a thread in another process has finished, I have chance to process now\n") ;time_t ct ;tm *ctm ;time(&ct) ;ctm = localtime(&ct) ;printf("The Current time is %02d:%02d:%02d\n", ctm->tm_hour, ctm->tm_min, ctm->tm_sec) ;printf("%d doing something now in Process Id %d\n", GetCurrentThreadId(), GetCurrentProcessId()) ;Sleep(1000 * 20) ;printf("%d has Finished in Process Id %d\n", GetCurrentThreadId(), GetCurrentProcessId()) ;ReleaseMutex(g_hMutext) ;return 0 ;}int _tmain(int argc, _TCHAR* argv[]){g_hMutext = CreateMutex(NULL, FALSE, _T("ShonmMutext")) ;CreateThread(NULL, 0, Fun, NULL, 0, NULL) ;while(TRUE){}return 0;}
请看运行效果:

我们看到当5852进程中的线程7716结束后(时间是11:06:29),进程7252中的线程5736同时开始获得该互斥量,说明该互斥量成功的被两个进程共享。使用的方式也很简单,就是给创建的内核对象命一个相同的名字,这样就相当于是一家人了,援兵已到,立马行动,哈哈。

哪些对象可以被命名?

创建内核对象函数有一个名字参数的都可以。以下函数都可以:

HANDLE CreateMutex(   PSLCURITY_ATTRIBUTES psa,   BOOL bInitialOwner,   PCTSTR pszName);HANDLE CreateEvent(   PSECURITY_ATTRIBUTES psa,   BOOL bManualReset,   BOOL bInitialState,   PCTSTR pszName);HANDLE CreateSemaphore(   PSECURITY_ATTRIBUTES psa,   LONG lInitialCount,   LONG lMaximumCount,   PCTSTR pszNarne);HANDLE CreateWaitableTimer(   PSLCURITY_ATTRIBUTES psa,   BOOL bManualReset,   PCTSTR pszName);HANDLE CreateFileMapping(   HANDLE hFile,   PSECURITY_ATTRIBUTES psa,   DWORD flProtect,   DWORD dwMaximumSizeHigh,   DWORD dwMaximumSizeLow,   PCTSTR pszName);HANDLE CreateJobObject(   PSECURITY_ATTRIBUTES psa,   PCTSTR pszName);

现在我们探讨以下,为什么可以这样做?一个进程中的对象是如何被另一个进程认识?那是因为内核对象由内核即操作系统拥有,而不是进程拥有。进程只是拥有一个句柄表,当进程调用创建内核的函数时,操作系统会将刚才产生的内核对象的索引添加到进程的句柄表中。如果创建时的内核对象是命名的,那么当第二次创建该命名的内核对象时(不管是在该进程中,还是在其他进程中),只是打开已被创建的内核对象,由于内核对象都是系统级别的,当然可以被进程共享。

0 0