`
op380op
  • 浏览: 15455 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

《Windows 核心编程》 -- 内核对象 --札记

 
阅读更多

《Windows 核心编程》 -- 内核对象 --札记
2010年07月06日
  1.常见的内核对象有哪些?
  答:存取符号对象、事件对象、文件对象、文件映射对象、I / O完成端口对象、作业对象、信箱对象、互斥对象、管道对象、进程对象、信标对象、线程对象和等待计时器对象等
  2.怎么使用和管理内核对象?
  答:内核对象的数据结构只能被内核访问,因此应用程序无法在内存中找到这些数据结构并直接改变它们的内容。通常使用Wi n d o w s提供的一组函数来对这些结构进行操作。
  3.内核对象主要特征有哪些?
  答:1)内核对象由内核所拥有,而不是由进程所拥有,因此必须记住的是,内核对象的存在时间可以比创建该对象的进程长。
  2)内核知道有多少进程正在使用某个内核对象,因为每个对象包含一个使用计数。使用计数是所有内核对象类型常用的数据成员之一。当一个对象刚刚创建时,它的使用计数被置为1。然后,当另一个进程访问一个现有的内核对象时,使用计数就递增1。当进程终止运行时,内核就自动确定该进程仍然打开的所有内核对象的使用计数。如果内核对象的使用计数降为0,内核就撤消该对象。这样可以确保在没有进程引用该对象时系统中不保留任何内核对象。
  3)内核对象能够得到安全描述符的保护.(安全描述符用于描述谁创建了该对象,谁能够访问或使用该对象,谁无权访问该对象。安全描述符通常在编写服务器应用程序时使用,如果你编写客户机端的应用程序,那么可以忽略内核对象的这个特性。)
  4.如何区分内核对象和非内核对象?
  答:若要确定一个对象是否属于内核对象,最容易的方法是观察创建该对象所用的函数。创建内核对象的所有函数几乎都有一个参数,你可以用来设定安全属性的信息,这与前面讲到的C r e a t e F i l e M a p p i n g函数是相同的。用于创建用户对象或G D I对象的函数都没有P S E C U R I T Y AT T R I B U T E S参数
  如:                //内核对象: WINBASEAPI __out_opt HANDLE WINAPI CreateFileMappingW( __in HANDLE hFile, __in_opt LPSECURITY_ATTRIBUTES lpFileMappingAttributes, __in DWORD flProtect, __in DWORD dwMaximumSizeHigh, __in DWORD dwMaximumSizeLow, __in_opt LPCWSTR lpName ); //非内核对象: WINUSERAPI HICON WINAPI CreateIcon( __in_opt HINSTANCE hInstance, __in int nWidth, __in int nHeight, __in BYTE cPlanes, __in BYTE cBitsPixel, __in CONST BYTE *lpbANDbits, __in CONST BYTE *lpbXORbits );   5.内核对象的创建后存在哪里?返回什么?
  答:用于创建内核对象的所有函数均返回与进程相关的句柄,这些句柄可以被在相同进程中运行的任何或所有线程成功地加以使用。该句柄值实际上是放入进程的句柄表中的索引,它用于标识内核对象的信息存放的位置。
  如果调用一个函数以便创建内核对象,但是调用失败了,那么返回的句柄值通常是0(N U L L,原因通常是内存紧缺了,或者遇到了安全方面的问题)。不过有少数函数在运行失败时返回的句柄值是-1(I N VA L I D H A N D L E VA L U E),因此使用时尽量查看SDK文档,确认返回值进行判断,不可武断的判断是 NULL 或者是 I N VA L I D H A N D L E VA L U E
  6.内核对象的关闭方法是什么?如果不关闭会怎样?
  答:无论怎样创建内核对象,都要向系统指明将通过调用C l o s e H a n d l e来结束对该对象的操作: WINBASEAPI BOOL WINAPI CloseHandle( __in HANDLE hObject ); 在C l o s e H a n d l e返回之前,它会清除进程的句柄表中的项目,该句柄现在对你的进程已经无效,不应该试图使用它。无论内核对象是否已经撤消,都会发生清除操作。当调用C l o s e H a n d l e函数之后,将不再拥有对内核对象的访问权。
  假如忘记调用C l o s e H a n d l e函数,那么会不会出现内存泄漏呢?答案是可能的,但是也不一定。在进程运行时,进程有可能泄漏资源(如内核对象)。但是,当进程终止运行时,操作系统能够确保该进程使用的任何资源或全部资源均被释放,这是有保证的。
  插曲1:应用程序在运行时有可能泄漏内核对象,但是当进程终止运行时,系统将能确保所有内容均被正确地清除。另外,这个情况适用于所有对象、资源和内存块,也就是说,当进程终止运行时,系统将保证进程不会留下任何对象。
  插曲2:很多程序在创建线程都这样写的: ThreadHandle = CreateThread(NULL,0,.....); CloseHandel(ThreadHandle );   莫非是创建线程之后就销毁了?非也!通过MSDN相关说明,我们能够看到:
  1)线程和线程句柄(Handle)不是一个东西,线程是在cpu上运行的.....(说不清楚了),线程句柄是一个内核对象。我们可以通过句柄来操作线程,但是线程的生命周期和线程句柄的生命周期不一样的。线程的生命周期就是线程函数从开始执行到return,线程句柄的生命周期是从CreateThread返回到你CloseHandle()。
  2)所有的内核对象(包括线程Handle)都是系统资源,用了要还的,也就是说用完后一定要closehandle关闭之,如果不这么做,你系统的句柄资源很快就用光了。
  3)如果你CreateThread以后需要对这个线程做一些操作,比如改变优先级,被其他线程等待,强制TermateThread等,就要保存这个句柄,使用完了在CloseHandle。如果你开了一个线程,而不需要对它进行如何干预,CreateThread后直接CloseHandle就行了。
  所以CloseHandel(ThreadHandle );
  只是关闭了一个线程句柄对象,表示我不再使用该句柄,即不对这个句柄对应的线程做任何干预了。并没有结束线程。
  跨越进程边界共享内核对象 --待研究中……
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics