在受控环境(Win32)下运行应用程序的问题 [英] Problems with running an application under controlled environment (Win32)

查看:88
本文介绍了在受控环境(Win32)下运行应用程序的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不确定如何标记此问题或如何写标题,因此,如果有人有更好的主意,请对其进行编辑

I'm not exactly sure how to tag this question or how to write the title, so if anyone has a better idea, please edit it

这是交易:

前段时间,我写了一个计算机奥林匹克管理系统的关键部分.系统的工作是从参与者(代码文件)中获取提交,进行编译,针对预定义的测试用例运行它们,然后返回结果.加上您可以想象的所有其他内容.

Some time ago I had written a little but cruicial part of a computing olympiad management system. The system's job is to get submissions from participants (code files), compile them, run them against predefined test cases, and return results. Plus all the rest of the stuff you can imagine it should do.

我写的那一部分叫做 Limiter .这是一个小程序,其工作是采用另一个程序并在受控环境中运行它.在这种情况下,受控制意味着对可用内存,计算时间和对系统资源的访问的限制.另外,如果程序崩溃,我应该能够确定异常的类型并将其报告给用户.另外,当进程终止时,应注意其执行了多长时间(分辨率至少为0.01秒,更好).

The part I had written was called Limiter. It was a little program whose job was to take another program and run it in a controlled environment. Controlled in this case means limitations on available memory, computing time and access to system resources. Plus if the program crashes I should be able to determine the type of the exception and report that to the user. Also, when the process terminated, it should be noted how long it executed (with a resolution of at least 0.01 seconds, better more).

当然,实现此目标的理想解决方案是虚拟化,但是我对此并不经验丰富.

Of course, the ideal solution to this would be virtualization, but I'm not that experienced to write that.

我对此的解决方案分为三个部分.

My solution to this was split into three parts.

最简单的部分是对系统资源的访问.该程序将仅使用有限的访问令牌执行.我结合了一些基本的(所有人,匿名等)访问令牌,这些令牌可用于所有进程,以便实际上提供对系统的只读访问权限,但在其中执行的文件夹除外.

The simplest part was the access to system resources. The program would simply be executed with limited access tokens. I combined some of the basic (Everyone, Anonymous, etc.) access tokens that are available to all processes in order to provide practically a read-only access to the system, with the exception of the folder it was executing in.

内存限制是通过作业对象完成的-它们允许指定最大内存限制.

The limitation of memory was done through job objects - they allow to specify maximum memory limit.

最后,为了限制执行时间并捕获所有异常,我的Limiter作为调试器附加到了进程中.因此,我可以监视它所花费的时间,并在花费太长时间的情况下终止它.请注意,我不能为此使用Job对象,因为它们仅报告作业的内核时间和用户时间.某个进程可能会执行类似Sleep(99999999)的操作,但这些操作都不计入其中,但仍会禁用测试计算机.因此,尽管我没有在最终执行时间中算出进程的空闲时间,但它仍然必须有一个限制.

And lastly, to limit execution time and catch all the exceptions, my Limiter attaches to the process as a debugger. Thus I can monitor the time it has spent and terminate it if it takes too long. Note, that I cannot use Job objects for this, because they only report Kernel Time and User Time for the job. A process might do something like Sleep(99999999) which would count in none of them, but still would disable the testing machine. Thus, although I don't count a processes idle time in its final execution time, it still has to have a limit.

现在,我不是这类低级专家.我花了几天时间阅读MSDN并在其中玩耍,并尽我所能提出了一个解决方案.不幸的是,它似乎运行不正常.在大多数情况下,它似乎都可以正常工作,但奇怪的情况一直在蔓延.刚才我有一个小的C ++程序,它可以在一秒钟内独立运行,但是我的Limiter报告了8秒的用户模式时间(从作业计数器中获取).这是代码.它将在大约半秒内打印输出,然后仅等待7秒以上即可:

Now, I'm no expert in low-level stuff like this. I spent a few days reading MSDN and playing around, and came up with a solution as best I could. Unfortunately it seems it's not running as well as it could be expected. For most part it seems to work fine, but weird cases keep creeping up. Just now I have a little C++ program which runs in a split second on its own, but my Limiter reports 8 seconds of User mode time (taken from job counters). Here's the code. It prints the output in about half a second and then spends more than 7 seconds just waiting:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector< vector<int> > dp(50000, vector<int>(4, -1));
    cout << dp.size();
}

限制器的代码很长,因此在这里不包括它.我也觉得我的方法可能有问题-也许我不应该做调试程序.也许有一些我不知道的常见陷阱.

The code of the limiter is pretty lengthy, so I'm not including it here. I also feel that there might be something wrong with my approach - perhaps I shouldn't do the debugger stuff. Perhaps there are some common pitfalls that I don't know of.

对于其他人如何解决此问题,我需要一些建议.也许已经有某种方法可以执行此操作,而我的限制器已过时了?

I would like some advice on how other people would tackle this problem. Perhaps there is already something that does this, and my Limiter is obsolete?


已添加:问题似乎出在我上面发布的小程序中.我为此打开了一个新问题,因为它有些无关.我仍然希望对这种限制程序的方法发表评论.


Added: The problem seems to be in the little program that I posted above. I've opened a new question for it, since it is somewhat unrelated. I'd still like comments on this approach for limiting a program.

推荐答案

在连接了调试器的情况下运行可以更改应用程序的特性.性能可能会受到影响,甚至代码路径也会发生变化(如果目标进程根据调试器的存在来执行操作,即

Running with a debugger attached can change the characteristics of the application. Performance can be impacted, and code paths can even change (if the target process does things based on the presence of a debugger, i.e. IsDebuggerPresent).

我们使用的另一种方法是将自己的应用程序配置为作为JIT调试器运行.通过设置AeDebug注册表项,您可以控制在应用程序崩溃时调用什么调试器.这样,您仅在目标进程崩溃时跳入,并且在正常运行时不会影响该进程.

A different approach that we've used is to configure our own application to run as the JIT debugger. By setting the AeDebug registry key, you can control what debugger is invoked when an application crashes. This way you only jump in when the target process crashes, and it doesn't impact the process during normal run-time.

此网站提供了有关设置事后调试程序的一些详细信息:配置自动调试.

This site has some details about setting the postmortem debugger: Configuring Automatic Debugging.

您用于限制内存,获取时间等的方法听起来都很好.

Your approaches for limiting the memory, getting timing etc. all sound perfectly fine.

这篇关于在受控环境(Win32)下运行应用程序的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆