APP下载

源代码在线评测系统设计与实现

2012-06-09袁明磊付贤政

关键词:源代码评测子系统

袁明磊,付贤政

(安徽国防科技职业学院信息工程系,安徽 六安237011)

当前我校程序类课程的教学训练与考核方式仍然比较单一,主要采取人工评阅纸质源代码的模式。随着计算机技术的发展,传统的源代码评测方式越来越显出耗时、耗力、人为因素大等缺点。因此建立一套适合我校的源代码在线评测系统成为迫切的需求[1]。

1 研究源代码在线评测系统的意义

源代码在线评测系统可以作为高职学校程序设计类课程的辅助教学平台。源代码在线评测系统本身也是一个程序竞赛平台,该平台可以完成程序竞赛的实时评测。源代码在线评测系统还可以作为学生课余时间锻炼程序设计能力的一个平台,为学生提供一个提高程序设计能力的平台。源代码在线评测系统能根据程序运行计算出程序执行过程中所用的内存和时间。时间越短内存越少,说明程序设计越优秀。

2 源代码在线评测系统的模型

源代码在线评测系统分为Judge服务器(判题内核)、Web服务器和MySQL数据库服务器三部分。Judge服务可以监视数据库服务器中的待评测任务队列;Web服务器为用户提供了操作源代码在线评测系统的人机交互界面;Judge服务器和Web服务器共用MySQL数据库,MySQL数据库存储待评测任务队列和评测结果等信息。

源代码在线评测系统的工作过程如下:

(1)用户通过Web服务器提供的接口将待评测的源代码提交,之后 Web服务器将源代码加入MySQL数据库;

(2)Judge服务器定期读取 MySQL数据库中的待评测源代码,读取后就自动锁定该源代码,用来防止多个Judge服务器对源代码的重复读取;

(3)Judge服务器评测源代码并将评测结果存储到MySQL数据库内;

(4)Web服务器从MySQL数据库中读取并且显示源代码的评测结果。

源代码在线评测系统的服务器结构如图1所示,其中MySQL服务器、Web服务器、Judge服务器既可以由同一台服务器承担,也可以分别由不同的服务器承担。

图1 源代码在线评测系统服务器结构

3 源代码在线评测系统的设计

3.1 源代码在线评测系统的总体结构

源代码在线评测系统主要由:用户子系统、题目子系统、竞赛子系统、评测子系统4个模块组成。其中评测子系统部署在Judge服务器内,是系统工作的核心。用户子系统、题目子系统、竞赛子系统的数据部分部署在MySQL数据库服务器内,显示和逻辑控制部署在Web服务器中[2]。

系统总体结构如图2所示。

图2 系统总体结构

3.2 源代码在线评测系统数据库实体关系图设计

源代码在线评测系统中的主要实体有:用户(user)、管理员(administrator)、游客(guest)、题目(problem)、竞 赛 (contest)、测 试 代 码 (source_code)、解题状态(solution)、编译错误(compileinfo)和运行时错误(runtimeinfo)。为了更清楚地表示系统的原理,将评测服务也作为实体来看待。各个实体之间的关系如图3所示。

图3 源代码在线评测系统E-R图

3.3 评测模块流程设计

评测子系统的主要工作由myoj_client实现。myoj_client工作流程如图4所示。

工作过程如下:

(1)读取配置文件“./init/judge.conf”,从配置文件中获取评测子系统全局变量的值;

(2)利用 MySQL提供的接口函数,实现对MySQL数据库的连接;

(3)利用 MySQL提供的接口函数,获取MySQL数据库中待评测源代码的信息;

(4)将待评测的源代码,存储到run文件夹下,文件名为main.c;

(5)将输出文件重定向至“./run/ce.txt”;

(6)执行编译;

(7)编译失败,则将编译错误(Compile Error)存储到数据库,跳转至第(19)步;

(8)编译成功,则会生成可执行文件,名为main;

(9)记录当前时间time1;

(10)读取题号对应的测试数据文件中的一对的输入文 件 和 输 出 文 件;eg:./date/1000/1.in 与./date/1000/1.out相对应。

(11)如果读取文件成功,则将输入输出文件分别存储到run文件夹内,存储为data.in和data.out。

(12)如果读取文件失败,记录当前时间time2,并将测试成功(Accepted)存储到数据库,将time2-time1存储到数据库中,作为程序运行时间,跳转至第(19)步;

(13)重定向输入文件为data.in,重定向输出文件为user.out;

(14)执行main程序;

(15)超时,则将超时间限制(Time Limit Exceed)运行结果存储到数据库;跳转至第(19)步;

(16)超内存,则将超内存限制(Memory Limit Exceed)运行结果存储到数据库;跳转至第(19)步;

(17)比较user.out文件和data.out文件,如果完全匹配则跳转至第(10)步;

(18)如果user.out文件和data.out文件有区别,则存储(Wrong Answer)到数据库,跳转至第(19)步;

(19)本次源代码评测结束。

评测功能模块应能给出以下4种类型的反馈信息并存入数据库:

编译错误:源代码无法通过编译。

运行时错误信息:用户程序运行时出现异常 ,如超内存,超时间等。

结果正确:用户程序能准确地通过所有测试用例且其他指标均符合要求。

结果错误:用户程序没能得到正确运行结果。

4 源代码在线评测系统实现时用到的关键技术

4.1 采用C语言操作MySQL数据库

评测模块主要通过C语言提供的接口实现对MySQL数据库的操作。用到的API主要有:

MYSQL*mysql_init(MYSQL*mysql),用来实现初始化一个MySQL对象。

MYSQL*mysql_connect(MYSQL*mysql,const char*host,const char*user,const char*passwd),用来实现连接数据库。

int mysql_query(MYSQL*mysql,const char*query),实现对SQL语句的执行操作。

4.2 编译源代码

对源代码文件进行编译。实现对源代码文件进行编译的核心代码如下:

编译的参数主要有:-o out_file,-O2,-Wall,-lm,--static,-std=c99,-DONLINE_JUDGE。 分 别具有如下含义:

编译结果判断。通过测试编译时输出文件的大小来确定编译是否通过。当编译输出文件大小大于0时,说明在编译时有警告或错误信息。当编译输出文件等于0时,说明编译通过。

4.3 执行被测试程序

源代码文件编译通过之后,会生成一个名为“main”的文件。接下来的工作是测试程序的正确性。源代码在线评测系统采用的是黑盒测试。

执行被测试程序的过程如下:

(1)重定向输入输出文件。

在执行被测试程序时,需要先去读取程序的标准输入文件。因此在执行被测试程序之前需要将输入文件重定向到提前准备好的标准输入数据,将输出数据重定向到用户工作目录内。实现的关键代码如下:

(2)创建一个子进程。

利用fork()函数生成一个子进程。被测试程序的整个运行过程都是在子进程内完成的。

(3)设置资源限制。

运行程序之前需要设置运行时的限制资源,包括内存和CPU时间等限制。资源限制采用struct rlimit实现。struct rlimit结构如下

结构体中rlim_cur是要取得或设置的资源软限制的值,rlim_max是硬限制的值。

(4)用函数调用要执行的程序。

执行被测试程序使用Execl()实现。

Execl()可以执行第一个参数path字符串所代表的文件,接下来的参数代表执行该文件时传递的参数argv[0],argv[1].....最后一个参数必须用空指针NULL结束。使用该函数时需要的头文件为:#include<unistd.h>。

4.4 测试运行结果

测试程序运行结果的基本思想如下:利用标准输入文件作为待评测程序的输入文件,将待评测程序的输出结果和标准输出结果进行比较。如果所有测试用例的程序输出和标准输出均一致,则认为待评测程序正确,否则认为被评测程序有错误。在测试过程中还需要监视内存和时间是否超限,如果超限则返回相应的错误代码。

在测试运行结果之前和之后分别对系统时间进行获取,两者时间差即为评测时间。

测试运行结果的核心代码如下所示:

(1)定义全局目录、标准输入、输出文件的名字和用户程序输出文件名。下面为具体的程序代码:

(2)判断标准输入文件是否存在。下面为具体的程序代码:

(3)以标准输入和标准输出为依据,测试源代码程序的正确性。其中prepare_files()函数实现将标准输入和标准输出文件复制到run文件夹下。run_solution()函数运行在子进程中,用来执行程序并判断程序输出结果和标准答案之间的关系,同时负责监视程序的运行状态,并可以将程序运行状态返回,以供父进程捕获。watch_solution()函数运行在父进程中。用来获取run_solution()函数的返回值,返回值代表程序的测试结果。下面为具体的程序代码:

为防止非法用户的反复提交,数据库记录每次用户提交的时间,限制用户最快提交速度是1min提交一次程序。

4.5 评测时间的获取

测试时间获取是以s为单位的,获取评判时间的精度为ms级。主要用到了结构体timeval和gettimeofday()函数。评判时间获取的方法如下:

4.6 将评测结果存入数据库

程序测试完成之后,需要将测试的结果保存到数据库。同时更新和题目相关的数据表。需要更新的数据表有:problem表、solution表和user表。

更新数据库信息需要利用C语言来操作MySQL数据库来实现。

下面以存储测试结果为例,说明如何利用C语言将测试结果存入数据库:

5 系统运行截图

下面是源代码在线评测系统的运行截图,图5是用户提交源代码的界面。图6是源代码在线评测系统的评测结果界面。

图5 提交题目源代码界面(正确源代码)

图6 源代码测试状态界面

6 结语

本文首先介绍了系统的意义,接着阐述了系统的模型。本文重点介绍了源代码在线评测系统的设计和实现技术,最后给出了系统的运行截图。实践表明,该系统能极大地提高程序测试的效率,提高学生的学习兴趣,是一个很好的教学平台。

[1]梁嵩,王建新,盛羽.在线程序语言评测系统的设计与实现[J].计算技术与自动化,2010,6(2):128-132.

[2]王腾,姚丹霖.计算机应用与软件[J].计算机应用与软件,2006,12:129-130.

猜你喜欢

源代码评测子系统
不对中转子系统耦合动力学特性研究
基于TXL的源代码插桩技术研究
次时代主机微软XSX全方位评测(下)
次时代主机微软XSX全方位评测(上)
GSM-R基站子系统同步方案研究
攻坡新利器,TOKEN VENTOUS评测
驼峰测长设备在线监测子系统的设计与应用
软件源代码非公知性司法鉴定方法探析
基于语法和语义结合的源代码精确搜索方法
Canyon Ultimate CF SLX 8.0 DI2评测