一、摘要
1.内核对象有使用计数,当计数减为0时,内核对象被销毁。
2.内核对象有安全描述符,控制该进程能做的操作。
3.每个进程内有内核对象句柄表,记录使用中的内核对象。
二、内核对象
1.对内核对象的操作,只能通过调API
应用程序无法在内存中找到表示内核对象的数据结构,也就无法直接修改其状态。
要对内核对象操作,只能先获得其句柄,然后调用window定义好的API
2.内核对象的使用计数,记录在使用它的进程数
内核对象是属于内核的,而不属于任何一个进程,包括创建它的哪个进程。
内核对象中有一个使用计数的数据,记录在使用它的进程数。
只有当使用计数为零时,该内核对象才会被销毁。
即使创建它的进程终止了,该内核对象的使用计数不为零就不会被销毁。
3.内核对象的安全描述符,控制进程对其的使用权
在创建内核对象的API中,都有一个“安全描述符”的参数,是用来控制对这个内核对象的使用权的
例如创建文件内存映射CreateFileMapping就有一个PSECURITY_ATTRIBUTES的参数。而在获取该内核对象的API OpenFileMapping中,会有一个表征获取该对象做什么操作的参数。
如果该用户允许对该内核对象做该操作,则成功返回该内核对象句柄,否则返回NULL分辨一个对象是否为内核对象的标志是,创建该对象的API是否有“安全描述符”这个参数。
如创建GDI就没有该参数,所以GDI不是内核对象
4.进程的内核对象句柄表,记录使用的内核对象
内核对象句柄表结构:
索引 (Handle) | 内核对象内存块的指针 | 访问屏蔽(标志位的DWORD) | 继承标志(标志位的DWORD ) |
---|---|---|---|
1 | 0 x ? ? ? ? ? ? ? ? | 0 x ? ? ? ? ? ? ? ? | 0 x ? ? ? ? ? ? ? ? |
2 | 0 x ? ? ? ? ? ? ? ? | 0 x ? ? ? ? ? ? ? ? | 0 x ? ? ? ? ? ? ? ? |
… | … | … | … |
每个进程内都有一个内核对象句柄表来记录它在使用的内核对象,表中包含该内核对象内存块的指针。
在内核对象的句柄就是该内核对象在此表中的索引值。创建内核对象时,会在表中寻找空白项,并添加新项,并通过该内核对象指针对它的使用计数置1.
用CloseHandle释放进程对该内核对象使用权时,就通过该指针对使用计数减1
即使没有用CloseHandle,当进程终止时,会对句柄表中没有释放使用权的内核对象计数减1
5.进程间访问内核对象
设置子进程继承父进程的内核对象
创建有名字的内核对象,并通过内核对象名字访问它。
DuplicateHandle 复制内核对象
6.当用Create*(如CreateMutex)创建有名字的内核对象
如果同名字、同类的内核对象已存在,则返回该内核对象的Handle;
如果同名字、不同类的内核对象已存在,则创建失败,并返回NULL
如果没有同名字的内核对象存在,则创建新内核对象