HUST JudgeOnline 开发日记 1
来源:互联网 发布:如何搭建云计算平台 编辑:程序博客网 时间:2024/05/16 03:02
首先介绍一下这个项目:这是我的毕业设计,一个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来限制它。
这样已经可以判断出各种运行时错误,准确计算运行时间,唯一的问题是内存不好测量
附加说明: 该项目将作为遵循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);
}
}
#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);
}
}
- HUST JudgeOnline 开发日记 1
- HUST JudgeOnline 开发日记 2
- HUST JudgeOnline 开发日记 3
- JudgeOnline
- Wcf 开发日记 1
- 开发日记1
- MAS开发日记 -1
- MEAN_fullstack 开发日记(1)
- <开发日记1> 准备
- HUST
- HUST
- HUST
- HUST
- pushlets技术-开发日记1
- Capistrano开发日记(1)
- vc数据库开发日记1
- Qt项目开发日记1
- WEBjava开发日记(1)
- ERROR: Unknown command 'crunch' 解决方法
- Java沙箱的实现
- tomcat 6无法安装的解决办法
- 计算1~n之和
- ios数据存储
- HUST JudgeOnline 开发日记 1
- HDU 4512
- 一个人的战斗
- uestc oj 1796 Flash Mob
- 六个可以让你变得更强大的残酷事实
- HUST JudgeOnline 开发日记 2
- HUST JudgeOnline 开发日记 3
- 如何设置Java桌面程序界面外观(How to Set the Look and Feel)
- C#中编制装逼小软件的一些技巧