基础和正确的大小来处理局部变量,
表达式temp推/弹出,并调用库(包括
堆栈空间用于库程序工作).这样的堆栈
帧实际上可以小到32字节,通常是.
这一切都很好,除非代码做愚蠢的事情
导致硬件陷阱… Windows出现在哪个位置
坚持将整个x86机器上下文“堆叠”.
如果您包含FP / MMX /等等,这是大约500字节.寄存器,
它是做什么的.自然地,一个500字节的推送在一个32字节堆栈
粉碎不应该的东西. (硬件推几句话
在陷阱上,但不是整个上下文).
[EDIT 11/27/2012:见this for measured details on the rediculous
amount of stack Windows actually pushes]
我可以让Windows存储异常上下文块
别的地方(例如,到线程特有的位置)?
那么软件可能会出现异常
打到线程并处理它,而不会溢出我的
小堆栈框架.
我不认为这是可能的,但我以为我会问一个更大的
听众.是否有操作系统标准的通话/接口
那可能会导致这种情况发生?
在操作系统中做这件事情是微不足道的,如果我可以让MS让我的
过程可选地定义上下文存储位置“contextp”,其中
被初始化为默认启用当前的旧版行为.
然后替换中断/陷阱向量代码:
hardwareint: push context mov contextp,esp
…与…
hardwareint: mov <somereg> contextp test <somereg> jnz $2 push context mov contextp,esp jmp $1 $2: store context @ somereg $1: equ *
保存somereg等所需的明显变化等
[我现在做的是:检查每个功能的生成代码.
如果它有机会产生陷阱(例如除以零),
或者我们正在调试(可能的坏指针deref等),添加
足够的空间到FP框架的堆栈框架.堆叠帧
现在最终是~~ 500-1000字节的大小,程序不能
到目前为止,这有时是一个真正的问题
我们正在写的应用程序.所以我们有一个可行的解决方案,
但它使调试变得复杂]
编辑8月25日:我设法将这个故事告诉了微软的内部工程师
谁具有权威性,以确定谁可能实际上是谁
关心.解决方案可能会有微弱的希望.
编辑9月14日:MS Kernal集团建筑师听到这个故事,并且是同情的.他表示,MS会考虑一个解决方案(如所提出的解决方案),但不太可能在服务包中.可能要等待下一个版本的Windows. (叹…我可能长大了…)
编辑:2010年9月13日(1年后).没有微软的行动.我最新的噩梦:在Windows X64上执行32位进程的陷阱,在中断处理程序伪造32位上下文之前,将整个X64上下文推送到堆栈上?那会更大(两倍于整数寄存器的两倍,是SSE寄存器的两倍)?
编辑:2012年2月25日(1.5年过去了)…对微软没有反应.我猜他们只是不在乎我的并行性.我认为这是对社会的一种伤害; MS在正常情况下使用的“大堆栈模型”通过吃大量虚拟机限制了任何时刻可以存在的并行计算量. PARLANSE模式将让人们在各种运行/等待状态下拥有一百万个活的“谷物”应用程序;这真的发生在我们的一些应用程序中,并行处理了1亿个节点图. PARLANSE方案可以实现大约1Gb的RAM,这是非常易于管理的.如果您尝试使用MS 1Mb“大堆栈”,则需要10 ^ 12个字节的虚拟机只适用于堆栈空间,我非常确定Windows不会让您管理一百万个线程.
编辑:2014年4月29日(4年过去了).我猜MS只是不读SO.我已经在PARLANSE上做了足够的工程,所以我们只需要在调试过程中支付大堆栈帧的价格,或者在进行FP操作时,我们设法找到了非常实用的方法. MS持续令人失望;各种版本的Windows推送在堆栈上的东西的数量似乎差异很大,非常高于和超出了对硬件上下文的需求.有一些提示,一些这种变异性是由非MS产品(例如防病毒)在异常处理链中粘住鼻子引起的;为什么他们不能从我的地址空间外面呢?不管怎样,我们通过简单地为FP /调试陷阱添加一个大的斜率因子来处理所有这些,并等待超出该数量的字段中不可避免的MS系统.
问题是,您还需要重新实现一个内核模式 – > usermode回调(对于SEH这个回调驻留在ntdll.dll中,被命名为KiuserExceptionDispatcher,这将触发所有的SEH逻辑).关键是,系统的其余部分依赖于SEH的工作方式,现在,您的解决方案会破坏事情,因为你正在做系统的.也许你可以在中断时检查你在哪个进程.
但是,整体概念容易出错,非常严重影响系统的稳定性.
这些实际上是rootkit的技术.
编辑:一些更多的细节:你需要重新实现中断处理程序的原因是,例外(例如除以零)本质上是软件中断,并且总是通过IDT.当抛出异常时,内核收集上下文并将异常发送回usermode(通过上述的ntdll中的KiUserExceptionDispatcher).您需要在此处进行干预,因此您还需要提供一种恢复用户模式的机制. (在ntdll中有一个函数用作内核模式的入口点 – 我不记得名字,但它的名字与KiUserACP …..)