作者:[email protected] 新浪微博@孙雨润 新浪博客 CSDN博客日期:2012年11月3日
内核对象是一个内存中的数据结构,只能由OS内核分配访问。访问内核对象的API会返回进程相关的Handle,无法直接跨进程共享。内核对象使用Count Reference,Life Cycle可能长于创建它的进程。
【Note】使用Sysinternals的WinObj可以查看所有内核对象类型的列表。
创建内核对象的API都有SECURITY_ATTRIBUTES
做参数,如果不需要加访问限制则传NULL。如果想访问现有内核对象,需要指定即将执行的操作:
HANDLE hFileMap = OpenFileMapping(FILE_MAP_READ, FALSE, _T("TestFileMap"));
如果访问被拒绝会返回NULL。
进程初始化时系统为其分配一个Handle table,仅供内核对象使用而非用户对象或GDI对象。
下面是一些用于常见内核对象的API:
HANDLE CreateThread(...);
HANDLE CreateFile(...);
HANDLE CreateFileMapping(...);
HANDLE CreateSemaphore(...);
【Note】CreateFile返回值与INVALID_HANDLE_VALUE比较,其余与NULL比较。
CloseHandle(HANDLE hObject);
下面情况需要共享内核对象:
只有Process之间有父子关系时使用这种方式,使子进程能访问父进程的内核对象。
使用上边提到的SECURITY_ATTRIBUTES
:
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
HANDLE hMutex = CreateMutex(&sa, FALSE, NULL);
调用CreateProcess
创建子进程,bInheritHandles传TRUE
父进程想控制哪些子进程能继承内核对象Handle:
BOOL SetHandleInformation(HANDLE hObject, DWORD dwMask, DWORD dwFlags);
SetHandleInformation(hObj, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); // Open
SetHandleInformation(hObj, HANDLE_FLAG_INHERIT, 0); // Close
SetHandleInformation(hObj, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE); // 禁止close句柄
许多内核对象创建时可以使用pszName
命名,pszName
为NULL
时为匿名对象。【Note】Create*函数不知道刚刚是新建了一个内核对象,还是打开了一个现有的同名内核对象,因此最好使用Open*函数测试。
进程S能访问一个内核对象,希望T也能访问也能访问:
HANDLE hObjInProcessS = CreateMutex(NULL, FALSE, NULL);
HANDLE hProcessT = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessIdT);
HANDLE hObjInProcessT;
DuplicateHandle(GetCurrentProcess(), hObjInProcessS, hProcessT, &hObjInProcessT, 0, FALSE, DUPLICATE_SAME_ACCESS);
CloseHandle(hProcessT);