Golang Go语言中如何实现一个 OJ 的评测机?

Golang Go语言中如何实现一个 OJ 的评测机?

在做一个 OJ 系统的评测机,需要做一个容器隔离用户程序,并且监控程序使用到的内存大小和时间

别人推荐使用 cgroup 以及 clone 、ubshare 的系统调用,可是找不到相关资料

大家有什么方法推荐吗?

16 回复

我有一个方法。。。上 github 借鉴借鉴。。。

更多关于Golang Go语言中如何实现一个 OJ 的评测机?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


uoj 的做法好像是 docker

做的第一个项目就是和同学一起搞了个 oj,评测机直接拉一个 docker 起来跑完删掉。。。我记得这个方案的缺陷是无法区分内存爆掉和超时的情况?

代码完全读不懂

那也得硬读。。。我想应该不会有资料一步一步教怎么做一个评测机

去搜搜本科论文库,有不少 CS 的哥们本科毕业设计做的这个

以前的一个面试官写的,并且用在他们学校的校赛上了,你可以参考一下,整体不难,一个调度中心,一堆 worker https://github.com/ma6174/acmjudger

如果想了解一下简单的判题原理的话可以看看我的博客文章 https://www.lanrongqi.com/2020/08/online-judge-development-2 ,这个是我自己用的 go 写的判题机 https://github.com/LanceLRQ/deer-executor , 不过没有实现沙箱功能,生产环境是直接放 docker 里跑的。也没用到 cgroup 那些,在学了在学了…╮( ̄▽ ̄)╭
顺便给你个我虽然没用过但是看源代码感觉还蛮厉害的 go 语言判题机 https://github.com/criyle/go-judge
一起学习交流呀

考虑下用 Docker 吧,如果有人乱搞得考虑 OJ 被黑掉的场合

#3 +1

单纯的 docker 不一定安全,gvisor 应该更靠谱些。
印象还有超轻虚拟机+docker 方案。

就是这个源码我看不懂,配上作者的博客也无法理解

非主流方法:如果评测机用的是 Ubuntu 等自带 AppArmor 的系统的话,倒是可以不用容器,通过 AppArmor 来实现安全加固。

内存和时间限制,一般来说是联用轮询和 rlimit 系统资源限制:
1 )定时器限制时间+轮询采样内存消耗情况作为主要监控手段,用于反馈 TLE/MLE
2 ) rlimit 系统限制设得比题面描述高一些,用来保底
(不单用 rlimit 是因为超限程序会被直接杀死,从而无法区分 RE, TLE 和 MLE ;而且无法限制程序的非用户态时间)

另外,安全方面还有 ptrace, seccomp 等传统方法。

嗯,我再试试

在Golang中实现一个OJ(在线评测系统)的评测机,主要涉及到以下几个关键步骤:

  1. 输入/输出处理: 评测机需要能读取用户提交的代码的输入,并将代码的输出与预期结果进行比较。可以使用标准输入/输出来实现,例如通过os/exec包执行代码并捕获其输出。

  2. 沙箱执行: 为了防止恶意代码对系统造成危害,需要在沙箱环境中执行用户代码。可以使用容器技术(如Docker)或操作系统级别的权限隔离来实现。

  3. 时间/内存限制: 评测机需要能够监控并限制代码执行的时间和内存使用。可以使用context包来设置执行超时,并通过监控进程的资源使用情况来实现内存限制。

  4. 编译与执行: 根据提交的代码语言,调用相应的编译器或解释器进行编译和执行。例如,对于Go语言代码,可以直接使用go run命令。

  5. 结果判定: 将用户代码的输出与预期结果进行比较,判定其正确性。可以使用字符串匹配、正则表达式或专门的比较函数来实现。

  6. 日志与错误处理: 记录代码执行过程中的日志和错误信息,以便在代码执行失败时进行调试和分析。

综上所述,实现一个OJ评测机需要综合考虑输入/输出处理、沙箱执行、时间/内存限制、编译与执行、结果判定以及日志与错误处理等多个方面。通过合理的设计和实现,可以确保评测机的安全性和准确性。

回到顶部