《Windows核心编程》内核对象

内核对象是操作系统用于管理资源的关键数据结构,包括事件、线程、文件等。应用程序通过Windows API创建并操作内核对象,使用句柄进行访问。内核对象的生命周期与使用计数相关,当计数为0时会被销毁。安全性通过安全描述符保障,可使用对象句柄继承、命名或复制来跨进程共享。关闭对象句柄不会立即销毁对象,仅减少使用计数。
摘要由CSDN通过智能技术生成

一、何为内核对象

  1. 内核对象是用于管理进程线程文件等诸多种类大量资源的数据结构
  2. 常见的内核对象有:事件对象、文件对象、互斥量对象、进程对象、线程对象、线程池工厂对象、管道对象、信号量对象等。
  3. 每个内核对象都只是一个内存块(这个内存块是一个数据结构,其成员维护着与对象相关的信息),它由操作系统内核分配,并只能由操作系统内核访问

二、应用程序如何操作内核对象

  1. 内核对象的数据结构只能由操作系统内核访问,应用程序不能在内存中定位这些数据结构并直接更改其内容。
  2. 只有通过调用Windows API创建内核对象,再通过函数返回的HANDLE(句柄)来间接操作内核对象。

三、内核对象的生命周期

  1. 虽然内核对象与进程相关,但内核对象的所有者是操作系统内核,而非进程,所以进程结束,内核对象不一定被销毁。假如其他进程正在使用本进程创建的内核对象,本进程终止运行,内核对象在其他进程终止运行之前,它不会被销毁。
  2. 系统内核根据内核对象的使用计数来判断是否销毁内核对象。所有内核对象都包含一个数据成员:使用计算。内核对象被创建时,其使用计数被设为1,另一个进程获得该内核对象的访问后,使用计数+1,进程终止运行后,使用计数-1。一旦使用计数变成0,操作系统内核就会销毁该内核对象

四、内核对象的安全性

  1. 内核对象可以用一个安全描述符(SECURITY_ATTRIBUTES)来保护。
  2. 安全描述符描述了谁拥有对象。
  3. 如果想对创建的内核对象加以访问限制,就必须创建一个安全描述符(SECURITY_ATTRIBUTES结构体),然后初始化结构体

五、用户对象/GDI对象

  1. 用户对象:用户创建的对象,用户具有使用权。
  2. GDI对象:即图形对象,用户具有使用权。

六、进程内核对象句柄表

  1. 一个进程在初始化时,系统将为它分配一个句柄表(为空),句柄表仅供内核对象使用,不适用于用户对象或GDI对象。
  2. 用于创建内核对象的任何函数都会返回一个与进程相关的句柄,这个句柄可由同一个进程中运行的所有线程使用
  3. 系统用索引来表示内核对象的信息保存在进程句柄表中的具体位置。

七、关闭内核对象

  1. 调用CloseHandle向系统表明结束使用内核对象。
  2. 关闭内核对象不代表会销毁内核对象,只会让使用计数-1。
  3. 调用CloseHandle后,还应同时将保存内核对象的变量设为NULL,否则可能会出现意外错误。
HANDLE	m_hThread;	
BOOL CloseHandle(m_hThread);
m_hThread = NULL;

八、跨进程边界共享内核对象

允许进程共享内核对象的方法:①使用对象句柄继承;②为对象命名;③复制对象句柄。

1. 使用对象句柄继承
①使用条件:要求进程之间有父-子关系
②使用方法:步骤如下
A.设置对象句柄可继承。父进程创建一个内核对象时,父进程必须向系统指出该对象的句柄是可以继承的。
B.通过CreatepProcess函数,让父进程生成子进程

//A.设置对象句柄可继承
SECURITY_ATTRIBUTES sa; //安全描述符
sa.nLength = sizeof(sa); //用于版本控制
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE; //指定该内核对象句柄是可继承的

//B.生成子进程
CreatepProcess(...);//将bInheritHandles设为TRUE

2. 为对象命名
①使用条件:只针对可进行命名的内核对象。比如:

HANDLE CreateMutex(
	PSECURITY_ATTRIBUTES psa;
	BOOL bInitialOwner;
	PCTSTR pszName;

②使用方法:不同进程创建内核对象时,使用同一个对象名称,比如:

//进程A
HANDLE hMutexProcessA = CreateMutex(NULL,FALSE,TEXT("JeffMutex"));

//进程B
HANDLE hMutexProcessB = CreateMutex(NULL,FALSE,TEXT("JeffMutex"));

③优势:进程B不一定是进程A的子进程
④缺点:难保证唯一性

重要用途:可利用命名对象来防止运行一个应用程序的多个实例。只需在_tmain 或 _tWinMain函数中调用一个Create*函数来创建一个命名对象,再调用GetLastError,如果返回ERROR_ALREADY_EXISTS,则表明应用程序的另一个实例正在运行。比如:

int WINAPI _tWinMain(HINSTANCE hInstExe, HINSTANCE, PRSTR pszCmdLine, int nCmdShow)
{
	HANDLE h = CreateMutex(NULL, FALSE,
				TEXT("fa531cc1"));
	if(GetLastError() == ERROR_ALREADY_EXISTS)
	{
		//该程序已有实例在运行
		CloseHandle(h);
		return(0);
	}
	
	CloseHandle(h);
	return(0);
}

3. 复制对象句柄
①使用方法:调用DuplicateHandle函数

BOOL DuplicateHandle(
	HANDLE hSourceProcessHandle,//源进程内核对象句柄
	HANDLE hSourceHandle,	//任意内核对象句柄,须与hSourceProcessHandle中的进程相关
	HANDLE hTargetProcessHandle,//目标进程内核对象句柄
	PHANDLE phTargetHandle, //接收复制得到的HANDLE值
	DWORD dwDesiredAccess,
	BOOL bInheritHandle,
	DWORD dwOptions
	);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值