首页 > 代码库 > 跨进程边界共享内核对象

跨进程边界共享内核对象

正在拜读《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* 只会返回失败。