book
归档: Linux 
flag

评测机需要什么呢?

  • 基本的ACWARE
  • 高级一点的TLEMLE
  • 更加先进的沙箱
  • 超先进的CTLECMLE
  • 更具有实用价值的SPJtestlib交互器

以上全部实现的judger大概掰着指头都可以数过来,LOJ,UOJ,Codeforces, etc…

自己写评测机!

以下文字只适用于linux

ulimit

可能出于多种原因,比如自己出题,20+组数据自己一个一个验非常繁琐,等等。

我和kZIme写了OALJ,由于刚开始写的时候,我和kZime都非常naive,写出来的是一个只能判断答案正确与否的东西。后来,我了解到了一条叫做ulimit的命令,可以用来限制进程的最大运行时间/内存。

于是就通过py脚本执行这个操作,通过判断程序的返回值来确定运行状态,通过diff来判断答案是否正确。

缺点就是无法获取内存的多少。

fork-exec

后来我又学习了一个,了解了linux的进程机制。

在此之前,首先说一下一个虚拟地址空间

虚拟地址空间

在早期的Windows中,常常会出现一个程序跑飞,把其他程序也干掉,顺手蓝屏的操作。或者是神仙打架,大家一起gg。出现这些情况的原因在于早期的Windows中,程序可以直接操作到物理内存,如果出现了越界等操作,有时甚至会跨越到别的程序的内存里去。为了解决这个问题,操作系统为应用程序提供了“全世界的内存都是我的”的假象,即虚拟地址空间。

在操作系统提供的抽象中,每个程序享有独占的内存空间(好棒的感觉),如果你瞎搞,就会立刻已Segment fault崩溃掉,而不会去祸害他人。

fork

fork是一个系统函数,可以将当前进程“复制”一份一模一样的,不过奇妙的是,由于调用fork会出现两个一模一样的进程,新进程是旧进程的孩儿,fork会返回两次,一次是在调用方,返回新进程的pid,另一次是在新进程,返回0,以告诉它“你是旧进程的孩儿”。

注意fork调用后,新旧进程使用不同的虚拟地址空间,所以他们互不影响。

exec

exec也是一个系统函数,可以将当前进程替换成要执行的进程,以前进程的信息将被完全抹去(莫名中二)。


所以,说了这么多,有什么用呢?

我们可以在评测的时候将评测机自身fork一下,让新进程exec成待评测程序。

然后旧进程作为新进程的爸爸,自然可以为所欲为,监测内存啥的不在话下,如果超时/超内存就一个SIGKILL甩他脸上。

嗯。。待续。。

navigate_before navigate_next