Windows的内核对象大致有以下几种:
1.访问令牌(access token)对象
2.事件对象
3.文件对象
4.文件映射对象
5.I/O端口对象
6.作业对象
7.邮件槽(mailslot)对象
8.互斥量(mutex)对象
9.管道(pipe)对象
10.进程对象
11.信号量(semaphore)对象
12.线程对象
13.可等待的计时器对象
14.线程池工厂(thread pool worker factory)对象
每个内核对象都只是一个内存块,它由操作系统内核分配,并只能有操作系统内核访问。
每个内核对象都包含一个使用计数(usage count)。初次创建一个对象的时候,其使用计数为1。另一个进程获得对现有对象的访问后,使用计数会递增。进程终止运行后,操作系统内核将自动递减此进程仍然打开的所有内核对象的使用计数。如果内核对象的使用计数为0时,操作系统内核对象会自动销毁该对象。
内核对象可以用一个安全操作符(security descriptor, SD)来保护。安全描述符描述了谁(通常是对象的创建者)拥有对象;哪些用户被容许访问或使用该对象;哪些组和用户被拒绝访问该对象。安全描述符通常在编写服务器应用程序的时候使用。
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpsa, // 安全描述,通常设为NULL
DWORD cbStack,
LPTHREAD_START_ROUTINE lpStartAddr,
LPVOID lpvThreadParam,
DWORD fdwCreate,
LPDWORD lpIDThread
);
安全描述通常设为NULL,表明使用默认的安全性
判断一个对象是否是一个内核对象还是一个用户对象或GDI对象,主要看创建这个对象的函数。有安全描述的就是内核对象,反之就不是。
如:
HBITMAP CreateBitmap(
int nWidth, // bitmap width, in pixels
int nHeight, // bitmap height, in pixels
UINT cPlanes, // number of color planes
UINT cBitsPerPel, // number of bits to identify color
CONST VOID *lpvBits // color data array
);
创建内核对象一定要检查它的返回值
通常它的返回值会是NULL或者INVALID_HANDLE_VALUE ,要主要查看MSDN进行区别
使用完内核对象时要注意关闭该内核对象
BOOL CloseHandle(
HANDLE hObject
);
一旦调用了CloseHandle,我们的进程就不能再访问该内核对象;但是,如果该对象的使用计数还没有递减为0,它就不会被销毁。这说明还有其他的进程在使用该内核对象。
当忘记调用CloseHandle,会发生对象泄露情况吗?
不一定,在应用程序运行时,它可能会泄露内核对象;当进程终止运行,系统会保证一切都会被正常清除。
当进程终止时,对于内核对象,操作会做以下操作:
进程终止时,系统自动扫描该进程的句柄表。如果这个表中有任何有效的标记项(即进程终止前没有关闭的对象),操作系统会为我们关闭这些对象句柄。只要这些对象中有一个使用计数递减到0,内核就会销毁对象。
不光如此,这适合于所有的内核对象、资源(包括GDI对象在内)以及内存块。进程终止运行时,系统会保证我们的进程不会留下任何东西。