首先介绍一下这个项目:这是我的毕业设计,一个B/S系统,用于ACM/ICPC(国际大学生程序设计竞赛)的再线评测与竞赛。

附加说明: 该项目将作为遵循GPL协议的开源项目发布。

评测过程是这样的,选手通过浏览器登陆系统,阅读编程问题描述(这里所有问题都有标准输入和输出),然后编写代码,通过标单提交,在服务器端对选手的代码进行检查,然后编译运行,服务器要对选手的程序运行状态进行控制,主要控制这几项:
编译错误(Compile Error)
运行时错误(Runtime Error)
使用内存超出限制(Memory Limit Exceeded)
消耗CPU时间超出限制(Time Limit Exceeded)
程序输出的信息量超出限制(Output Limit Exceeded)

出现以上任何一项问题都要立即中止评测,并给出错误报告,反馈给选手。

如果编译运行成功,则对程序输出的信息进行检查,此时有以下情况
程序输出与期望的相同(Accepted)
程序输出与期望的不同(Wrong Answer)
程序输出格式有误(Presentation Error)

对于以上三种情况要分别给出信息,反馈给选手。

在比赛中,会有10道以内的编程题供选手解答。
对于比赛成绩的判定实行罚时记分制,即比赛开始时所有选手分数为0,然后依选手提交代码并得到(Accept)的时间来进行扣分,即选手提交代码越晚,扣分越多,同时如果提交代码后得到Accept以外的任何结果,都进行相应的扣分。
比赛结束后,先按选手解题数目,然后按罚时排序,同样的解题数,罚时越小越靠前。

以上为整个系统的功能概况。我把这个系统分为三个部分来完成:
1。评测程序
2。数据库
3。用户界面

评测程序在整个系统中的地位是非常重要的,而且也是难度最高的,所以我将这一个模块的实现放到了首要位置。

以下是试验阶段的部分代码,使用父进程对待运行的客户程序进行监视,用wait4()函数来监控并取得子进程的终止状态,子进程调用客户程序,并使用setrlimit来限制它。
这样已经可以判断出各种运行时错误,准确计算运行时间,唯一的问题是内存不好测量

#include <stdio.h>
#include
<sys/resource.h>
#include
<sys/time.h>
#include
<signal.h>
#include
<unistd.h>
#include
<stdlib.h>
#include
<sys/wait.h>
#include
<errno.h>

#define MEGA_BYTES 1048576

int main(int argc, char * argv[])
...{
pid_t pid
= vfork();
if( pid > 0)...{
struct rusage contest_usage;
int ret;
int contest_status;
do ...{
// non-block wait, so as to monitor the child proccess' status
ret = wait4(pid, &contest_status, WNOHANG, &contest_usage);
}
while(ret == 0);

if(WIFEXITED(contest_status))...{
puts(
"hooray!"); // the child process terminated normally
}

else if(WIFSIGNALED(contest_status))...{
printf(
"There might be some error! ");
int sig = WTERMSIG(contest_status);
printf(
"error id: %d ", sig);
if(sig == SIGXCPU)...{
puts(
"time limit exceeded");
}

if(sig == SIGXFSZ)...{
puts(
"output limit exceeded");
}

if(sig == SIGSEGV)...{
puts(
"runtime error");
}

if(sig==SIGKILL)...{
puts(
"memory limit exceeded");
}

}


// calculate the time used by contestant's process
double utime,stime,tmp;
utime
= contest_usage.ru_utime.tv_sec*1000.0 + contest_usage.ru_utime.tv_usec/1000.0;
stime
= contest_usage.ru_stime.tv_sec*1000.0 + contest_usage.ru_stime.tv_usec/1000.0;
printf(
"user time: %f ",utime);
printf(
"sys time: %f ",stime);
// how to count the memory cost of the process?
//
}

else ...{
struct rlimit limit;
// forbid the system to do core dump;
// getrlimit(PLIMIT_CORE, &limit);
limit.rlim_cur = 0;
setrlimit(RLIMIT_CORE,
&limit);
// set the limit on the child process's CPU time
getrlimit(RLIMIT_CPU, &limit);
limit.rlim_cur
= 3;
setrlimit(RLIMIT_CPU,
&limit);
// set the limit on the child process's memory
getrlimit(RLIMIT_AS, &limit);
limit.rlim_cur
= 128*MEGA_BYTES;
setrlimit(RLIMIT_AS,
&limit);
// set the limit on the Maximum size of file created by child process
getrlimit(RLIMIT_FSIZE, &limit);
limit.rlim_cur
= 1024; // currently set to 100K;
setrlimit(RLIMIT_FSIZE, &limit);

int exec_ret;
freopen(
"infile","r",stdin);
exec_ret
= execv("./contestant.out", argv);
// if it goes here, there must be something wrong
printf("an exception! error id: %d ", exec_ret);
}

}
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
昵称   密码   游客无需密码
网址   电邮   [注册]
               

验证码 不区分大小写