子进程的内存使用情况?

6
我正在Ubuntu上运行一个类似于"C"的"沙盒":它接受程序并在用户"nobody"下安全运行(截获信号等)。此外,它分配内存和时间限制,并测量时间和内存使用情况。(如果你好奇的话,这是为了对测试数据上的程序进行标记的一种"在线评测机")

目前,我已经从mooshak中改编了"safeexec"模块。虽然大多数东西都工作正常,但内存使用似乎是一个问题。(它非常不准确)

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

"safeexec"程序似乎是这样工作的:

  1. fork()出子进程
  2. 在子进程中使用execv()运行所需程序
  3. 在父进程中监控子进程,直到子进程终止(使用wait4,它返回CPU使用情况,但不包括内存使用情况)
    因此,解析子进程的/proc/../stat文件(已被execv替换)

那么为什么/proc/child_pid/stat中的VM有时等于0?
是因为execv()完成得太快,导致/proc/child_pid/stat不可用吗?
如果是这样,是否有其他方法来获取子进程的内存使用情况?
(由于这是用于评估在时间限制下的程序,我不能承受像valgrind这样会影响性能的东西)

提前感谢。

3个回答

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

嗯,听起来很有趣。不过有没有办法跟踪静态/自动数组呢?

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

自动数组是个问题-我不确定如何处理它们。当调用内存分配代码时,可以查看正在使用多少堆栈(查看本地变量的地址)。但是不能保证在使用最大局部数组量的内存时将分配内存,因此它最多只提供了粗略的度量。

另一个想法:也许可以使用调试器技术-ptrace()系统调用-来控制子进程,特别是为了暂停足够长的时间以能够从/proc/...收集内存使用统计信息。


听起来很有趣。 有没有办法跟踪静态/自动数组呢? - v3.
哇,ptrace真的很棒。谢谢!(由于ptrace在执行execv()时会导致子进程暂停,因此我能够在它刚开始时测量内存使用情况) - v3.

2

在执行execve()之前,您可以设置硬资源限制(RLIMIT_AS资源的setrlimit)。程序将无法分配超过该内存量的内存。如果程序尝试这样做,内存分配调用(brk、mmap、mremap)将失败。如果程序未处理内存不足的情况,它将导致段错误,并反映在wait4返回的退出状态中。


我已经在做了 - 但我想知道它实际上使用了多少(以比较解决方案)。 - v3.

0
你可以使用sys/resources.h库中的getrusage(2)函数。
链接:https://linux.die.net/man/2/getrusage
该函数使用包含ru_maxrss字段的“rusage”结构,该字段存储有关当前进程所有子进程中最大的子内存使用情况的信息。
此函数还可以在所有子进程终止后从主进程中执行。
要获取信息,请尝试类似以下内容的代码:

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接