《Windows内核编程》基本数据结构
- 格式:pdf
- 大小:186.26 KB
- 文档页数:15
《Windows核心编程》Windows的“堆”分为默认堆和私有堆两种。
默认堆是在程序初始化时由操作系统自动创建的,所有标准内存管理函数都是在默认堆中申请内存的;而私有堆相当于在默认堆中保留了一大块内存,用堆管理函数可以在这个保留的内存区域中分配内存。
一个进程的默认堆只有一个,而私有堆可以被创建多个。
默认堆可以直接被使用,而私有堆在使用前需要先创建,使用私有堆有很多好处:1)可以使用默认堆的函数有多种,而它们可能在不同的线程中同时对默认堆进行操作,为了保持同步,对默认堆的访问是顺序进行的;而私有堆的空间是预留的,不同线程在不同的私有堆中同时分配内存并不会引起冲突,所以整体的运行速度更快。
2)当系统必须在物理内存和页文件之间进行页面交换时,系统的性能会受到很大的影响,在某些情况下,使用私有堆可以防止系统频繁地在物理内存和交换文件之间进行数据交换,因为将经常访问的内存局限在一个小范围地址的话,页面交换就不大可能发生,把频繁访问的大量小块内存放在同一个私有堆中就可以保证它们在内存中的位置更近。
3)使用私有堆有利于封装和保护模块化的程序。
当程序包含多个模块时,如果使用标准内存管理函数在默认堆中分配内存,那么所有模块分配的内存块是交叉排列在一起的,如果模块A中的一个错误导致内存操作越界,可能会覆盖模块B使用的内存块,到模块B执行时出错,我们将很难发现错误的源头来自于模块A。
而如果让不同模块使用自己的私有堆,那么它们的内存就会完全隔离开了,越界错误就很容易跟踪和定位了。
4)使用私有堆使得大量内存的清理变得方便,在默认堆中分配的内存需要一块块单独释放,但将一个私有堆释放后,在这个堆里的内存就全部被释放掉了。
并不需要预先释放堆栈的每个内存块。
私有堆的创建和释放:创建私有堆的函数是HeapCreate:HANDLE WINAPI HeapCreate(__in DWORD flOptions, //指定堆的属性://HEAP_GENERATE_EXCEPTIONS---指定函数失败时返回值,不指定这个标志时,函数失败//时返回NULL、否则返回一个具体的错误代码//HEAP_NO_SERIALIZE---控制对私有堆的访问是否要进行独占性的检测;指定这个标志时,//建立堆时不进行独占性检测,访问速度可以更快__in SIZE_T dwInitialSize, //创建堆时分配给堆的物理内存(堆的内存不足时可以自动扩展)__in SIZE_T dwMaximumSize //能够扩展到的最大物理内存);如果一个堆不再需要了,可以调用HeapDestroy函数将它释放:BOOL WINAPI HeapDestroy(__in HANDLE hHeap //堆句柄);释放私有堆可以释放堆中包含的所有内存块,也可以将堆占用的物理内存和保留的地址空间全部返还给系统。
Windows进程与线程数据结构Windows进程与线程数据结构1、引言1.1 目的1.2 背景2、进程与线程概述2.1 进程的定义与特点2.2 线程的定义与特点2.3 进程与线程的关系3、进程数据结构3.1 进程控制块 (Process Control Block, PCB) 3.1.1 PCB的作用与组成3.1.2 PCB中的进程属性3.2 进程地质空间3.2.1 用户态和内核态地质空间3.2.2 虚拟内存管理3.3 进程状态3.3.1 进程的执行状态3.3.2 进程的阻塞状态3.3.3 进程的就绪状态3.4 进程调度算法3.4.1 先来先服务(First-Come, First-Served, FCFS)3.4.2 短作业优先(Shortest Job Next, SJN)3.4.3 优先级调度算法3.4.4 时间片轮转调度算法3.4.5 多级反馈队列调度算法4、线程数据结构4.1 线程控制块 (Thread Control Block, TCB)4.1.1 TCB的作用与组成4.1.2 TCB中的线程属性4.2 线程同步4.2.1 互斥量 (Mutex)4.2.2 信号量 (Semaphore)4.2.3 事件 (Event)4.2.4 临界区 (Critical Section)4.3 线程调度4.3.1 抢占式调度与非抢占式调度4.3.2 线程优先级4.3.3 协同式调度与抢占式调度5、附件附件1、进程与线程数据结构示意图附件2、示例代码法律名词及注释:- 进程:指计算机系统中同一程序的不同执行实例,具有独立的运行空间和资源。
- 线程:是系统内的执行单元,是程序中的一个执行流程,一个进程可以拥有多个线程。
- PCB(Process Control Block):每个进程在操作系统中都对应着一个PCB数据结构,用于保存进程的相关信息。
- 进程地质空间:进程分配的内存空间,用于存放程序、数据和堆栈等信息。
《Windows内核编程》-----基本汇编指令学习各种高级外挂制作技术,马上去百度搜索"魔鬼作坊",点击第一个站进入,快速成为做挂达人。
1)用VS2010新建Win32Console Application,工程名为ACEC ore,工程建立完成后得到打开文件ACECore.cpp,代码如下:#include"stdafx.h"int_tmain(int argc,_TCHAR*argv[]){return0;}2)用VS2010查看汇编代码的方法:1.VC必须处于debug状态才能看到汇编指令窗口。
因此在上面代码return0一句上设置断点。
2.按下F5键调试程序,当程序停在断点处时,打开菜单“Debug”下的“Windows”子菜单,选择“Disassembly”。
这样就出现反汇编窗口,显示汇编代码:---g:/acecore/acecore/acecore.cpp---------------------------------------------//ACECore.cpp:Defines the entry point for the console a pplication.//#include"stdafx.h"int_tmain(int argc,_TCHAR*argv[]){00411350push ebp00411351mov ebp,esp00411353sub esp,0C0h00411359push ebx0041135A push esi0041135B push edi0041135C lea edi,[ebp-0C0h]00411362mov ecx,30h00411367mov eax,0CCCCCCCCh0041136C rep stos dword ptr es:[edi]return0;0041136E xor eax,eax}3)相关汇编指令:push:把一个32位的操作数压入堆栈中,这个操作导致esp被减4。
《操作系统原理实验》Windows进程与线程数据结构主讲:黄伯虎Windows 体系结构简化的windows 结构图Kernel: 由低层次的操作系统功能构成,比如线程调度、中断和异常分发、多处理器同步等。
提供了一些例程和基本对象。
执行体可以利用这些对象实现更高层次的功能。
Executive: 包含了基本的操作系统服务,包括内存管理、进程和线程管理、安全性、I/O 、网络和跨进程通信等。
Windows基本对象暴露给windows API的执行体对象执行体对象:指由执行体的各种组件(比如进程管理器、内存管理器、I/O子系统等)所实现的对象。
用户可见。
内核对象:指由Windows内核实现的一组更为基本的对象。
内核对象对用户而言是不可见的,只能在执行体内部被创建和使用。
Windows进程的组成(从最高抽象层次看)一个私有的虚拟地址空间一个可执行的程序:定义了代码和数据,并被映射到进程的虚拟地址空间。
一个已经打开句柄的列表:指向各种资源,比如信号量、文件,该进程的所有线程都可访问这些系统资源。
一个被称为访问令牌的安全环境:标识与该进程关联的用户、安全组和特权一个被称为进程ID的唯一标识至少一个执行线程Windows进程的关键数据结构执行体进程块(EPROCESS)执行体进程对象的对象体,包括进程ID、父进程ID、程序名、进程优先级、内存管理信息、设备映像等。
核心进程块(KPROCESS)内核进程对象的对象体,又称PCB,包括线程调度时需要的信息,如进程状态、线程时间片等。
进程环境块(PEB)包括用户态代码需要和修改的信息。
Windows环境子系统核心态部件win32k.sys为每个进程建立的进程信息数据结构WIN32KPROCESSWindows环境子系统进程csrss(用户态)为每个进程建立的进程信息数据结构Process environmentblockWin32 process blockHandle tableProcess address spaceSystem address spaceProcess block (EPROCESS)PCB组成线程的基本部件一组代表处理器状态的CPU寄存器中的内容两个栈:一个用于当线程在内核模式下执行的时候,另一个用于线程在用户模式下执行的时候。
ZWCreateThreadEx 结构是 Windows 内核中一个重要的数据结构,用于在用户模式进程中创建线程。
它包含了一系列的参数和属性,用于指定新线程的行为和属性。
在本文中,我将深入探讨ZWCreateThreadEx 结构的相关内容,并重点分析其在 Windows 内核中的作用和应用。
我们需要了解ZWCreateThreadEx 结构的组成和构成要素。
ZWCreateThreadEx 结构包括了被调用函数的参数、返回值等信息,以及线程的属性、环境等信息。
通过这些信息,操作系统可以根据用户的需求和指定的参数来创建一个新的线程。
在实际的应用中,我们可以通过初始化并填充ZWCreateThreadEx 结构,然后通过调用相应的函数来创建一个线程。
接下来,我们需要探讨ZWCreateThreadEx 结构在内核中的作用和应用。
在 Windows 内核中,创建线程是一个非常常见的操作,线程的创建需要提供一系列的参数和属性,来指定线程的行为和特性。
ZWCreateThreadEx 结构为我们提供了一个便捷和灵活的方式来指定这些参数和属性,使得我们能够更加精细地控制线程的创建和行为。
通过对ZWCreateThreadEx 结构的了解和使用,我们可以更好地理解和掌握线程的创建和调度机制。
在文章的后半部分,我会共享我个人对ZWCreateThreadEx 结构的观点和理解。
从我的角度来看,ZWCreateThreadEx 结构在 Windows内核中的重要性不言而喻。
它为我们提供了一个灵活和强大的工具,可以帮助我们更好地管理和控制线程的创建和行为。
通过对ZWCreateThreadEx 结构的深入研究和理解,我们可以更好地理解Windows 内核的工作原理和机制,从而能够更好地应用它来解决实际的问题和挑战。
总结而言,ZWCreateThreadEx 结构在 Windows 内核中扮演着非常重要的角色,它为线程的创建和调度提供了一个灵活和强大的工具。
《Windows内核编程》基本数据结构学习各种高级外挂制作技术,马上去百度搜索(魔鬼作坊),点击第一个站进入,快速成为做挂达人。
驱动对象:每个驱动程序都会有唯一的驱动对象与之对应,并且这个驱动对象是在驱动加载时被内核中的对象管理程序所创建的。
驱动对象用DRIVER_OBJECT数据结构表示,它作为驱动的一个实例被内核加载,并且内核对一个驱动只加载一个实例。
确切地说,是由内核中的I/O管理器负责加载的,驱动程序需要在DriverEntry中初始化。
驱动对象的结构定义如下(wd m.h):typedef struct_DRIVER_OBJECT{//结构的类型和大小CSHORT Type;CSHORT Size;//每个驱动程序会有一个或多个设备对象,其中,每个设备对象都有一个指针指向下一个驱动对象//最后一个设备对象指向空。
DeviceObject指向驱动对象的第一个设备对象。
通过Devic eObject,就//可以遍历驱动对象中的所有设备对象了。
PDEVICE_OBJECT DeviceObject;ULONG Flags;//The following section describes where the driver is loaded.The count //field is used to count the number of times the driver has had its//registered reinitialization routine invoked.PVOID DriverStart;ULONG DriverSize;PVOID DriverSection;PDRIVER_EXTENSION DriverExtension;//记录驱动设备的名字,用UNICODE字符串记录,该字符串一般/Driver/[驱动程序名称]UNICODE_STRING DriverName;//设备的硬件数据库键名,也是UNICODE字符串记录。
一般为///REGISTRY/MACHINE/HADRWARE/DESCRIPTION/SYSTEMPUNICODE_STRING HardwareDatabase;//文件驱动中用到的派遣函数PFAST_IO_DISPATCH FastIoDispatch;//The following section describes the entry points to this particular//driver.Note that the major function dispatch table must be the last //field in the object so that it remains extensible.PDRIVER_INITIALIZE DriverInit;//记录StartIO例程的函数地址,用于串行化操作PDRIVER_STARTIO DriverStartIo;//指定驱动卸载时所用的回调函数地址PDRIVER_UNLOAD DriverUnload;//MajorFunction域记录的是一个函数指针数组,也就是MajorFunction是一个数组,数组中的每个//成员记录着一个指针,每一个指针指向的是一个函数。
这个函数是处理IRP的派遣函数PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION+1];}DRIVER_OBJECT;typedef struct_DRIVER_OBJECT*PDRIVER_OBJECT;实际上如果写一个驱动程序,或者说编写一个内核模块,要在Windows中加载,就必须填写上面的结构,来告诉Windows程序提供的功能。
注意内核模块并不生成一个进程,它只是写一组回调函数让Windows调用,且这组回调函数必须符合Windows内核规定的格式。
上面代码中的“快速IO分发函数”FastIoDispatch和“普通分发函数”MajorFunction就是这样一种回调函数。
这些函数用来处理发送给这个内核模块的请求。
Windows中很多组件都拥有自己的DRIVER_OBJECT,例如:所有的硬件驱动程序、所有的类驱动(Disk、Cdrom…)、文件系统(NTFS和FastFat,有各自的DRIVER_OBJECT),以及许多其他的内核组件。
我们可以使用一个软件WinObj来查看所有的内核对象。
设备对象:每个驱动程序会创建一个或多个设备对象,用DEVICE_OBJECT数据结构表示。
每个设备对象都会有一个指针指向下一个设备对象,因此就形成一个设备链。
设备链的第一个设备是由DRIVER_OBJECT结构体中指明的。
设备对象是内核中的重要对象,其重要性不亚于Windows GUI编程中的窗口。
窗口是唯一可以接收消息的对象,任何消息都是发送到一个窗口中的;而在内核编程中,大部分“消息”是以请求IRP的方式传递的。
而设备对象(DEVICE_OBJECT)是唯一可以接收请求的实体,任何一个请求IRP都是发送给某个设备对象的。
设备对象的结构是DEVICE_OBJECT,常常被简称为DO。
一个DO可以代表很多不同的东西,例如一个实际的硬盘、或实现一个类似管道的功能等等。
我们总是在内核程序中生成一个DO,而一个内核程序是用一个驱动对象表示的,因此,一个设备对象总是属于一个驱动对象。
在WDK的wdm.h文件中DO的定义如下:typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT)_DEVICE_OBJECT{//结构的类型和大小CSHORT Type;USHORT Size;//引用计数LONG ReferenceCount;//指向驱动程序中的驱动对象,同属于一个驱动程序的驱动对象指向的是同一驱动对象struct_DRIVER_OBJECT*DriverObject;//下一个设备对象。
//这里指的下一个设备对象是同属于一个驱动对象的设备,也就是同一个驱动程序创建的若干设备//对象,每个设备对象根据NextDevice域形成链表,从而可以枚举每个设备对象struct_DEVICE_OBJECT*NextDevice;//指向下一个设备对象,这里指的是,如果有更高一层的驱动附加到这个驱动的时候//AttachedDevice指向的就是那个更高一层的驱动struct_DEVICE_OBJECT*AttachedDevice;//在使用StartIO例程的时候,此域指向的是当前IRP结构struct_IRP*CurrentIrp;PIO_TIMER Timer;//此域是一个32位的无符号整型,每一位有具体的含义//DO_BUFFERED_IO---读写操作使用缓冲方式(系统复制缓冲区)访问用户模式数据//DO_EXCLUSIVE---一次只允许一个线程打开设备句柄//DO_DIRECT_IO---读写操作使用直接方式(内存描述符表)访问用户模式数据//DO_DEVICE_INITIALIZING---设备对象正在初始化//DO_POWER_PAGABLE---必须在PASSIVE_LEVEL级上处理IRP_MJ_PNP请求//DO_POWER_INRUSH---设备上电期间需要大电流ULONG Flags;ULONG Characteristics;__volatile PVPB Vpb;//指向设备扩展对象,每个设备都会指定一个设备扩展对象,设备扩展对象记录的是设备自己//特殊定义的结构体,即程序员自己定义的结构体。
另外,在驱动开发中,应该尽量避免全局变量的//使用,因为全局变量涉及不容易同步问题。
解决的方法是:将全局变量存在设备扩展中PVOID DeviceExtension;//设备类型,当制作虚拟设备时,应选择FILE_DEVICE_UNKNOWN类型的设备DEVICE_TYPE DeviceType;//IRP栈大小。
在多层驱动情况下,驱动与驱动之间会形成类似堆栈的结构,IRP会依次从//最高层传递到最底层CCHAR StackSize;union{LIST_ENTRY ListEntry;WAIT_CONTEXT_BLOCK Wcb;}Queue;//设备在大容量传输时,需要内存对齐,以保证传输速度ULONG AlignmentRequirement;KDEVICE_QUEUE DeviceQueue;KDPC Dpc;//The following field is for exclusive use by the filesystem to keep //track of the number of Fsp threads currently using the device ULONG ActiveThreadCount;PSECURITY_DESCRIPTOR SecurityDescriptor;KEVENT DeviceLock;USHORT SectorSize;USHORT Spare1;struct_DEVOBJ_EXTENSION*DeviceObjectExtension;PVOID Reserved;}DEVICE_OBJECT;typedef struct_DEVICE_OBJECT*PDEVICE_OBJECT;一个驱动对象可以生成多个设备对象,而Windows向设备对象发送请求时,这些请求是被驱动对象的分发函数所捕获的,即当Windows内核向一个设备发送一个请求时,驱动对象的分发函数中的某一个会被调用,分发函数原型如下://参数device是请求的目标设备;参数irp是请求的指针NTSTATUE ASCEDispatch(PDEVICE_OBJECT device,PIRP irp);附:设备扩展:设备对象记录“通用”设备的信息,而另外一些“特殊”信息记录在设备扩展里。
各个设备扩展由程序员自己定义,每个设备的设备扩展不尽相同。
设备扩展是由程序员指定内容和大小,由I/O管理器创建的,并保存在非分页内存中。
在驱动程序中,尽量避免使用全局函数,因为全局函数往往导致函数的不可重入性。
重入性指的是在多线程程序中,多个函数并行运行,函数的运行结果不会根据函数的调用先后顺序而导致不同。
解决的办法是,将全局变量以设备扩展的形式存储,并加以适当的同步保护措施。
除此之外,在设备扩展中还会记录下列一些内容:设备对象的反向指针;设备状态或驱动环境变量;中断对象指针;控制器对象指针。
由于设备扩展是驱动程序专用的,它的结构必须在驱动程序的头文件中定义。