6

我在 Ubuntu 上用 C 语言运行一种“沙箱”:它需要一个程序,并在用户下安全地运行它nobody(并拦截信号等)。此外,它还分配内存和时间限制,并测量时间和内存使用情况。
(如果您很好奇,这是一种“在线法官”在测试数据上标记程序)

目前我已经从mooshak改编了safeexec模块。尽管大多数事情都可以正常工作,但内存使用似乎是个问题。(这是非常不准确的)

现在我已经尝试了这里的建议并从 中解析了 VM /proc/pid/stat,现在准确性问题已得到解决。但是,对于真正快速完成的程序,它不起作用,只会返回 0。

safeexec程序似乎是这样工作的

  1. fork()
  2. 在子进程中使用execv()以运行所需的程序
  3. 从父进程监视程序,直到子进程终止(使用wait4,这恰好返回 CPU 使用率 - 但不是内存?)
    因此它解析/proc/../stat子进程(已被 execv 替换)

那么为什么 VM in/proc/child_pid/stat有时等于 0?
是因为 execv() 完成得太快,而且/proc/child_pid/stat不可用吗?
如果是这样,是否有其他方法可以获取孩子的内存使用情况?
(因为这是为了在时间限制内判断程序,所以我不能承受像 valgrind 这样的性能损失)

提前致谢。

4

3 回答 3

3

您能否安排子进程使用您自己的malloc()et al 版本并记录 HWM 内存使用情况(可能使用注册的处理程序atexit())?也许您会使用 LD_PRELOAD 来加载您的内存管理库。这对巨大的静态数组或巨大的自动数组没有帮助。


嗯,听起来很有趣。不过,有什么方法可以跟踪静态/自动数组吗?

可以使用“size”命令分析静态内存——或多或少。

自动数组是个问题——我不确定你如何处理这些。您的内存分配代码可以查看调用时使用了多少堆栈(查看局部变量的地址)。但是不能保证在使用最大数量的本地数组时会分配内存,因此它充其量只是一个粗略的衡量标准。

另一种想法:也许你可以使用调试器技术——ptrace()系统调用——来控制子进程,特别是让它保持足够长的时间,以便能够从/proc/....

于 2009-04-13T14:07:54.623 回答
2

您可以在 execve() 之前设置硬资源限制(RLIMIT_AS 资源的 setrlimit)。该程序将无法分配超过该数量的内存。如果它尝试这样做,内存分配调用(brk、mmap、mremap)将失败。如果程序没有处理内存不足的情况,就会出现segfault,这会体现在wait4返回的退出状态中。

于 2009-04-13T14:09:43.387 回答
0

您可以使用 sys/resources.h 库中的 getrusage(2) 函数。
链接:https
: //linux.die.net/man/2/getrusage 此函数使用“rusage”结构,其中包含 ru_maxrss 字段,该字段存储有关当前所有子进程拥有的最大子内存使用量的信息。
在所有子进程终止后,也可以从主进程执行此功能。
要获取信息,请尝试以下操作:

struct rusage usage;
int a = getrusage(RUSAGE_CHILDREN, &usage);

但是有一个小技巧。
如果您想获得有关每个子进程内存使用情况的信息(不仅是最大的一个),您必须两次 fork() 您的程序(第一次 fork 允许您拥有独立的进程,第二个将是您想要测试的进程.

于 2018-03-25T18:30:15.570 回答