我正在Ubuntu的C中运行一种“沙盒”:它需要一个程序,并在用户nobody
下安全地运行它(并拦截信号等)。此外,它还分配内存和时间限制,并测量时间和内存使用情况
(如果你很好奇,那就是某种“在线评判”来标记测试数据上的程序)
目前我已经从mooshak改编了 safeexec 模块。虽然大多数东西都能正常工作,但内存使用似乎是一个问题。 (这是非常不准确的)
现在我尝试了here建议,并从/proc/pid/stat
解析了VM,现在修复了准确性问题。但是,对于快速完成的程序,它不起作用,只返回0。
safeexec 程序似乎是这样的:
fork()
s execv()
来运行所需的程序wait4
,这恰好返回CPU使用率 - 而不是内存?)/proc/../stat
(已被execv替换)那么为什么/proc/child_pid/stat
中的VM有时等于0?
是因为execv()完成得太快,而/proc/child_pid/stat
只是不可用?
如果是这样,是否有某种其他方式来获取孩子的内存使用情况?
(因为这是为了在一个时间限制内判断程序,我买不起像valgrind这样的性能损失的东西)
提前致谢。
答案 0 :(得分:3)
您是否可以安排子进程使用您自己的malloc()
等版本并记录HWM内存使用情况(可能使用注册了atexit()
的处理程序)?也许您使用LD_PRELOAD来加载内存管理库。这对巨大的静态数组或巨大的自动数组没有帮助。
嗯,听起来很有趣。有什么方法可以跟踪静态/自动数组吗?
可以使用'size'命令分析静态内存 - 或多或少。
自动数组是一个问题 - 我不知道你如何处理这些问题。您的内存分配代码可以查看调用时正在使用的堆栈数量(查看本地变量的地址)。但是,当使用最大量的本地阵列时,无法保证将分配内存,因此它最多只能提供粗略的度量。
另一个想法:也许您可以使用调试器技术 - ptrace()
系统调用 - 来控制子进程,特别是将其保持足够长的时间以便能够从中收集内存使用情况统计信息/proc/...
。
答案 1 :(得分:2)
您可以在execve()之前设置硬资源限制(RLIMIT_AS资源的setrlimit)。该程序将无法分配超过该数量的内存。如果它试图这样做,内存分配调用(brk,mmap,mremap)将失败。如果程序没有处理内存不足的情况,它将会发生段错误,这将反映在wait4返回的退出状态中。
答案 2 :(得分: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允许你有独立的进程,第二个将是你喜欢的进程)测试。