进程间共享内核对象
内核对象的句柄是可以被继承的但内核对象本身是不能被继承的。
每个句柄都有一个标志位指出该句柄是否可以被继承。如果创建内核对象时传递的LPSECURITY_ATTRIBUTES参数位NULL则,返回的句柄是不可继承的(标志位为0)把binheritHandle设为TURE就使得标志位为1。
- 句柄的继承:
(1)A:当父进程创建内核对象时,通知OS该对象的句柄能够被继承。父进程须分配和初始化一个SECURITY_ATTRIBUTES结构,并把该结构的地址传递给特定的Create*函数。
B:父进程使用Create Process函数派生出子进程(binherit Handles参数位TRUE时子进程将继承父进程的可继承句柄,否则为FALSE则不可继承)。
1将父进程的可继承句柄精确拷贝到子进程的句柄表中(这样使得表示一个内和对象的句柄值在父子进程中是一致的)。
2内核对象的使用计数增加1,(父进程可立刻关闭该对象的句柄而步影响子进程操作对象的能力,子进程也不一定先终结。子父进程须分别调用Close Handle函数关闭进程)
对象句柄的继承只发生在派生的那一刻,之后父进程再创建带可继承句柄的内核对象,这些句柄是不能被已经运行着的子进程所继承的。
(2)改变句柄标志
父进程可以通过改变内核对象句柄继承标志来控制将一个带可继承的句柄的内核对象,让那个派生对象来继承内核对象的句柄。
BOOL Set Handle Information(HANDLE hobject,DWORD dwMask,DWORD dwFlages)
Hobject 标识一个有效的句柄 dwMask要改变哪个或哪些标志 dwFlages 将标志位设成的值
- 命名内核对象:
(1)Process A进程在创建内和对象时将内和对象命名,再用Create*创建一个新的Process B进程时指定与先前创建的内核对象同名的内核对象时:
A:系统首先要查看是否已经存在指定名字的内核对象。
B:若确实存在一个带有该名字的对象,则内核要检查对象的类型,系统会执行一次安全检查,以确定调用者是否拥有对该对象的完整的访问权。
C:如果拥有这种访问权,系统就在Process B的句柄表中找出一个空项目,并对该项目进行初始化,使该项目指向现有的内核对象。对象的使用计数被递增,如果为bInheritHandle参数传递TURE,那么返回的句柄将是可继承的。
D:如果该对象类型不匹配,或者调用者被拒绝访问,Create*将运行失败(返回NULL)这两个进程中的句柄值很可能是不同的值。
(2)按名字共享对象的另一种方法是,进程不调用Create*函数,而是调用Open*函数。调用Create*函数与调用Open*函数之间的主要差别是:如果对象并不存在那么Create*函数将创建该对象,而Open*函数则运行失败。
(3) 为了保证对象的唯一性,建议创建一个GUID,并将GUID的字符串表达式用作对象名。命名对象常常用来防止运行一个应用程序的多个实例。
(4) 终端服务器拥有内核对象的多个名字空间。如果存在一个可供内核对象使用的全局名字空间,就意味着它可以供所有的客户程序会话访问。该名字空间主要供服务程序使用。每个客户程序会话都有它自己的名字空间。它能防止运行相同应用程序的两个或多个会话之间出现互相干扰的情况,也就是说一个会话无法访问另一个会话的对象,尽管该对象拥有相同的名字。
服务程序的名字空间对象总是放在全局名字空间中。默认在终端服务器中,应用程序的命名内核对象将放入会话的名字空间中。可以用“ Global /”或“Local”置于对象名的前面,使命名对象进入全局名字空间或会话的名字空间。
HANDLE h = Create Event(NULL, FALSE, FALSE, “Global//MyName”):
- 复制对象句柄
可以通过DuplicateHandle函数来复制内核对象的句柄来实现进程间共享内核对象。
BOOL DuplicateHandle(HANDLE hSourseProsessHandle,
HANDLE hSoureseHandle, HANDLE hTargetProcessHandle,
PHANDLE phTargetHandle, DWORD dwDesiredAccess,
BOOL bInheritHandle, DWORD dwOptions);
hSourseProsessHandle源进程的内核对象句柄,hTargetProcessHandle目标进程的内核对象句柄。
hSoureseHandle 源内和对象的句柄,phTargetHandle目标内核对象的句柄(是HANDLE变量的地址,它将接收获取源进程句柄信息拷贝的项目索引。返回的句柄值与hTargetProcessHandle标识的进程相关)
dwOptions参数可以是0(零),也可以是下面两个标志的任何组合:DUPLICATE_SAME_ACCESS和DUPLICATE_CLOSE_SOURCE
A:如果设定了DUPLICATE_SAME_ACCESS目标进程的句柄拥有与源进程句柄相同的访问屏蔽。使用该标志将使函数忽略它的dwDesiredAccess参数。
B:如果设定了DUPLICATE_CLOSE_SOURCE标志,则可以关闭源进程中的句柄。该标志使得一个进程能够很容易地将内核对象传递给另一个进程。当使用该标志时,内核对象的使用计数不会受到影响。