C++服务器 支持http、tcp protobuf、websocket,linux开源框架 零依赖轻松编译部署 Reactor
开源地址: https://github.com/crust-hub/tubekit/tree/main
Github:https://github.com/gaowanlu
诚招有兴趣的小伙伴加入开发维护
Tubekit
The C++ TCP server framework based on the Reactor model continues to implement POSIX thread pool, Epoll, non blocking IO, object pool, log, socket network programming, support the dynamic library to implement custom protocol extensions, and use http parser to process http requests. Currently only supports Linux systems
Platform: Linux
Protocol: HTTP TCP Stream(Protobuf) WebSocket
Get Start
prepare
$ sudo apt update
$ sudo apt install protobuf-compiler libprotobuf-dev
$ apt install g++ cmake make
$ git clone https://github.com/crust-hub/tubekit.git
Build
$ cd tubekit
$ cd protocol
$ make
$ cd ..
$ cmake .
$ make -j3
Config
$ vim bin/config/main.ini
Run
$ chmod +x ./run.sh
$ ./run.sh
Stop
$ chmod +x ./kill.sh
$ ./kill.sh
App
support tcp keep-alive stream (protobuf) and http app (http-parser)、websocket
Directory Structure
Directory Structure Link
Third Party
@http-parser
@lua
HTTP样例
#include "app/http_app.h"
#include <string>
#include <vector>
#include <filesystem>
#include <tubekit-log/logger.h>#include "utility/mime_type.h"
#include "utility/url.h"using std::string;
using std::vector;
using tubekit::app::http_app;
using tubekit::connection::http_connection;
namespace fs = std::filesystem;
namespace utility = tubekit::utility;class html_loader
{
public:static string load(string body){static string frame1 = "<!DOCTYPE html>\<html>\<head>\<title></title>\</head>\<body>";static string frame2 = "</body>\</html>";return frame1 + body + frame2;}static string a_tag(string url, string text){string frame = "<a href=\"" + url + "\">" + text + "</a></br>";return frame;}
};void http_app::process_connection(tubekit::connection::http_connection &m_http_connection)
{m_http_connection.m_buffer.set_limit_max(202300);// load callbackm_http_connection.destory_callback = [](http_connection &m_connection) -> void{if (m_connection.ptr){FILE *file = (FILE *)m_connection.ptr;::fclose(file);m_connection.ptr = nullptr;}};m_http_connection.process_callback = [](http_connection &connection) -> void{string url = utility::url::decode(connection.url);auto find_res = url.find("..");if (std::string::npos != find_res){connection.set_response_end(true);return;}const string prefix = "/";fs::path t_path;if (url.empty() || url[0] != '/'){t_path = prefix + url;}else{t_path = url;}if (fs::exists(t_path) && fs::status(t_path).type() == fs::file_type::regular){std::string mime_type;try{mime_type = utility::mime_type::get_type(t_path.string());}catch (...){mime_type = "application/octet-stream";}std::string response = "HTTP/1.1 200 OK\r\nServer: tubekit\r\n";response += "Content-Type: ";response += mime_type + "\r\n\r\n";try{connection.m_buffer.write(response.c_str(), response.size());}catch (const std::runtime_error &e){LOG_ERROR(e.what());}connection.ptr = nullptr;connection.ptr = ::fopen(t_path.c_str(), "r");if (connection.ptr == nullptr){connection.set_response_end(true);return;}// Write when the contents of the buffer have been sent write_end_callback will be executed,// and the response must be set response_end to true, then write after write_end_callback will be continuously recalledconnection.write_end_callback = [](http_connection &m_connection) -> void{char buf[202300] = {0};int len = 0;len = ::fread(buf, sizeof(char), 202300, (FILE *)m_connection.ptr);if (len > 0){try{m_connection.m_buffer.write(buf, len);}catch (const std::runtime_error &e){LOG_ERROR(e.what());}}else{m_connection.set_response_end(true);}};return;}if (fs::exists(t_path) && fs::status(t_path).type() == fs::file_type::directory){connection.ptr = nullptr;const char *response = "HTTP/1.1 200 OK\r\nServer: tubekit\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n";try{connection.m_buffer.write(response, strlen(response));}catch (const std::runtime_error &e){LOG_ERROR(e.what());}// generate dir listvector<string> a_tags;for (const auto &dir_entry : fs::directory_iterator{t_path}){std::string sub_path = dir_entry.path().string(); //.substr(prefix.size());a_tags.push_back(html_loader::a_tag(utility::url::encode(sub_path), sub_path));}string body;for (const auto &a_tag : a_tags){body += a_tag;}string html = html_loader::load(body);try{connection.m_buffer.write(html.c_str(), html.size());}catch (const std::runtime_error &e){LOG_ERROR(e.what());}connection.set_response_end(true);return;}const char *response = "HTTP/1.1 404 Not Found\r\nServer: tubekit\r\nContent-Type: text/text; charset=UTF-8\r\n\r\n";try{connection.m_buffer.write(response, strlen(response));}catch (const std::runtime_error &e){LOG_ERROR(e.what());}connection.set_response_end(true);};
}
protobuf样例
#include "app/stream_app.h"
#include "proto_res/proto_cmd.pb.h"
#include "proto_res/proto_example.pb.h"
#include "proto_res/proto_message_head.pb.h"
#include <tubekit-log/logger.h>
#include <string>
#include <set>
#include "thread/mutex.h"
#include "utility/singleton.h"
#include "connection/connection_mgr.h"
#include "socket/socket.h"
#include "socket/socket_handler.h"using tubekit::app::stream_app;
using tubekit::connection::connection_mgr;
using tubekit::connection::stream_connection;
using tubekit::socket::socket;
using tubekit::socket::socket_handler;
using tubekit::utility::singleton;namespace tubekit::app
{std::set<void *> global_player;tubekit::thread::mutex global_player_mutex;
}int process_protocol(tubekit::connection::stream_connection &m_stream_connection, ProtoPackage &package)
{// EXAMPLE_REQif (package.cmd() == ProtoCmd::EXAMPLE_REQ){ProtoExampleReq exampleReq;if (exampleReq.ParseFromString(package.body())){LOG_ERROR("%s", exampleReq.testcontext().c_str());// std::cout << exampleReq.testcontext() << std::endl;}else{return -1;}return 0;}return -1;
}void stream_app::process_connection(tubekit::connection::stream_connection &m_stream_connection)
{using tubekit::app::global_player;using tubekit::app::global_player_mutex;uint64_t all_data_len = m_stream_connection.m_recv_buffer.can_readable_size();char *all_data_buffer = new char[all_data_len];m_stream_connection.m_recv_buffer.copy_all(all_data_buffer, all_data_len);uint64_t offset = 0;do{char *tmp_buffer = all_data_buffer + offset;uint64_t data_len = all_data_len - offset;if (data_len == 0){break;}ProtoPackage protoPackage;if (!protoPackage.ParseFromArray(tmp_buffer, data_len)){// std::cout << "protoPackage.ParseFromArray failed" << std::endl;break;}if (0 != process_protocol(m_stream_connection, protoPackage)){// std::cout << "process_protocol failed" << std::endl;m_stream_connection.mark_close();m_stream_connection.m_recv_buffer.clear();break;}// std::cout << "datalen " << data_len << " package size " << protoPackage.ByteSizeLong() << std::endl;offset += protoPackage.ByteSizeLong();} while (true);if (!m_stream_connection.m_recv_buffer.read_ptr_move_n(offset)){m_stream_connection.mark_close();}delete[] all_data_buffer;
}void stream_app::on_close_connection(tubekit::connection::stream_connection &m_stream_connection)
{using tubekit::app::global_player;using tubekit::app::global_player_mutex;global_player_mutex.lock();global_player.erase(m_stream_connection.get_socket_ptr());LOG_ERROR("player online %d", global_player.size());global_player_mutex.unlock();
}void stream_app::on_new_connection(tubekit::connection::stream_connection &m_stream_connection)
{using tubekit::app::global_player;using tubekit::app::global_player_mutex;global_player_mutex.lock();global_player.insert(m_stream_connection.get_socket_ptr());LOG_ERROR("player online %d", global_player.size());global_player_mutex.unlock();
}bool stream_app::new_client_connection(const std::string &ip, int port)
{socket::socket *socket_object = singleton<socket_handler>::instance()->alloc_socket();if (!socket_object){LOG_ERROR("alloc_socket return nullptr");return false;}bool b_ret = socket_object->connect(ip, port);if (!b_ret){LOG_ERROR("connection remote %s:%d failed", ip.c_str(), port);singleton<socket_handler>::instance()->remove(socket_object);return false;}int i_ret = singleton<socket_handler>::instance()->attach(socket_object);if (0 != i_ret){LOG_ERROR("attach to socket_handler error ret %d", i_ret);singleton<socket_handler>::instance()->remove(socket_object);return false;}// maybe to do some management for client socket...return true;
}
websocket
#include "app/websocket_app.h"
#include <vector>
#include <tubekit-log/logger.h>
#include "utility/singleton.h"
#include "connection/connection_mgr.h"
#include <arpa/inet.h>using namespace tubekit::app;
using namespace tubekit::utility;
using namespace tubekit::connection;struct websocket_frame
{uint8_t fin;uint8_t opcode;uint8_t mask;uint64_t payload_length;std::vector<uint8_t> masking_key;std::string payload_data;
};enum class websocket_frame_type
{CONNECTION_CLOSE_FRAME = 0,TEXT_FRAME = 1,BINARY_FRAME = 2,PONG = 3,PING = 4,CONTINUATION_FRAME = 5,ERROR = 6
};void websocket_app::process_connection(tubekit::connection::websocket_connection &m_websocket_connection)
{LOG_ERROR("process_connection");uint64_t all_data_len = m_websocket_connection.m_recv_buffer.can_readable_size();if (all_data_len <= 0){LOG_ERROR("all_data_len <= 0");return;}char *data = new (std::nothrow) char[all_data_len];if (!data){return;}all_data_len = m_websocket_connection.m_recv_buffer.copy_all(data, all_data_len);size_t index = 0;while (true){if (index >= all_data_len){break;}size_t start_index = index;websocket_frame frame;websocket_frame_type type = websocket_frame_type::ERROR;switch ((uint8_t)data[index]){case 0x81:{type = websocket_frame_type::TEXT_FRAME;break;}case 0x82:{type = websocket_frame_type::BINARY_FRAME;break;}case 0x88:{type = websocket_frame_type::CONNECTION_CLOSE_FRAME;break;}case 0x89:{type = websocket_frame_type::PING;break;}default:{if (data[index] >= 0x00 && data[index] <= 0x7F){type = websocket_frame_type::CONTINUATION_FRAME;}break;}}if (type != websocket_frame_type::TEXT_FRAME && type != websocket_frame_type::BINARY_FRAME){m_websocket_connection.mark_close();break;}frame.fin = (data[index] & 0x80) != 0;frame.opcode = data[index] & 0x0F;index++;if (index >= all_data_len){LOG_ERROR("index[%llu] >= all_data_len[%llu]", index, all_data_len);break;}frame.mask = (data[index] & 0x80) != 0;frame.payload_length = data[index] & 0x7F;index++;if (index >= all_data_len){LOG_ERROR("index[%llu] >= all_data_len[%llu]", index, all_data_len);break;}if (frame.payload_length == 126){frame.payload_length = 0;if (index + 2 >= all_data_len){LOG_ERROR("index[%llu] >= all_data_len[%llu]", index + 2, all_data_len);break;}uint16_t tmp = 0;u_char *ph;ph = (u_char *)&tmp;*ph++ = data[index];*ph++ = data[index + 1];tmp = ntohs(tmp);frame.payload_length = tmp;index += 2;}else if (frame.payload_length == 127){frame.payload_length = 0;if (index + 8 >= all_data_len){LOG_ERROR("index[%llu] >= all_data_len[%llu]", index + 8, all_data_len);break;}uint32_t tmp = 0;u_char *ph = (u_char *)&tmp;*ph++ = data[index++];*ph++ = data[index++];*ph++ = data[index++];*ph++ = data[index++];frame.payload_length = ntohl(tmp);frame.payload_length = frame.payload_length << 32;ph = (u_char *)&tmp;*ph++ = data[index++];*ph++ = data[index++];*ph++ = data[index++];*ph++ = data[index++];tmp = ntohl(tmp);frame.payload_length = frame.payload_length | tmp;}if (frame.payload_length == 0){break;}if (frame.mask){if (index + 4 >= all_data_len){LOG_ERROR("index[%llu] >= all_data_len[%llu]", index + 3, all_data_len);break;}frame.masking_key = {(uint8_t)data[index], (uint8_t)data[index + 1], (uint8_t)data[index + 2], (uint8_t)data[index + 3]};index += 4;}// payload data [data+index,data+index+frame.payload_length]if (index >= all_data_len){LOG_ERROR("index[%llu] >= all_data_len[%llu]", index, all_data_len);break;}if (index - 1 + frame.payload_length >= all_data_len){LOG_ERROR("index - 1 + frame.payload_length=[%llu] >= all_data_len[%llu]", index - 1 + frame.payload_length, all_data_len);break;}std::string payload_data(data + index, frame.payload_length);if (frame.mask){for (size_t i = 0; i < payload_data.size(); ++i){payload_data[i] ^= frame.masking_key[i % 4];}}frame.payload_data = std::move(payload_data);// broadcastsingleton<connection_mgr>::instance()->for_each([&frame](connection::connection &conn) -> void{websocket_connection *ptr_conn = static_cast<websocket_connection *>(&conn);websocket_app::send_packet(*ptr_conn, frame.payload_data.c_str(), frame.payload_length, false);});// websocket_app::send_packet(m_websocket_connection, frame.payload_data.c_str(), frame.payload_length, false);// frame.payload_data.push_back(0);// LOG_ERROR("%s", frame.payload_data.c_str());m_websocket_connection.m_recv_buffer.read_ptr_move_n(index - start_index + frame.payload_length);index += frame.payload_length;}delete[] data;
}void websocket_app::on_close_connection(tubekit::connection::websocket_connection &m_websocket_connection)
{LOG_ERROR("on_close_connection");
}void websocket_app::on_new_connection(tubekit::connection::websocket_connection &m_websocket_connection)
{LOG_ERROR("on_new_connection");
}bool websocket_app::send_packet(tubekit::connection::websocket_connection &m_websocket_connection, const char *data, size_t data_len, bool use_safe)
{if (!data){return false;}uint8_t opcode = 0x81;size_t message_length = data_len;std::vector<uint8_t> frame;frame.push_back(opcode);if (message_length <= 125){frame.push_back(static_cast<uint8_t>(message_length));}else if (message_length <= 0xFFFF){frame.push_back(126);frame.push_back((message_length >> 8) & 0xFF);frame.push_back(message_length & 0xFF);}else{frame.push_back(127);for (int i = 7; i >= 0; --i){frame.push_back((message_length >> (8 * i)) & 0xFF);}}frame.insert(frame.end(), data, data + data_len);if (!use_safe){return m_websocket_connection.send((const char *)frame.data(), frame.size());}return singleton<connection_mgr>::instance()->safe_send(m_websocket_connection.get_socket_ptr(), (const char *)frame.data(), frame.size());
}
相关文章:
C++服务器 支持http、tcp protobuf、websocket,linux开源框架 零依赖轻松编译部署 Reactor
开源地址: https://github.com/crust-hub/tubekit/tree/main Github:https://github.com/gaowanlu 诚招有兴趣的小伙伴加入开发维护 Tubekit The C TCP server framework based on the Reactor model continues to implement POSIX thread pool, Epoll, non blocking IO, obj…...
1688API接口系列,1688开放平台接口使用方案(商品详情数据+搜索商品列表+商家订单类)
1688商品详情接口是指1688平台提供的API接口,用于获取商品详情信息。通过该接口,您可以获取到商品的详细信息,包括商品标题、价格、库存、描述、图片等。 要使用1688商品详情接口,您需要先申请1688的API权限,并获取ac…...
CentOS服务器网页版Rstudio-server及R包批量安装最佳实践
CentOS服务器安装网页版Rstudio-server及R包批量安装 以下为CentOS 7/8的Rstudio-server安装、配置和R包安装操作 1. 软件包安装 Centos 7安装 # 下载安装包,大小115.14 MB wget -c https://download2.rstudio.org/server/centos7/x86_64/rstudio-server-rhel-…...
centos7内核升级(k8s基础篇)
1.查看系统内核版本信息 uname -r 2.升级内核 2.1更新yum源仓库 yum -y update更新完成后,启用 ELRepo 仓库并安装ELRepo仓库的yum源 ELRepo 仓库是基于社区的用于企业级 Linux 仓库,提供对 RedHat Enterprise (RHEL) 和 其他基于 RHEL的 Linux 发行…...
数据结构与算法设计分析——NP完全理论
目录 一、P类问题与NP类问题的定义二、常见的NP类问题(一)旅行商问题(TSP)(二)哈密尔顿回路问题(三)判断回路问题(四)图的着色问题(五)…...
AGNES层次聚类
已知数据集D中有9个数据点,分别是(1,2),(2,3),(2,1), (3,1),(2,4),(3,5),(4,3),(1,5),(4,2)。要求: (1)采用层次聚类的聚集算法进行聚类,k2。 (2)距离计算采用欧几里得距离。 (3)簇之间的距离采用单链接方…...
HCIP —— 双点重发布 + 路由策略 实验
目录 实验拓扑: 实验要求: 实验配置: 1.配置IP地址 2.配置动态路由协议 —— RIP 、 OSPF R1 RIP R4 OSPF R2 配置RIP、OSPF 双向重发布 R3配置RIP、OSPF 双向重发布 3.查询路由表学习情况 4.使用路由策略控制选路 R2 R3 5.检…...
Python标准库:datetime模块【侯小啾python领航班系列(二十五)】
Python标准库:datetime模块【侯小啾python领航班系列(二十五)】 大家好,我是博主侯小啾, 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ…...
新版idea如何开启多台JVM虚拟机
1.看看自己的项目 2.可能开始的时候啥也没有,就点Run Configuration Type 3.再点击Edit Configurations... 4.点击号添加SpringBoot 5.主类选择一下,一般就一个,点他选了就行。 6.然后点击Modify Options 选择添加add VM Options 7.点击appl…...
软件工程单选多选补充
2. 4. 5. 6. 7. 8. 9. 10. 12。 13....
6-66.时间
本题要求输入小时、分钟和秒数,并将其输出。针对时间表示中出现的异常进行处理。例如小时数不应超过23,分钟不应超过59,秒数不应超过59。此外,以上三个变量均应大于等于0。 输入样例: 在这里给出三组输入。例如&…...
面试多线程八股文十问十答第一期
面试多线程八股文十问十答第一期 作者:程序员小白条,个人博客 相信看了本文后,对你的面试是有一定帮助的! ⭐点赞⭐收藏⭐不迷路!⭐ 1.ThreadLocal如何实现线程安全 Java的ThreadLocal是一个线程本地变量࿰…...
Mybatis 操作续集(结合上文)
当我们增加一个数据之后,如果我们想要获取它的 Id 进行别的操作,我们该如何获取 Id 呢? 用那个Options package com.example.mybatisdemo.mapper;import com.example.mybatisdemo.model.UserInfo; import org.apache.ibatis.annotations.*;import java.util.List;Mapper pub…...
JVM基础篇:垃圾回收
目录 1.前言 1.1C/C的内存管理 1.2Java的内存管理 2.方法区的回收 3.堆回收 3.1引用计数法和可达性分析法 3.2五种对象引用 强引用 软引用 弱引用 虚引用 终结器引用 3.3垃圾回收算法评价标准 ①吞吐量 ②最大暂停时间 ③堆使用效率 3.4垃圾回收算法 ①标记清…...
蓝桥杯ACwing习题
题目 :https://www.acwing.com/problem/content/4409/ 解析 :根据题目我们可以知道 问的是方案数 那么首先就想到了 dp 仔细想一下 发现类似于蒙德里安的梦想那道状态压缩的题 , 所以我们先考虑怎么定义 f[i][j] f[i][j] 表示的是 已经放了…...
vue发送请求携带token,拼接url地址下载文件
封装请求 ,该请求为普通的get请求 该请求返回值为: 请求成功之后拼接URL地址下载文件 代码块 downTemplateRequest(activeKeys.value).then((res) > {let url http://47.169.168.99:18888/media/${res.data.name};var elink document.createElemen…...
【PTA-C语言】编程练习3 - 循环结构Ⅱ
如果代码存在问题,麻烦大家指正 ~ ~有帮助麻烦点个赞 ~ ~ 编程练习3 - 循环结构(9~15) 7-9 特殊a串数列求和(分数 15)7-10 穷举法搬运砖块问题(分数 15)7-11 数字金字塔(分数 15&…...
Google Chrome 下载 (离线版)
1 访问网址 Google Chrome 网络浏览器 2 点击 下载Chrome 3 直接运行 ChromeStandaloneSetup64.exe 其他: ####################### 谷歌浏览器 (Google Chrome) 最新版离线安装包下载 https://www.iplaysoft.com/tools/chrome/#google_vignette Google Chrome …...
2023年GopherChina大会-核心PPT资料下载
一、峰会简介 自 Go 语言诞生以来,中国便是其应用最早和最广的国家之一,根据 Jetbrains 在 2021 年初做的调查报告,总体来说目前大概有 110 万专业的开发者 选择 Go 作为其主要开发语言。就其全球分布而言, 居住在亚洲的开发者最多ÿ…...
从源代码出发,Jenkins 任务排队时间过长问题的解决过程
最近开发了一个部署相关的工具,使用 Jenkins 来构建应用。Jenkins 的任务从模板中创建而来。每次部署时,通过 Jenkins API 来触发构建任务。在线上运行时发现,通过 API 触发的 Jenkins 任务总是会时不时在队列中等待较长的时间。某些情况下的…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...
Linux信号保存与处理机制详解
Linux信号的保存与处理涉及多个关键机制,以下是详细的总结: 1. 信号的保存 进程描述符(task_struct):每个进程的PCB中包含信号相关信息。 pending信号集:记录已到达但未处理的信号(未决信号&a…...
结合PDE反应扩散方程与物理信息神经网络(PINN)进行稀疏数据预测的技术方案
以下是一个结合PDE反应扩散方程与物理信息神经网络(PINN)进行稀疏数据预测的技术方案,包含完整数学推导、PyTorch/TensorFlow双框架实现代码及对比实验分析。 基于PINN的反应扩散方程稀疏数据预测与大规模数据泛化能力研究 1. 问题定义与数学模型 1.1 反应扩散方程 考虑标…...
