现在的位置: 首页 > 综合 > 正文

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

2018年02月24日 ⁄ 综合 ⁄ 共 2648字 ⁄ 字号 评论关闭

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

下面给出代码,以互斥量的名字作为旗号。关于互斥量可以参考前面的博客:白话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);

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


抱歉!评论已关闭.