windows核心编程指南16.pdf
《windows核心编程指南16.pdf》由会员分享,可在线阅读,更多相关《windows核心编程指南16.pdf(12页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、下载第1 6章线程的堆栈有时系统会在你自己进程的地址空间中保留一些区域。第 3章讲过,对于进程和线程环境块来说,就会出现这种情况。另外,系统也可以在你自己进程的地址空间中为线程的堆栈保留一些区域。每当创建一个线程时,系统就会为线程的堆栈(每个线程有它自己的堆栈)保留一个堆栈空间区域,并将一些物理存储器提交给这个已保留的区域。按照默认设置,系统保留 1 MB的地址空间并提交两个页面的内存。但是,这些默认值是可以修改的,方法是在你链接应用程序时设定M i c r o s o f t的链接程序的/S TA C K选项:当创建一个线程的堆栈时,系统将会保留一个链接程序的/S TA C K开关指明的地址
2、空间区域。但是,当调用C r e a t e T h r e a d或_ b e g i n t h r e a d e x函数时,可以重载原先提交的内存数量。这两个函数都有一个参数,可以用来重载原先提交给堆栈的地址空间的内存数量。如果设定这个参数为0,那么系统将使用/S TA C K开关指明的已提交的堆栈大小值。后面将假定我们使用默认的堆栈大小值,即1 MB的保留区域,每次提交一个页面的内存。图16-1显示了在页面大小为 4 KB的计算机上的一个堆栈区域的样子(保留的起始地址是0 x 0 8 0 0 0 0 0 0)。该堆栈区域和提交给它的所有物理存储器均拥有页面保护属性PA G E _R
3、E A D W R I T E。图16-1 线程的堆栈区域刚刚创建时的样子内存地址0 x080FF0000 x080FD0000 x080FD0000 x080030000 x080020000 x080010000 x08000000堆栈底部:保留页面保留页面保留页面保留页面保留页面带有保护属性标志的已提交页面页面状态堆栈顶部:已提示的页面当保留了这个区域后,系统将物理存储器提交给区域的顶部的两个页面。在允许线程启动运行之前,系统将线程的堆栈指针寄存器设置为指向堆栈区域的最高页面的结尾处(一个非常接近0 x 0 8 1 0 0 0 0 0的地址)。这个页面就是线程开始使用它的堆栈的位置。从顶
4、部向下的第二个页面称为保护页面。当线程调用更多的函数来扩展它的调用树状结构时,线程将需要更多的堆栈空间。每当线程试图访问保护页面中的存储器时,系统就会得到关于这个情况的通知。作为响应,系统将提交紧靠保护页面下面的另一个存储器页面。然后,系统从当前保护页面中删除保护页面的保护标志,并将它赋予新提交的存储器页面。这种方法使得堆栈存储器只有在线程需要时才会增加。最终,如果线程的调用树继续扩展,堆栈区域就会变成图 1 6-2所示的样子。如图 1 6-2所示,假定线程的调用树非常深,堆栈指针C P U寄存器指向堆栈内存地址0 x 0 8 0 0 3 0 0 4。这时,当线程调用另一个函数时,系统必须提交
5、更多的物理存储器。但是,当系统将物理存储器提交给0 x 0 8 0 0 1 0 0 0地址上的页面时,系统执行的操作与它给堆栈的其他内存区域提交物理存储器时的操作并不完全一样。图1 6-3显示了堆栈的保留内存区域的样子。如你预计的那样,从地址0 x 0 8 0 0 2 0 0 0开始的页面的保护属性已经被删除,物理存储器被提交给从0 x 0 8 0 0 1 0 0 0地址开始的页面。它们的差别是,系统并不将保护属性应用于新的物理存储器页面(0 x 0 8 0 0 1 0 0 0)。这意味着该堆栈已保留的地址空间区域包含了它能够包含的全部物理存储器。最底下的页面总是被保留的,从来不会被提交。下面
6、将要说明它的原因。当系统将物理存储器提交给0 x 0 8 0 0 1 0 0 0地址上的页面时,它必须再执行一个操作,即它要引发一个 E X C E P T I O N _ S TA C K _ O V E R F L O W异常处理(在 Wi n N T.h文件中定义为0 x C 0 0 0 0 0 F D)。通过使用结构化异常处理(S E H),你的程序将能得到关于这个异常处理条件的通知,并且能够实现适度恢复。关于S E H的详细说明,请参见第2 3、2 4和2 5章的内容。本章结尾处的S u m m a t i o n示例应用程序将展示如何对堆栈溢出进行适度恢复。图16-2 几乎完整的线
7、程堆栈区域386计计第三部分 内 存 管 理下载内存地址0 x080FF0000 x080FD0000 x080FD0000 x080030000 x080020000 x080010000 x08000000堆栈底部:保留页面保留页面带有保护属性标志的已提交页面已提交的页面已提交的页面已提交的页面页面状态堆栈顶部:已提交的页面图16-3 完整的线程堆栈区域如果在出现堆栈溢出异常条件之后,线程继续使用该堆栈,那么在 0 x 0 8 0 0 1 0 0 0地址上的页面中的全部内存均将被使用,同时,该线程将试图访问从 0 x 0 8 0 0 0 0 0 0开始的页面中的内存。当该线程试图访问这个保
8、留的(未提交的)内存时,系统就会引发一个访问违规异常条件。如果在线程试图访问该堆栈时引发了这个访问违规异常条件,线程就会陷入很大的麻烦之中。这时,系统就会接管控制权,并终止进程的运行不仅终止线程的运行,而切终止整个进程的运行。系统甚至不向用户显示一个消息框,整个进程都消失了!下面要说明为什么堆栈区域的最后一个页面始终被保留着。这样做的目的是为了防止不小心改写进程使用的其他数据。可以看到,在 0 x 0 7 F F 0 0 0这个地址上(0 x 0 8 0 0 0 0 0 0下面的一个页面),另一个地址空间区域已经提交了物理存储器。如果 0 x 0 8 0 0 0 0 0 0地址上的页面包含物理
9、存储器,系统将无法抓住线程访问已保留堆栈区域的尝试。如果堆栈深入到已保留堆栈区域的下面,那么线程中的代码就会改写进程的地址空间中的其他数据,这是个非常难以抓住的错误。16.1 Windows 98下的线程堆栈在Windows 98下,堆栈的行为特性与Windows 2000下的堆栈非常相似。但是它们之间存在某些重大的差别。图1 6-4显示了Windows 98下1 MB的堆栈的各个区域的样子(从0 x 0 0 5 3 0 0 0 0地址上开始保留)。首先请注意,尽管我们想要创建的堆栈大小最大只有 1 MB,但是堆栈区域的大小实际上是1 MB加128 KB。在Windows 98中,每当为一个堆
10、栈保留一个区域时,系统保留的区域实际上比要求的尺寸要大128 KB。该堆栈位于该区域的中间,堆栈的前面有一个64 KB的块,堆栈的后面是另一个64 KB的块。第 1 6章线程的堆栈计计387下载内存地址0 x080FF0000 x080FE0000 x080FD0000 x080030000 x080020000 x080010000 x08000000堆栈底部:保留页面已提交的页面已提交的页面已提交的页面已提交的页面已提交的页面页面状态堆栈顶部:已提交的页面图16-4 Windows 98下线程的堆栈区域刚刚创建时的样子堆栈开始处的64 KB用于抓取堆栈的溢出条件,而堆栈后面的 64 KB则
11、用于抓取堆栈的下溢条件。若要了解为什么需要检测堆栈下溢条件,请看下面这个代码段:当该函数的赋值语句执行时,便尝试访问线程堆栈结尾处之外的内存。当然,编译器和链接程序不会抓住上面代码中的错误,但是,如果应用程序是在 Windows 98下运行,那么当该语句执行时,就会引发访问违规。这是Windows 98的一个出色特性,而Windows 2000是没有的。在Wi n d o w s2 0 0 0中,可以在紧跟线程堆栈的后面建立另一个区域。如果出现这种情况,并且你试图访问你的堆栈外面的内存,那么你将会破坏与进程的另一个部分相关的内存,而系统将不会发现这个情况。需要指出的第二个重要差别是,没有一个页
12、面具有 PA G E _ G U A R D保护属性标志。由于Windows 98不支持这个标志,所以它使用一个不同的方法来扩展线程的堆栈。Windows 98将紧靠堆栈下面的已提交页面标记为PA G E _ N O A C C E S S保护属性(图1 6-4中的地址0 x 0 0 6 3 E 0 0 0)。然后,当线程接触读/写页面下面的页面时,将会发生访问违规。系统抓住这个访问违规,将不能访问的页面改为读写页面,并提交前一个保护页面下面的一个新保护页面。第三个应该注意的差别是图1 6-4中的0 x 0 0 6 3 7 0 0 0地址上的单个PA G E _ R E A D W R I T
13、 E内存页面。这个页面是为了实现与 1 6位Wi n d o w s相兼容而存在的。虽然 M i c r o s o f t从未将它纳入文档,但是开发人员发现1 6位应用程序的堆栈段(S S)开始处的1 6个字节包含了关于1 6位应用程序的堆栈、本地堆栈和本地原子表的信息。由于在 Windows 98上运行的Wi n 3 2应用程序常常调用1 6位D L L组件,有些1 6位组件认为这些信息可以在堆栈段的开始处得到,因此 M i c r o s o f t不得不在Windows 98中仿真这些字节的设置。当3 2位代码转换为1 6位代码时,Windows 98 将把一个1 6388计计第三部分
14、 内 存 管 理下载内存地址0 x006400000 x0063F0000 x0063E0000 x006380000 x006370000 x0065400000 x00530000大小16页面(65 536字节)1页面(4096字节)1页面(4096字节)6页面(24 576字节)1页(4096字节)247页面(1 011 712字节)16页面(65 536字节)页面状态堆栈顶部:保留供堆栈下溢时使用带有PA G E _ R E A D W R I T E保护属性的已提交页面,堆栈在用仿真PA G E _ G U A R D标志的PA G E _ N O _ACCESS页面保留供堆栈溢出时
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- windows 核心 编程 指南 16
限制150内