✏️ 前言
我还是一直坚持在线判题类项目的,原因是发现其实这个话题可以比较好的帮助我去走进很多技术的生态。
判题服务的核心:判题机是一个相对接近系统的课题,由于系统需要允许用户在服务端执行代码,判题机也就成为了服务端最容易出问题的地方。
不让它出问题的方式也很简单,那就是给允许在判题机当中的代码提供一个“沙箱”,简而言之就是给代码提供一个较为接近原生系统的环境,但是限制它进行一些危险操作。
为什么会有judger-rs
去年我在做SHUpdtp的后端的时候,判题机我是没有自己写的,用的是QingdaoU/Judger,通过docker进行部署。
起初我开始做judger-rs的时候纯粹是为了找事,因为平时也没什么机会自己写Rust。
后来看了一圈以后发现用国内开源的判题机在GitHub上基本就青岛的一个,很多系统都是拷贝过来直接用的,青岛判题机本身也有一定的年代了。
并且docker部署判题机的方式是比较智障的行为,docker本身也是个类似沙箱的东西,沙箱套沙箱其实是完全没有必要的。我在网上看到一个之前也写判题机的博客,哥们最后直接不写了,docker一把梭,发现之前一切都白干了。
我个人不喜欢docker的原因还是在于它真的会让有些东西变得很慢,判题机如果能脱离docker部署就意味着它能在高压环境下进行更多的判题任务。
并不是说青岛的判题机不能脱离docker部署,只是在脱离docker之后,判题机是需要健壮性的。
所以正好和Rust的特点碰撞了,而且Rust适合做工程化,有利于项目管理,因此就打算在青岛的基础上,先用Rust做改写,然后在逐步更新新的功能。
📕 实现
模块
目前拟定要做的模块有core
和server
两块,core
是沙箱本体,server
主要解决多机器部署的问题。
这两部分在青岛版当中分别使用C和Python写的,用Rust改写以后可以优化整体的工程结构,并提高服务的性能。
我一直在很墨迹地写core
,server
要等core
做好了以后才会碰。
Core
流程
我整理了第一版流程的流程图,展示了沙箱的大致工作方式。
主要的角色有两个:Monitor
和Runner
。
**Monitor**
主要负责应对子进程出现死循环需要强制关停的情况,并且通过**wait4**
来等待进程结束、收集进程资源的使用情况**Runner**
主要负责正确启动被判题进程,通过**setrlimit**``**seccomp**
等方式为将启动的被判题进程设限进度
目前我已经大致的做出了这套流程的框架,其中wait4``collect result``set I/O``set time & mem limit
等部分还没怎么写(要么是写了一句、要么就是根本没写)。
不过框架定了,剩下的基本也就是代码填空了,比较难理的是这些调用哪些放在**Monitor**
里,哪些放在**Runner**
里。
框架的建立也就意味着,judger-rs正式进入了一个可以接受外部PR的阶段了。❤️️ 写在最后
找到此项目请访问judger-rs,欢迎各位来试用或者提PR!
你可以在README当中找到更多内容,比如Discord圈子,以及如何免安装参与贡献。