编译技术实验三之编译器的构造和设计
一、实验目的:
我们将设计多个不同的综合实验项目提供给学生选择。(如:LL(1)文法自动生成语法分析程序的设计;单词的自动识别与智能纠错;语言的程序编辑器;数学计算式的识别等)学生可在这些项目中选择1个项目,体现了实验技术的全面性和先进性。综合实验将以编译原理、技术为基础,结合前期课程,加上实际需求和学生自己的设计才能完成。这些前期课程接口包括离散数学、数据结构、C++程序设计语言、操作系统、汇编语言、数据库原理等。通过综合实验使学生设计制作出有一定水平的编译程序,使学生更好地掌握编译原理和基本技术
设计一个小型编译器。
二、实验内容及原理
以高级程序设计语言的编译原理和基本技术,加上实际编辑程序过程的需求,把综合实验项目分层次展开,经过小组学生的分工与合作加上创意才能完成。
设计的语言上可以使用编译性语言,也可以使用解释性语言。实验的结果是一个编译器或一个综合编译技术的应用软件。
三、实验过程原始数据记录
主要结构:
char terminal[50]; //终结符
set<string>Noter; //非终结符
vector<string>nt;
vector<string>t;
int tNum;//终结符个数
int nNum;//非终结符个数
string Production[50] = { "" };//产生式
string ReProduction[50] = { "" };//新产生式
int ProNum;//产生式个数
int ReProNum = 0;//新产生式个数
vector<pair<string, string>>I;//所有项目
vector<pair<string, string>>closure;//项目的闭包
vector<pair<string, string>>project;
vector<pair<string, string>>Start;
map<pair<int, string>, int>table;
string str;
unordered_map<int, vector<pair<int, string>>>LRtable;
unordered_map<int, vector<pair<string, int>>>state;
string lrtable[100][100] = { "-1" };
vector<int>sq;//状态栈
vector<char>inputStr, sign;//全体字符以及符号栈
主要函数:
void Gramma()
void GrammaF()
void get_project()
vector<pair<string, string>> get_closure(const vector<pair<string, string>>& pro)
vector<pair<string, string>> Goto(const vector<pair<string, string>>& pro, const string& flag)
vector<vector<pair<string, string>>> get_all_closure(const vector<pair<string, string>>& pro)
int get_num(string s)
int getChar(char ch)
int get_rnext(string s)
void get_LRTable(vector<vector<pair<string, string>>>allclosure)
void init()
string outPut(int i)
void check()
void analyst()
源代码:
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<unordered_map>
#include<iomanip>
#include<map>
using namespace std;char terminal[50]; //终结符
set<string>Noter; //非终结符
vector<string>nt;
vector<string>t;
int tNum; //终结符个数
int nNum; //非终结符个数
string Production[50] = { "" }; //产生式
string ReProduction[50] = { "" }; //新产生式
int ProNum; //产生式个数
int ReProNum = 0; //新产生式个数
vector<pair<string, string>>I; //所有项目
vector<pair<string, string>>closure; //项目闭包
vector<pair<string, string>>project;
vector<pair<string, string>>Start;
map<pair<int, string>, int>table;
string str;
unordered_map<int, vector<pair<int, string>>>LRtable;
string lrtable[100][100] = { "-1" };
unordered_map<int, vector<pair<string, int>>>state;
vector<int>sq;//状态栈
vector<char>inputStr, sign;//全体字符以及符号栈void Gramma() {cout << "--------------------------" << endl;cout << "请输入终结符的个数:";cin >> tNum;cout << "请输入终结符:" << endl;for (int i = 0; i < tNum; i++) {cin >> terminal[i];string st;st.push_back(terminal[i]);t.push_back(st);}cout << "请输入非终结符的个数:";cin >> nNum;cout << "请输入非终结符:" << endl;for (int i = 0; i < nNum; i++) {string s;cin >> s;Noter.insert(s);nt.push_back(s);t.push_back(s);}cout << "请输入产生式的个数:";cin >> ProNum;cout << "请输入产生式:" << endl;for (int i = 0; i < ProNum; i++) {cin >> Production[i];}
}void GrammaF() {int x = 0, z = 1;//x为第z个产生式的第x个字符for (int i = 0; i < ProNum; i++) {x = 3;int k = 0;while (x < Production[i].size()) {for (k = 0; k < 3; k++) {//获取产生式的左部以及箭头ReProduction[z] += Production[i][k];}while (x < Production[i].size() && Production[i][x] != '|') {ReProduction[z] += Production[i][x];x++;}z++;x++;}}string s = ReProduction[1].substr(0, 1) + "'";str = s;ReProduction[0] = s + "->" + ReProduction[1].substr(0, 1);t.push_back(s);Noter.insert(s);nt.push_back(s);nNum++;ReProNum = z;project.push_back({ s,ReProduction[1].substr(0, 1) });for (int i = 1; i < ReProNum; i++) {string fir = ReProduction[i].substr(0, 1);string sec = ReProduction[i].substr(3);project.push_back({ fir,sec });}
}void get_project() {I.push_back({ ReProduction[0].substr(0,2),"." + ReProduction[0].substr(4) });Start.push_back({ ReProduction[0].substr(0,2),"." + ReProduction[0].substr(4) });I.push_back({ ReProduction[0].substr(0,2),ReProduction[0].substr(4) + "." });for (int i = 1; i < ReProNum; i++) {string First = "";First += ReProduction[i][0];string Second = ReProduction[i].substr(3);for (int j = 0; j <= Second.size(); j++) {string tmp = Second;tmp.insert(j, ".");I.push_back({ First,tmp });}}for (int i = 0; i < I.size(); i++) {cout << I[i].first << " " << I[i].second << endl;}
}vector<pair<string, string>> get_closure(const vector<pair<string, string>>& pro) {vector<pair<string, string>>closure = pro;auto Size = closure.size();string first;for (int i = 0; i < Size; i++) {auto pos = closure[i].second.find(".");if (pos == string::npos) {cout << "error" << endl;cout << closure[i].first << "-->>" << closure[i].second << endl;return closure;}auto c = closure[i].second[pos + 1];first.push_back(c);if (Noter.find(first) == Noter.end()) {first.clear();continue;}for (int i = 0; i < project.size(); i++) {if (first == project[i].first) {auto second = project[i].second;second.insert(0, ".");bool flag = 0;for (int j = 0; j < Size; j++) {if (second == closure[j].second) {flag = 1;break;}}if (flag == 0) {closure.push_back({ first,second });}}}first.clear();Size = closure.size();}return closure;
}vector<pair<string, string>> Goto(const vector<pair<string, string>>& pro, const string& f) {vector<pair<string, string>>nextJ;for (int i = 0; i < pro.size(); i++) {auto p = pro[i].second.find(".");if (p == string::npos) {cout << "error" << endl;return nextJ;}else {auto ch = pro[i].second[p + 1];if (ch == '\0')continue;string temp;temp.push_back(ch);if (temp != f)continue;else{auto first = pro[i].first;auto second = pro[i].second;second[p] = second[p + 1];second[p + 1] = '.';nextJ.push_back({ first, second });}}}auto T = nextJ;nextJ = get_closure(T);return nextJ;
}vector<vector<pair<string, string>>> get_all_closure(const vector<pair<string, string>>& pro) {vector<vector<pair<string, string>>>allclosure;allclosure.push_back(pro);auto size = allclosure.size();for (int i = 0; i < size; i++) {set<string>flag;auto len = allclosure[i].size();for (int j = 0; j < len; j++) {auto pos = allclosure[i][j].second.find(".");if (pos == string::npos) {cout << "error" << endl;return allclosure;}else {auto ch = allclosure[i][j].second[pos + 1];if (ch == '\0') {continue;}string str;str.push_back(ch);flag.insert(str);}}for (set<string>::iterator it = flag.begin(); it != flag.end(); it++) {auto closure = Goto(allclosure[i], *it);if (closure.size() == 0)continue;else {bool stop = 0;for (int j = 0; j < size; j++) {if (allclosure[j] == closure) {table.insert({ {i,*it},j });stop = 1;break;}}if (stop == 1) {continue;}allclosure.push_back(closure);int sz = allclosure.size() - 1;table.insert({ {i,*it}, sz });}}size = allclosure.size();}return allclosure;
}int get_num(string s) {for (int i = 0; i < t.size(); i++) {if (t[i] == s) {return i;}}return -1;
}int get_rnext(string s) {for (int i = 0; i < project.size(); i++) {if (s == project[i].second) {return i;}}return -1;
}void get_LRTable(vector<vector<pair<string, string>>>allclosure) {for (int i = 0; i < allclosure.size(); i++) {for (int j = 0; j < t.size(); j++) {lrtable[i][j] = "-1";}}vector<pair<int, int>>nums;bool st[100] = { false };int acc;for (map<pair<int, string>, int>::iterator it = table.begin(); it != table.end(); it++){int from = it->first.first;int next = it->second;string s = it->first.second;auto Inext = allclosure[next];auto Ifrom = allclosure[from];lrtable[from][get_num(s)] = "s" + to_string(next);for (int j = 0; j < Ifrom.size(); j++) {auto pos = Ifrom[j].second.find(".");if (pos == Ifrom[j].second.size() - 1 && Ifrom[j].first != str) {int rnext = get_rnext(Ifrom[j].second.substr(0, Ifrom[j].second.size() - 1));nums.push_back({ from,rnext });}if (pos == Ifrom[j].second.size() - 1 && Ifrom[j].first == str) {acc = from;}}st[from] = true;}lrtable[acc][get_num("#")] = "acc";for (int i = 0; i < allclosure.size(); i++) {if (!st[i]) {for (int j = 0; j < allclosure[i].size(); j++) {auto pos = allclosure[i][j].second.find(".");if (pos == allclosure[i][j].second.size() - 1) {int rnext = get_rnext(allclosure[i][j].second.substr(0, allclosure[i][j].second.size() - 1));nums.push_back({ i,rnext });}}}}for (int i = 0; i < nums.size(); i++) {int f = nums[i].first, rnext = nums[i].second;for (int j = 0; j < tNum; j++) {lrtable[f][j] = "r" + to_string(rnext);}}for (int i = 0; i < allclosure.size(); i++) {for (int j = 0; j < t.size(); j++) {if (lrtable[i][j] != "-1") {LRtable[i].push_back({ j,lrtable[i][j] });}}}
}int getChar(char ch) {string s;s.push_back(ch);for (int i = 0; i < t.size(); i++) {if (t[i] == s)return i;}return -1;
}
void init() {for (map<pair<int, string>, int>::iterator it = table.begin(); it != table.end(); it++){state[it->first.first].push_back({ it->first.second,it->second });}
}string outPut(int i) {char buf[100];int count = 0;if (i == 0) {string str;for (vector<int>::iterator it = sq.begin(); it != sq.end(); it++) {int c = *it;str += to_string(c);}return str;}else if (i == 1) {for (vector<char>::iterator it = sign.begin(); it != sign.end(); it++) {buf[count++] = *it;}}else {for (vector<char>::iterator it = inputStr.begin(); it != inputStr.end(); it++) {buf[count++] = *it;}}buf[count] = '\0';string str(buf);return str;
}
void check() {int step = 1;sign.push_back('#');sq.push_back(0);cout << setw(10) << "步骤" << setw(10) << "状态栈" << setw(10) << "符号栈" << setw(10) << "输入串" << setw(25) << "动作说明" << endl;int s = 0;int oldstatus;char ch = inputStr.front();int c = getChar(ch);if (c == -1) {cout << "error" << endl;return;}while (lrtable[s][getChar(ch)] != "acc") {string sstr = lrtable[s][getChar(ch)];int s1 = 0;for (int i = 1; i < sstr.size(); i++) {s1 = s1 * 10 + (sstr[i] - '0');}s = s1;if (sstr == "-1") {cout << "error" << endl;return;}if (sstr.substr(0, 1) == "s") {cout << setw(10) << step << setw(10) << outPut(0) << setw(10) << outPut(1) << setw(10) << outPut(2) << setw(10) << "A" << "CTION[" << sq.back() << "," << ch << "]=S" << s << "," << "状态" << s << "入栈" << endl;sign.push_back(ch);inputStr.erase(inputStr.begin());sq.push_back(s);}else if (sstr.substr(0, 1) == "r") {string formu = ReProduction[s];string stop = project[s].first;int strlen = formu.size();int popnum = strlen - 3;int i = 0;for (vector<int>::reverse_iterator it = sq.rbegin(); it != sq.rend(); it++) {i++;if (i == popnum + 1) {oldstatus = *it;break;}}int r = s;for (int i = 0; i < state[oldstatus].size(); i++) {if (state[oldstatus][i].first == stop) {s = state[oldstatus][i].second;}}cout << setw(10) << step << setw(10) << outPut(0) << setw(10) << outPut(1) << setw(10) << outPut(2) << setw(10) << "r" << r << (string)":" + Production[r] + (string)"归约,GOTO{" << oldstatus << "," << 'E' << ")=" << s << "入栈" << endl;for (int i = 0; i < popnum; i++) {sq.pop_back();sign.pop_back();}sq.push_back(s);sign.push_back(stop[0]);}step++;s = sq.back();ch = inputStr.front();}cout << setw(10) << step << setw(10) << outPut(0) << setw(10) << outPut(1) << setw(10) << outPut(2) << setw(10) << "A" << "cc:分析成功" << endl;
}
void analyst() {init();string s;cout << "请输入字符串(+,-,*,/,E,i,(,),#):" << endl;cin >> s;for (int i = 0; i < s.size(); i++)inputStr.push_back(s[i]);if (inputStr.back() != '#')inputStr.push_back('#');check();
}int main() {Gramma();GrammaF();get_project();auto S = get_closure(Start);auto allclosure = get_all_closure(S);for (int i = 0; i < allclosure.size(); i++) {cout << "I" << i << ":" << endl;for (int j = 0; j < allclosure[i].size(); j++) {cout << allclosure[i][j].first << "->" << allclosure[i][j].second << endl;}}cout << table.size() << endl;cout << "\n转换关系:" << endl;for (map<pair<int, string>, int>::iterator it = table.begin(); it != table.end(); it++){cout << "[ " << it->first.first << ", " << it->first.second << " ] -> " << it->second << endl;}get_LRTable(allclosure);for (int i = 0; i < project.size(); i++) {cout << ReProduction[i] << endl;}for (int i = 0; i < allclosure.size(); i++) {for (int j = 0; j < t.size(); j++) {cout << lrtable[i][j] << " ";}cout << endl;}analyst();}
结果:
语法分析:
生成项目集
拓广文法
生成LR分析表
四、实验总结
通过这个实验,我认识到编译器的重要性和复杂性。在设计和构造编译器的过程中,我需要考虑语法分析、词法分析、语义分析等多个环节,同时还要处理错误处理、优化等问题。在实验中,我需要将学习到的几个章节的理论知识转化为实际可执行的代码。我学会了如何根据给定的文法和规则构建语法分析树,如何设计和实现词法分析器,如何进行语义分析和中间代码生成等。在设计和构造编译器的过程中,我遇到了很多困难和挑战,需要不断地debug,这有利于巩固了我的编程能力,提高我的设计思维和解决问题的能力。
相关文章:

编译技术实验三之编译器的构造和设计
一、实验目的: 我们将设计多个不同的综合实验项目提供给学生选择。(如:LL(1)文法自动生成语法分析程序的设计;单词的自动识别与智能纠错;语言的程序编辑器;数学计算式的识别等)学生可在这些项目中选择1个项…...

数据挖掘——数据预处理
数据挖掘——数据预处理 数据预处理数据预处理 ——主要任务数据清洗如何处理丢失的数据如何处理噪声数据如何处理不一致数据 数据集成相关分析相关系数(也成为皮尔逊相关系数)协方差 数据规约降维法:PCA主成分分析降数据——抽样法数据压缩 数据预处理 数据预处理…...

ECharts饼图下钻
背景:项目上需要对Echarts饼图进行功能定制,实现点击颜色块,下钻显示下一层级占比说明:饼图实现点击下钻/面包屑返回的功能 数据结构 [{name: a,value: 1,children: [...]},... ]点击下钻 // 为图表绑定点击事件(需要…...

【RK3568笔记】Android修改开机动画
概述 Android 的开机动画是由一系列连续的 PNG 图片作为帧组成的动画形式,不是一张 GIF 图片。将各帧 PNG 图片以压缩方式进行保存(压缩方式要求是存储压缩),并将保存的文件名命名为 bootanimation.zip,这个 bootanim…...

嵌入式技术之Linux(Ubuntu) 一
一、Linux入门 1.硬件和操作系统以及用户的关系 一个传感器,获得数据后,需要向服务器发送数据。传感器传数据给上位机。 上位机需要一个程序来接收数据,那么这个上位机是什么机器? 我们的笔记本电脑就可以当成上位机。 两个手…...
代码随想录day39 动态规划7
打家劫舍 题目:198.打家劫舍 213.打家劫舍II 337.打家劫舍III 需要重做:全部 198.打家劫舍 思路:第i个房子偷与不偷,取决于第i-2个房子和第i-1个房子 注意:注意下标的一致性。现在的下标含义是房子的下标&#x…...
ESP32-S3模组上实现低功耗(5)
接前一篇文章:ESP32-S3模组上实现低功耗(4) 本文内容参考: 系统低功耗模式介绍 - ESP32-S3 - — ESP-IDF 编程指南 latest 文档 电源管理 - ESP32-S3 - — ESP-IDF 编程指南 latest 文档...
PDF转文本以及转图片:itextpdf
文章目录 🐒个人主页:信计2102罗铠威🏅JavaEE系列专栏📖前言:🎀 1. itextpdf1.1导入itextpdf的maven依赖1.2 提取文本代码1.3 pdf转换成图片代码(本地图片地址还是线上PDF的URL地址均支持&#…...

AnaConda下载PyTorch慢的解决办法
使用Conda下载比较慢,改为pip下载 复制下载链接到迅雷下载 激活虚拟环境,安装whl,即可安装成功 pip install D:\openai.wiki\ChatGLM2-6B\torch-2.4.1cu121-cp38-cp38-win_amd64.whl...

移动端自动化测试Appium-java
一、Appium的简介 移动端的自动化测试框架 模拟人的操作进行功能自动化常用于功能测试、兼容性测试 跨平台的自动化测试 二、Appium的原理 核心是web服务器,接受客户端的连接,接收客户端的命令,在手机设备上执行命令,收集命令…...

IO: 作业:Day1
思维导图 main.c #include"student.h" int main(int argc, const char *argv[]) { stuPtr hcreat(); int n0; add_node(h); add_node(h); add_node(h); show(h); save(h,"student.txt"); stuPtr ptrc…...

ue5 替换角色的骨骼网格体和动画蓝图
一开始动画蓝图,骨骼网格体都是用的女性角色 现在把它换成男性 编译 保存 运行 把动画类换成ABP_Manny 进入ABP_Manny中 进入到idle 找到这个拖进来 编译 就变成站着端枪 运行一下,没有问题...
el-cascader 树状选择-点击父级禁用子级
背景:项目上需要实现树状选择,点击父级禁用子级的功能,element组件本身没有该配置项说明:需要实现几个功能点:点击父级禁用子级;再次点击取消禁用;仅回填所选级;上下级不关联实现代码…...

AWS re:Invent 的创新技术
本月早些时候,Amazon 于 12 月 1 日至 5 日在内华达州拉斯维加斯举行了为期 5 天的 re:Invent 大会。如果您从未参加过 re:Invent 会议,那么最能描述它的词是“巨大”——不仅从与会者人数(60,000 人)来看&…...

PHP7和PHP8的最佳实践
php 7 和 php 8 的最佳实践包括:使用类型提示以避免运行时错误;利用命名空间组织代码并避免命名冲突;采用命名参数、联合类型等新特性增强可读性;用错误处理优雅地处理异常;关注性能优化,如避免全局变量和选…...
Debian、Ubuntu 22.04和ubuntu 24.04国内镜像源(包括 docker 源)
Debian 更换国内清华源 1、备份原文件mv /etc/apt/sources.list /etc/apt/sources.list.old 2、写入新源,以下是 Debian 11 的: cat > /etc/apt/sources.list << EOF deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib…...

点亮一个esp32 的led
最近入了一个ESP32 兄弟们,这玩意还可以,买来肯定是给它点亮啊对吧 我就是点灯侠🎇 😭千万不要不接天线啊,不然你会一直找不到你的wifi 1.点灯第一步你得有IDE Arduino 就是这个绿东西 可是怎么下载安装呢ÿ…...
C++ shared_ptr进一步认知,为什么引用计数>2退出作用域都可以调用析构
1.使用智能指针需要#include <memeroy> 2.上代码: #include <memory> #include <iostream> using namespace std; struct lifePeriod {lifePeriod():a(1){cout << "无参构造!" << endl;}virtual ~lifePeriod(…...
JavaScript代码片段二
见过不少人、经过不少事、也吃过不少苦,感悟世事无常、人心多变,靠着回忆将往事串珠成链,聊聊感情、谈谈发展,我慢慢写、你一点一点看...... JavaScript统计文字个数、特殊字符转义、动态插入js代码、身份证验证 统计文字个数 f…...

【计算机视觉】单目深度估计模型-Depth Anything-V2
概述 本篇将简单介绍Depth Anything V2单目深度估计模型,该模型旨在解决现有的深度估计模型在处理复杂场景、透明或反射物体时的性能限制。与前一代模型相比,V2版本通过采用合成图像训练、增加教师模型容量,并利用大规模伪标签现实数据进行学…...

Xamarin入门笔记(Xamarin已经被MAUI取代)
初级代码游戏的专栏介绍与文章目录-CSDN博客 Xamarin入门 概述 环境 Android开发环境比较简单,自带模拟器,实体机打开开发者模式即可。 iOS开发环境比较复杂,必须搭配Mac电脑,Windows连接Mac开发可能有问题(比如发…...

.NET 7 AOT 使用及 .NET 与 Go 语言互操作详解
.NET 7 AOT 使用及 .NET 与 Go 语言互操作详解 目录 .NET 7 AOT 使用及 .NET 与 Go 语言互操作详解 一、背景与技术概述 1.1 AOT 编译技术简介 1.2 Go 语言与 .NET 的互补性 二、.NET 7 AOT 编译实践 2.1 环境准备 2.2 创建 AOT 项目 2.3 AOT 编译流程 2.4 调试信息处…...
对数的运算困惑
难点总结 学生在对数运算中的难点分析: 一、不理解对数,不会用对数公式或错用对数公式 ①对数 l o g 2 3 log_23 log23和指数幂 2 3 2^3 23一样,也就是个实数而已,所以其也会有加减乘除乘方开方等运算; 比如 2 2 + l o g 2 3 = 2 2 ⋅ 2 l o g 2 3 = 4 ⋅ 3 = 12 2^{2…...
云原生时代 Kafka 深度实践:02快速上手与环境搭建
2.1 本地开发环境搭建 单机模式安装 下载与解压:前往Apache Kafka 官网,下载最新稳定版本的 Kafka 二进制包(如kafka_2.13-3.6.0.tgz,其中2.13为 Scala 版本)。解压到本地目录,例如/opt/kafka:…...

Nginx安全防护与HTTPS部署实战
目录 前言一. 核心安全配置1. 隐藏版本号2. 限制危险请求方法3. 请求限制(CC攻击防御)(1)使用nginx的limit_req模块限制请求速率(2)压力测试验证 4. 防盗链 二. 高级防护1. 动态黑名单(1&#x…...
WPF【11_10】WPF实战-重构与美化(配置Material UI框架)
11-16 【UI美化】配置Material UI框架 三种比较主流的 UI 设计规范,分别是: 苹果的扁平化 UI 设计、安卓或者说谷歌 的 Material Design 以及微软的 Metro 风格。 这三种风格都极具特色,不过我们接下来将会使用的是 Material Design 。在 W…...
每日算法 -【Swift 算法】字符串转整数算法题详解:myAtoi 实现与正则表达式对比
Swift 字符串转整数算法题详解:myAtoi 实现与正则表达式对比 🧩 题目背景 LeetCode 上的经典算法题 8. String to Integer (atoi) 是一道考察字符串解析与边界处理的题目。这道题虽看似简单,但处理细节相当复杂。我们将使用 Swift 语言实现…...
Kotlin 中的数据类型有隐式转换吗?为什么?
在 Kotlin 中,基本数据类型没有隐式转换。主要出于安全性和明确性的考虑。 1 Kotlin 的显式类型转换规则 Kotlin 要求开发者显式调用转换函数进行类型转换, 例如: val a: Int 10 val b: Long a.toLong() // 必须显式调用 toLong() // 错…...
Spring 核心知识点补充
Spring 核心知识点补充 1. IoC(控制反转) 核心思想:将对象的创建和依赖管理交给容器,而非在代码中直接控制实现方式: XML 配置:<bean> 标签定义对象注解:Component, Service, Repositor…...
Flannel 支持的后端
Flannel 是一个为 Kubernetes 设计的容器网络解决方案,支持多种后端(backend)来处理节点间的数据包转发。根据官方文档和其他可靠来源,以下是 Flannel 支持的后端类型及其说明: VXLAN(推荐) 描述…...