跨进程边界共享内核对象

在很多时候,不同进程中运行的线程需要共享内核对象,比如一些同步操作。

三种不同机制来允许进程共享内核对象:

① 使用对象句柄继承;

② 为对象命名;

③ 复制对象句柄。

(1) 使用对象句柄继承

只有进程之间存在父子关系的时候才可以使用对象句柄继承。首先要创建一个可继承的句柄,父进程必须分配并初始化一个SECURITY_ATTRIBUTES结构,并将该结构的地址传给具体的Create函数。以下代码创建了一个互斥量对象,并返回其可继承的句柄:

SECURITY_ATTRIBUTES sa;

sa.nLength sizeof(sa);

sa.lpSecurityDescriptor NULL;

sa.bInheritHandle TRUE;   //make the returned handle inheritable

 

HANDLE hMutex CreateMutex(&sa,FALSE,NULL);

接下来谈谈进程的句柄表记录项中保存的标志。句柄表中的每个记录项都有一个指明句柄是否可以继承的标志位。如果在创建内核对象时,将NULL作为PSECURITY_ATTRIBUTES参数传入,则返回的句柄是不可继承的,这个标志位为0.将bInheritHandle成员设为TRUE。则这个标志位为1。

 

               包含两个有效记录项的进程句柄表

索引

指向对象内存块的指针

访问掩码(包含标志位的一个DWORD)

标志

1

0xF0000000

0x???

0x00000000

2

0x00000000

(不可用)

(不可用)

3

0xF0000010

0x???

0x00000001

为了使用对象句柄继承,下一步是由父进程生成子进程。这是通过CreateProcess函数来完成的。

主要注意bInheritHandles参数。通常情况下,在生成一个进程时,我们要将该参数设为FALSE,这个值向系统表明,我们不希望子进程继承父进程句柄表中的“可继承句柄”;相反,传入TRUE时,将继承所有可继承句柄;传入TRUE时,操作系统创建了子进程,但不允许子进程立即运行,系统会为子进程创建一张新的、空白的进程句柄表,将父进程可继承句柄全部复制到子进程的句柄表中,

注意它们在父进程和子进程中的位置是一样的,这意味着,在父进程和子进程中,标识内核对象的句柄值是一致的。同时,系统还会递增内核对象的使用计数,为了销毁内核对象,父进程和子进程要么都调用CloseHandle(),要么都终止运行。

(2) 为对象命名

可以对内核对象命名,这种方式的一个优势是进程间不一定存在父子关系。

 

 

 

 

(3) 复制对象句柄

BOOL WINAPI DuplicateHandle(   

HANDLE hSourceProcessHandle,

HANDLE hSourceHandle,   

HANDLE hTargetProcessHandle,        

LPHANDLE lpTargetHandle,        

DWORD dwDesiredAccess,          

BOOL bInheritHandle    

DWORD dwOptions );

简单的说,这个函数获得一个进程的句柄表中的一个记录项,然后在另一个进程的句柄表中创建该记录项的一个副本。

要注意的是,hSourceHandle是相对于hSourceProcessHandle的,lpTargetHandle是相对于hTargetProcessHandle的。

 

dwOptions 参数可以是0或者以下两个标志的任意组合:DUPLICATE_SAME_ACCESS和DUPLICATE_CLOSE_SOURCE;

如果指定DUPLICATE_SAME_ACCESS,将向DuplicateHandle函数表明我们希望目标句柄拥有与源进程的句柄一样的访问掩码。使用这个标志后,DuplicateHandle函数会忽略它的dwDesiredAccess参数;

如果指定DUPLICATE_CLOSE_SOURCE标志,将会关闭源进程中的句柄。利用这个标志,一个进程可以轻松地将一个内核对象传给另一个进程。如果使用了这个标志,内核对象的使用计数不会受到影响。

应避免在源进程中关闭复制后的目标句柄,因为目标句柄是相对于目标进程来说的。

跨进程边界共享内核对象

跨进程边界共享内核对象

跨进程边界共享内核对象

跨进程边界共享内核对象

使用DuplicateHandle函数(来复制内核对象句柄)所遇到的问题和继承(内核对象句柄)时同样:目标进程不知道它现在能访问一个新的内核对象。所以进程C必须以某种方式来通知进程T,告诉它可以访问一个内核对象。显然,使用命令行参数或者更改进程T的环境变量是行不通的,因为进程已经启动运行了。我们必须使用窗口消息或者其它进程间通信(IPC)机制。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值