windows编程之内核对象

      学好windows编程,理解内核对象还是至关重要的(●'◡'●)。闲话不多说,下面先来了解一下关于内核对象的知识:

      内核对象(kernel object):内核对象是用于管理进程、线程和文件等诸多种类的大量资源。

      内核对象的分类:进程对象,线程对象,互斥量(mutex)对象,信号量(semaphore)对象,事件对象,作业对象,文件对象,文件映射对象,管道(pipe)对象,邮件槽(mailslot)对象,I/O完成端口对象,线程池工厂(thread pool  worker  factory)对象,令牌(access token)对象、可等待的计时器(waitable timer)对象等。

      内核对象的特性:

      每个内核对象都只是一个内存块,它由操作系统分配,并只能由操作系统内核访问,这个内存块是一个数据结构,其成员维护着与对象相关的信息。少数成员(安全描述符和使用计数等)是所有对象都有的,但其他大多数成员都是不同类型的对象特有的。例如,进程对象有一个ID,一个基本的优先级和一个退出代码;而文件对象有一个字节偏移量(byte offset)、一个共享模式和一个打开模式。

      由于内核对象的数据结构只能被操作系统访问,故应用程序不能在内存中定位这些数据结构并更改其内容;

     当调用一个可以创建内核对象的函数后,该函数会返回一个用于标识该对象的句柄。如果将该句柄值传递给另一个进程中的一个线程,那么这另一个进程使用你的进程的句柄值所作的调用就会失败。如果想在多个进程*享内核对象,要通过一定的机制(如对象句柄的继承性,命名对象,复制对象句柄)。

   

      下图所示是一个可以查看一个包含所有内核对象类型的列表的软件(WinObj)界面。有兴趣的可以下载学习一下,加深一下对内核对象的认识。

      windows编程之内核对象

内核对象的安全性:内核对象可以用一个安全描述符(security descriptor,SD)来保护。用于创建内核对象的所有函数几乎都指向一个SECURITY_ATTRIBUTES结构的指针作为参数:如下面的

                                                CreateFileMapping(

                                                                              HHANDLE hFile,

                                                                              PSECURITY_ATTRIBUTES  psa,

                                                                              DWORD flProtect,

                                                                              DWORD dwMaximumSizeHigh,  

                                                                              DWORD dwMaximumSiizelow,

                                                                              PCTSTR pszName              

                                                                           );

大多数应用程序只是为这个参数传入NULL,这样创建的内核对象具有默认的安全性----具体包括哪些默认的安全性,要取决于当前进程的安全令牌(security token)。但是也可以分配一个SECURITY_ATTRIBUTES结构,并对它进行初始化,再将它的地址传给这个参数。SECURITY_ATTRIBUTES结构体如下所示:

                                                typedef struct   _SECURITY_ATTRIBUTES {

                                                                              DWORD nLength;

                                                                              LPVOID lpSecurityDescriptor;

                                                                              BOOL  bInheritHandle;

                                                                              } SECURITY_ATTRIBUTES;

虽然这个结构称为SECURITY_ATTRIBUTES,但它实际上只包含一个和安全性有关的成员,即lpSecurityDescriptor。如果相对创建的内核对象加以访问限制,就必须创建一个安全描述符,然后按下面所示初始化其结构:

                                                                             SECURITY_ATTRIBUTES  sa;

                                                                             sa.nLength = sizeof(sa);

                                                                             sa.lpSecrityDeccriptor = pSD;

                                                                             sa.bInheritHandle = FALSE;

                                                                             HANDLE hFileMApping = CreateFileMapping(INVALID_HANDLE_VALUE,

                                                                                                                                         &sa,

                                                                                                                                         P0AGE_READWRITE,

                                                                                                                                         0,

                                                                                                                                         1024,

                                                                                                                                         TEXT(“MyFileMapping”));

若想访问一个现有的文件映射对象,以便从中读取数据,可以如下下述方式调用:

                                                                             HANDLE hFileMapping = OpenFileMapping(

                                                                                                                                         FILE_MAP_READ,FALSE,

                                                                                                                                         FALSE,

                                                                                                                                         TEXT(“MyFileMapping”));

若想判断一个对象是不是内核对象,最简单的方式是查看创建这个对象的函数。几乎所有创建内核对象的函数都有一个指定安全属性信息的参数,就像上述的CreateFileMapping函数一样。相反,用于创建用户对象或GDI对象的函数都没有PSECURITY_ATTRIBUTES参数。如下所示的CreateIcon函数

                                                                       HICON CreateIcon(

                                                                                                             HINSTANCE  hinst,

                                                                                                             int  nWidth,

                                                                                                             int nHight,

                                                                                                             BYTE cPlanes,

                                                                                                             BYTE cBitsPixel,

                                                                                                             CONST BYTE *pbANDbits,

                                                                                                             CONST BYTE *pbXORbits);

ps:像菜单、窗口、鼠标光标、画刷和字体这样的对象属于用户对象或GDI(Graphical Device  Interface)对象。 

       部分创建内核对象的函数:

                                                               HANDLE CraeateThread (

                                                                                                              PSECURITY_ATTRIBUTES  psa,

                                                                                                              size_t  dwStackSize,

                                                                                                              LPTHREAD_START_ROUTINE pfnstartAddress,

                                                                                                              PVOID pvParam,

                                                                                                              DWORD dwCreatinFlags,

                                                                                                              PDWORD pdwThread );

                                                                 HANDLE CraeateFile    (

                                                                                                              PCTSTR pszFileName

                                                                                                              DWORD  dwDesiredAccess,

                                                                                                              DWORD  dwShareMode,

                                                                                                              PSECURITY_ATTRIBUTES  psa,

                                                                                                              DWORD   daCreationDisposition,

                                                                                                              DWORD   dwFlagsAndAttributes,

                                                                                                              HANDLE   hTemplateFile );

                                                           HANDLE CreateSemaphore (

                                                                                                              PSECURITY_ATTRIBUTES  psa,

                                                                                                              LONG lInitialCount,

                                                                                                              LONG lMaxiumumCount,

                                                                                                              PCTSTR pszName);

                                                           ……

结束内核对象,需调用:BOOL CloseHandle(HANDLE  hobject);

    

                                                                          

                                                

 

上一篇:内核对象&句柄


下一篇:delphi关于文件操作集锦