二つの部分で受刑質問
デーモンでサービスプロセス、dと判断1.。データベース、抽出宣告質問キューのポーリングを担当。ときに新しい仕事を見つけるjudge_client生成するプロセス。
2.judge_clientプロセスは、実際の結果を決定するために、パフォーマンス指標を収集し、番組タイトルを宣告動作環境を準備する責任がある、データ、ターゲットプログラムを実行し、システムコールを監視しています。
判断プロセス
初期化:
1. pid_judged子プロセスを作成し、セッションのプロセスを主導するように設定されている(のumask(0)、クローズ(0〜2))
2.現在の作業ディレクトリを変更する「/ホーム/裁判官」
3.「が/home/judge/etc/judge.pid」ファイルに書き込まれ、その後、書き込みロックをpid_judged(サービスの実行の過程で、既にあるかどうかを確認するために使用されます)
4.設定SIGQUIT、SIGKILL、機能call_for_exitエンドサービスプロセスの実行をトリガするためにSIGTERM
ポーリング:
データベースへの接続(host_nameに、USER_NAME、パスワード、DB_NAME、port_number)を指定
6.Polledソリューションデータベーステーブル、ユーザーがスローされた評価タスクキューを提出していません
キュー「サブ・タイトル・プロセス」(子プロセス)をタスク、および「評価中」としてタスクをマークするタスクから抽出7.
RLIMIT構造はsetrlimitを(使用してファイルやバイト)の8.最大数は、プロセスの最大数(200)と、設定「サブ・タイトル・プロセスは、」最大CPU時間は、あなたが利用可能なメモリの最大バイト数を作成することができますことができます
9. EXECL通話機能実行の/ usr / binに/ judge_client、およびタスクIDにパラメータを渡す、judge_client_id
Judge_clientプロセス
初期化:
1.作業ディレクトリは/ home /裁判官を設定します。
2.タスクIDを取得し、judge_client_id
3. Connectデータベース
4. = WORKDIRする作業ディレクトリを設定し、「実行/ /ホーム/裁判官の?」
ファイルシステムにリンクされている解決策:WORKDIR / procが、WORKDIR /下のすべてのファイルとディレクトリを削除します
コンパイルします。
6.ユーザID、言語タイプタイトルIDを取得するデータベースを照会
7.指定された最大アップタイムtime_lmtを得るために、データベースを照会する権利、最大メモリmem_lmt
8.查询数据库获取用户提交的代码并写入Main.cc文件
9.创建子进程使用execvp函数执行g++命令编译Main.cc文件,并将编译信息写入ce.txt文件中
10.父进程调用waitpid函数来等待子进程编译结束,通过查看ce.txt文件来判断是否为编译错误,若为编译错误则退出
提取输入输出数据
11.在/home/judge/data/获取题目输入数据文件并保存路径为infile
12.将题目输入数据拷贝到workdir/data.in文件
13.获取题目输出数据文件并保存路径为outfile,创建user.out文件并保存路径为userfile
运行目标程序:
14.创建子进程pidApp,重定向输入输出流,从data.in读入数据,运行结果写入user.out,运行错误信息写入error.out
15.使用ptrace(PTRACE_TRACEME, 0, NULL, NULL)函数来使父进程跟踪自己
16.设置工作目录workdir为根目录(chroot()),提高系统安全性
17.使用rlimit结构体设置进程的CPU运行时间,可以创建最大文件字节数,可拥有最大进程数(1),拥有的堆栈数,可用内存数
18.alarm()设置定时器
19.调用execl使进程执行Main文件(目标程序)
监控目标程序:
20.父进程调用wait4(pidApp,&status,0,&ruse)来获取子进程暂停或中止时的返回状态和查看进程的使用资源情况
21.查看workdir/pro/pidApp/status里的VmPeak:属性的值,这个值是进程使用的最大内存数,如果超出限制,则ptrace(PTRACE_KILL,pidApp,NULL,NULL);退出监控
22.调用WIFEXITED(status)判断子进程是否正常结束
23.查看error.out文件,如果有内容则为运行错误,KILL掉子进程,监控结束
24.如果userfile的size > outfile的size*2,则为结果超出限制,kill掉子进程,监控结束
25.exitcode=WEXITSTATUS(status)获取子进程exit()返回的结束代码,如果为0或5则为正常,否则为异常结束,根据信号的类别给出相应错误,比如SIGALRM为计时器时间到了信号,SIGXCPU为运行时间到了信号,SIGXFSZ为输出文件大小超出信号等等
26.调用WIFSIGNALED(status)检查是否为异常结束(子进程通过信号结束)
27.调用sig=WTERMSIG(status)取得使子进程结束的信号编号,根据sig的类别给出相应的错误
28.调用ptrace(PTRACE_GETREGS,pidApp,NULL,®)来取得进程的寄存器信息(reg.REG_SYSCALL),检查系统调用函数的使用情况,若为禁止的系统调用函数则KILL掉子进程并将运行错误写入结果AC_status,结束监控
29.调用ptrace(PTRACE_SYSCALL,pidApp,NULL,NULL)使子进程继续执行
30.在监控结束以后统计usedtime+=ruse.ru_utime(用户使用时间)+ruse.ru_stime(系统使用时间)
31.根据AC_status的值更新数据库
感谢hustoj开源代码及作者!
---------------------
作者:cq_phqg
来源:CSDN
原文:https://blog.csdn.net/cq_phqg/article/details/46428987
版权声明:本文为博主原创文章,转载请附上博文链接!