首页 > 代码库 > 跨进程边界共享内核对象
跨进程边界共享内核对象
正在拜读《windows核心编程》,稍后总结。---------XiaoF
先说说为何要实现此功能
1,利用文件映射对象,可以在同一电脑的不同进程之间共享数据块。
2,借助邮件槽和命名管道,在网络中的不同计算机上运行的进程相互发送消息。
3,互斥量。信号量。事件,允许不同进程中的线程做同步。
如何实现,方法3种:使用对象句柄继承(父子进程);为对象命名;复制对象句柄。
使用对象句柄继承
只有在父子进程关系,才可以用对象句柄继承方法。
步骤如下:
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);
注解:SECURITY_ATTRIBUTES 结构的成员变量,nLength结构体大小;lpSecurityDescriptor 为安全访问描述符,如果想对
创建的对象记忆访问限制,修改此值;bInheritHandle 此变量如果是true 则是可以继承。
2,创建子进程
BOOL CreateProcess(PCTSTR pszApplicationName,PTSTR pszCommandLine,·······, Bool bInheritHandles, ······);
注意bInherithandles ,再生成一个进程时:此值决定子进程是否可以继承父进程句柄表中的“可继承句柄”;
如果bInheritHandles为True,系统会做三件事:1,创建子进程并创建一个新的进程句柄表;2:,遍历父进程句柄表,凡是标志是
可继承的句柄,就复制到子进程的句柄表中(位置也一样,完全一致);3, 系统还会递增内核对象的使用计数。
注:对象句柄的继承只会发生在子进程生成时,假如父进程又创建了一个内核对象,并同样将他的句柄设为可继承的句柄。正在运行的
子进程不会继承这个内核对象的。
子进程是不会知道自己继承的内核对象的句柄的。在子进程文档中英指出他从另一个进程生成时,希望还获得内核队形句柄。
3,为了使子进程得到想要的内核对象句柄,最常用的方法是:句柄值作为命令行参数传给子进程;进程通迅技术(WaitForInputIdle函数);父进程想起环境快中添加环境变量;
整理一下思路,稍后继续 ------XiaoF
对象命名
许多内核对象都可以进行命名。
1,在一个进程A中创建一个内核对象:
例如:上面所用例子:
HANDLE CreateMutex(
PECURITY_ATTRIBUTES psa,
BOOL bInitialOwner,
PCTSTR pszname);
最后一个参数pszName,向此参数传入NULL,相当于让系统创建一个未命名的内核对象,可以利用继承技术来实现共享内核对象;如
果想使用对象命名来实现,必须为此函数赋值。
paName赋值是“以0为终止符的名称字符串”的地址。这个名称可以长达MAX_PATH个字节。
例如创建一个互斥对象:
HANDLE hMutex = CreateMutex(NULL,FALSE,TEXT("XiaoF_Object");
注意:Microsoft没有提供任何机制来保证内核对象名称的唯一性(解决名称唯一的方法:专有命名空间)
,所以如果在名义一个XiaoF_Object的对象将会失败
注解:例如在创建一个信号对象:
HANDLE hSem = CreateSemaphore(NULL,1,1,TEXT("XiaoF_Object");
DWORD dwErrorCode = GetLastError();
结果dwErrorCode 的值为6(ERROR_INVALID_HANDLE),句柄错误。
2,在另一个进程中创建一个进程B:
在进程B中创建一个名称为XiaoF_Object的对象。
系统会查看是否存在XiaoF_Object的对象,如果存在,接着检查对象的类型,如果类型一致,接着执行一次安全检查,验证调用者是否对该对象拥有完全访问权限。如果是,系统就会在进程B的句柄表中找到空白项,初始化为指向现有的内核对象。如果对象的类型不匹配或者调用被拒绝,就会失败(返回NULL);
调用Create*创建对象函数成功后,未创建对象,其实是process B分配了一个新的Handle,他表示了内核中现有的对象。
内核对象的计数+1;
还可以使用Open* 函数
参数和Create* 一样。如果没有找到同名的内核对象,函数返回NULL,GetLastError返回2(ERROR_FILE_NOT_FOUND); 如果找到同名的对象,但是类型不同,函数返回NULL,GetLastError返回6,(ERROR_INVALID_HANDLE);如果同名同类型,系统会检查请求的访问(通过dwDesiredAccess制定)是否允许。如果均通过,系统跟新调用进程的句柄表,并内核对象计数+1;
Create* 和Open* 的区别:如果内核对象不存在,Create*会创建内核对象,而Open* 只会返回失败。