发布时间:2026/8/14 15:12:46
负载均衡式在线OJ---------第二幕 个人主页:小则又沐风个人专栏:数据结构竞赛专栏C语言CLinuxOJ项目目录前言代码与运行模块代码思路管理资源分配上限合并代码(编译和运行--引入json库)删除临时文件前言我们目前的项目知识简单的实现了代码的编译的功能,显而易见的是我们还需要代码的运行的功能.今天我们的任务就是来实现一下项目中的代码运行的模块代码与运行模块在实现这个模块之前我们需要建立起来一个共识:首先我们将用户提交的代码运行我们关心的是什么???我们这个模块并不是关心用户的代码运行是否正确.我们关心的是用户的代码是否能够运行起来.所以我们关心的就是代码运行的错误或者是正常.至于代码运行的结果是否正确就是项目的另外的模块了.(需要对运行结果和我们提供的测试用例进行比对)在确定我们运行模块的主要任务之后我们现在来编写一下我们的代码代码思路我们实现这个模块的思路还是通过创建子进程进行进程替换来完成的.代码运行的我们需要知道的是代码运行的输出结果是什么,需要知道如果代码运行出错的话错误的原因是什么.当然成熟的项目也需要提供给用户一个自测的功能.也就是需要提供一个输入的接口所以我们需要产生三个文件#pragma once #include iostream #include string #include stdio.h #include unistd.h #include fcntl.h #include unistd.h #include sys/stat.h #include sys/wait.h #include ../comm/util.hpp #include ../comm/Log.hpp using namespace LogMoudle; using namespace util; class ns_run { public: ns_run() { } ~ns_run() { } public: static int Run(const std::string file_name) { std::string std_in PathUtil::StdIn(file_name); std::string std_out PathUtil::StdOut(file_name); std::string std_error PathUtil::StdError(file_name); std::string _excute PathUtil::Exe(file_name); umask(0); int std_infd open(std_in.c_str(), O_CREAT | O_RDONLY, 0644); int std_outfd open(std_out.c_str(), O_CREAT | O_WRONLY, 0644); int std_errorfd open(std_error.c_str(), O_CREAT | O_WRONLY, 0644); int fd fork(); if (fd 0) { LOG(LogLevel::ERROR) fork error; close(std_infd); close(std_outfd); close(std_errorfd); return -1; } else if (fd 0) { dup2(std_infd, 0); dup2(std_outfd, 1); dup2(std_errorfd, 2); execl(_excute.c_str(), _excute.c_str(), nullptr); LOG(LogLevel::ERROR) execl error; exit(1); } else { int status; close(std_infd); close(std_outfd); close(std_errorfd); waitpid(fd, status, 0); LOG(LogLevel::INFO) 运行完毕 : (status 0x7F); return status 0x7f; } } };现在我们来测试一下我们的代码#includeiostream using namespace std; int main() { couthelloendl; return 0; }#include compile.hpp #includerun.hpp int main() { Compile::my_compile(code); int nns_run::Run(code); return 0; }管理资源分配上限现在我们的代码是可以做到对用户提供的代码进行编译和运行的,但是现在有一个问题就是如果有恶意的代码想要占用我们cpu的资源的代码我们的程序也会运行这个代码.在我们使用成熟的OJ的时候我们会遇到代码超时和内存超出的问题,我们也需要类似的机制来保护我们的程序,所以我们需要对用户的代码进行时间和内存分配进行限制static void SetProcLimit(int _cpu_limit, int _mem_limit) { // cpu 限制 struct rlimit cpu_rlimit; cpu_rlimit.rlim_cur _cpu_limit; cpu_rlimit.rlim_max RLIM_INFINITY; setrlimit(RLIMIT_CPU, cpu_rlimit); // 内存限制单位是kb struct rlimit mem_rlimit; mem_rlimit.rlim_max RLIM_INFINITY; mem_rlimit.rlim_cur _mem_limit * 1024; setrlimit(RLIMIT_AS, mem_rlimit); } static int Run(const std::string file_name, int _cpu_limit, int _mem_limit) { std::string std_in PathUtil::StdIn(file_name); std::string std_out PathUtil::StdOut(file_name); std::string std_error PathUtil::StdError(file_name); std::string _excute PathUtil::Exe(file_name); umask(0); int std_infd open(std_in.c_str(), O_CREAT | O_RDONLY, 0644); int std_outfd open(std_out.c_str(), O_CREAT | O_WRONLY, 0644); int std_errorfd open(std_error.c_str(), O_CREAT | O_WRONLY, 0644); int fd fork(); if (fd 0) { LOG(LogLevel::ERROR) fork error; close(std_infd); close(std_outfd); close(std_errorfd); return -1; } else if (fd 0) { dup2(std_infd, 0); dup2(std_outfd, 1); dup2(std_errorfd, 2); SetProcLimit(_cpu_limit, _mem_limit); execl(_excute.c_str(), _excute.c_str(), nullptr); LOG(LogLevel::ERROR) execl error; exit(1); } else { int status; close(std_infd); close(std_outfd); close(std_errorfd); waitpid(fd, status, 0); LOG(LogLevel::INFO) 运行完毕 : (status 0x7F); return status 0x7f; } }下面我们来介绍一个库,这个库中的方法可以帮助我们轻松实现序列化和反序列化这个库怎么使用呢?我来演示一下#include compile.hpp #include jsoncpp/json/json.h #includerun.hpp int main() { // Compile::my_compile(code); // //int nns_run::Run(code); Json::Value in_value; in_value[code]zhangsan; in_value[age]18; Json::StyledWriter writer; std::string outwriter.write(in_value); std::coutout; Json::Value out_value; Json::Reader read; read.parse(out,out_value); std::string codeout_value[code].asCString(); int ageout_value[age].asInt(); std::coutcode\nagestd::endl; return 0; }具体上是怎么使用的呢?首先我们需要定义出一个Json::value假设我们需要进行序列化,我们就将我们需要序列话的数据进行填写然后定义出一个 Json::StyledWriter 对象将我们的value值写入到字符串中读取的话就是类似的步骤,首先定义出一个value对象和一个Reader对象,调用相关的读函数将我们需要读的json字符串读取到我们的value中然后读取value中的数据合并代码(编译和运行--引入json库)#include jsoncpp/json/json.h #include run.hpp #include compile.hpp #include ../comm/util.hpp #include ../comm/Log.hpp using namespace LogMoudle; using namespace util; class com_run { public: com_run() { } ~com_run() { } public: static std::string StuToCode(int stu_code, const std::string file_name) { std::string out; switch (stu_code) { case 0: out 编译运行成功; break; case -1: out 代码为空; break; case -2: out 未知错误; break; case -3: FileUtil::ReadFile(file_name, out, true); break; case SIGABRT: out 内存超出限制; break; case SIGXCPU: out cpu运行时间超限; break; case SIGFPE: out 浮点数溢出; break; default: break; } return out; } // code // input // cpulimit // memlimit static void Start(const std::string in_json, std::string *out_json) { Json::Value in_value; Json::Reader read; read.parse(in_json, in_value); std::string code in_value[code].asCString(); std::string input in_value[input].asCString(); int cpulimit in_value[cpulimt].asInt(); int memlimit in_value[memlimt].asInt(); int stu_code 0; int run_code 0; std::string file_name; Json::Value out_value; if (code.size() 0) { // 代码为空 stu_code -1; goto END; } file_name FileUtil::MakeUniqueFileName(); if (!FileUtil::WriteFile(PathUtil::Src(file_name), code)) { stu_code -2; // 未知错误 goto END; } if (!Compile::my_compile(file_name)) { stu_code -3; // 编译错误 goto END; } run_code ns_run::Run(file_name, cpulimit, memlimit); if (run_code 0) { stu_code -2; goto END; } else if (run_code 0) { stu_code run_code; goto END; } else { stu_code 0; } END: out_value[stu] stu_code; out_value[reason] StuToCode(stu_code, file_name); if (stu_code 0) { std::string out_put; FileUtil::ReadFile(PathUtil::StdOut(file_name), out_put, true); out_value[output] out_put; std::string _stderror; FileUtil::ReadFile(PathUtil::StdError(file_name), _stderror, true); out_value[stderror] _stderror; } Json::StyledWriter writer; *out_jsonwriter.write(out_value); } };现在我们的代码完成了合并的工作现在我们就可以对传来的json串进行编译和运行了,但是我们每次工作都会生成许许多多的临时文件,我们需要在工作的收尾部分对这些产生的临时文件进行删除删除临时文件static void RvTempFile(const std::string file_name) { std::string SRCPathUtil::Src(file_name); if(FileUtil::IsFileExists(SRC)) { unlink(SRC.c_str()); } std::string STDERRORPathUtil::StdError(file_name); if(FileUtil::IsFileExists(STDERROR)) { unlink(STDERROR.c_str()); } std::string _compile_errorPathUtil::CompilerError(file_name); if(FileUtil::IsFileExists(_compile_error)) { unlink(_compile_error.c_str()); } std::string _exePathUtil::Exe(file_name); if(FileUtil::IsFileExists(_exe)) { unlink(_exe.c_str()); } std::string _stdinPathUtil::StdIn(file_name); if(FileUtil::IsFileExists(_stdin)) { unlink(_stdin.c_str()); } std::string _stdoutPathUtil::StdOut(file_name); if(FileUtil::IsFileExists(_stdout)) { unlink(_stdout.c_str()); } }现在我们的项目中的编译和运行的模块基本完成

相关新闻

2026/8/14 15:12:46

七、Vue组件

一、组件定义 你可以把“组件”想象成乐高积木。在 Vue 中,我们不再是一笔一划地写一整个大网页,而是把网页拆分成一个个独立、可复用的小积木(比如导航栏、按钮、文章列表),然后像搭积木一样把它们拼起来。 1. 组件定…

2026/8/14 15:12:46

大模型读懂文档了吗——多模态RAG的文档理解

摘要 文档理解是多模态RAG系统的"第一公里",这一步的质量决定整个系统的上限——垃圾进,垃圾出。本文从多维分类体系出发,梳理不同文档类型对模型感知、结构理解、语义推理三层能力的差异化挑战,结合半导体显示领域的典…

2026/8/14 15:12:46

继承(全)

目录 一. 继承的概念及定义 1.1 继承的概念 1.2 继承的机制 1.3 继承的定义 1.3.1 定义格式​编辑 1.3.2 继承父类成员访问方式的变化 1.4 继承类模板 二. 父类和子类对象赋值兼容转换 2.2 类型转换的特殊处理规则 2.3 应用实例 三. 继承中的作用域 3.1 隐藏规则 …

2026/8/14 16:02:54

NASA Earthdata Search下载MOD13A3.061数据完整教程

摘要:本文详细介绍如何使用NASA Earthdata Search平台下载特定地理范围的MOD13A3.061植被指数数据,包含从数据搜索、范围选择、时间筛选到数据下载的完整步骤,并配有详细的操作截图说明。 1. 访问Earthdata Search平台 首先,访问…

2026/8/14 16:02:54

安卓驱动面试后对framework的思考

今天去面试安卓驱动工程师的岗位,首先他问了我安卓hwui,当时有点懵,以下是常见的framework总结--------------------------------------------------------------------------- | Java Framework …

2026/8/14 15:57:54

windows 驱动实例分析系列: wintun驱动分析-SetupApiHost篇(下)

二、代码逐层深度解析 2.2 host_win7.h —— Windows 7 专属的“无中生有” 2.2.2 CreateInstanceWin7 的完整流程 VOID __stdcall CreateInstanceWin7(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {/* 1. 创建设备信息 */SetupDiCreateDeviceInfoW(DevInfo…

2026/8/14 4:27:24

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/14 4:27:24

当 LLM 遇见大文档:主流开源项目如何处理上下文超限

从 Agentic Loop 到 Repo Map,七种策略与六类陷阱引言:128K vs 10MB 的硬冲突 2026 年的 LLM 上下文窗口已达到 128K ~ 1M token(≈ 0.5MB ~ 4MB 文本),但 LLM 想要处理的真实数据规模远远超过这个量级:真实…

2026/8/14 0:00:09

Flutter与OpenHarmony实现剧本杀组队表单开发实战

1. 项目概述在移动应用开发领域,跨平台框架Flutter因其高效的开发体验和出色的性能表现,已经成为众多开发者的首选。而OpenHarmony作为新兴的操作系统平台,其开放性和灵活性为开发者提供了全新的可能性。本文将聚焦于一个实际应用场景——剧本…

2026/8/14 0:00:09

VSCode高效Git管理:从入门到实战技巧

1. 为什么选择VSCode进行Git代码管理作为微软推出的轻量级代码编辑器,Visual Studio Code(简称VSCode)已经成为全球开发者使用率最高的编辑器之一。根据2023年Stack Overflow开发者调查,VSCode的市场占有率高达74.48%。它内置的Gi…

2026/8/14 4:27:24

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/14 4:27:24

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/14 4:27:24

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…