EDA软件研发的DevOps平台

news2024/12/26 23:35:02

1:什么是DevOps

DevOps是十几年前,在互联网比较火的词,实际上就是ci/cd平台的另外一种说法,核心是说打破研发,测试,运维的边界,能够将整个产品开发的流程快速循环起来,随时可发版,随时可测试,达到敏捷开发的目的。当然,这里还牵扯到大量的线上发布,自动化测试的手段。

记得在更早前,研发桌面软件,或者大型的ERP软件时,并没有持续集成的概念,那时,测试不可能天天拿到最新的版本,拿到可测试版本,至少要一个月的周期。

转眼间,互联网甚至移动互联网的风头已过,芯片热兴起,国内不少企业开始进入EDA软件的领域。那EDA软件的开发,是否需要有DevOps,或者说CI/CD平台呢?实际上,仍然是非常需要的,甚至在某些场景,它起到的作用,非常之大。下面以我见到的案例,讲解一下要研发一个大型的EDA软件(桌面软件),如何搭建一个CI/CD平台。

1.1:EDA软件的开发流程

我们先来看一张图:

上面这张图,是对一个FPGA EDA软件开发流程的理解,它本身就是一个需要快速循环的过程。谁的周转率快,谁就能在软件中占得先机。

行内人会知道,要研发一款全链的EDA工具,不光是在某些环节有很高的难度,它的规模实际上也是不小的。中等规模可能是 100人的研发团队,在Xilinx,曾经有超过1000人的软件团队针对一款工具进行研发。所以,要协同好大家的工作,保证软件快速的持续更新,必须要有Ci/Cd平台。

在早期的CI/CD平台,大家的理解就是 GitLab + Jekins ,Build Tool + Pipe Line

当然,这仍然是核心,但要真正让这个平台有用,还有非常多的细节。

1.2:EDA软件的功能

首先,我们还是来看一下一款EDA工具,它本身是做什么的。

我们仍然以FPGA的EDA工具为例,上图可以非常清楚看到软件提供了编写逻辑电路,综合,映射,布局,布线,生成位流,烧录到芯片的全过程。

1.3:EDA软件的技术架构图

要完成这个软件,我们来看看它的技术架构,见下图:

我们今天不是讲FPGA的EDA软件是如何实现的,只需要看到它的复杂度即可。从上面的图可以看到,一款EDA软件需要多个模块组成,会严格分为 架构,器件,GUI,综合,技术映射,布局,布线,时序,功耗,位流生成,软件集成,TCL支持,测试等……非常多的模块,而这些模块的技术实际上有很大的差别,需要一个比较庞大的团队来支撑。而要将这些模块串到一起,必须要有一个CI/CD平台。好的,我们终于讲到正题了。

1.4:EDA CI/CD 平台的架构

所以,我画一下CI/CD平台的流程,如下:(后面我们会按照这张图,来介绍CI/CD平台需要完成的事情,并不会讲实现的细节哈)

2:开发环境搭建

EDA 软件,一般是采用C++来开发,因为需要极致性能,这方面 C++ 是王者。当然,对于GUI,有可能会使用其它语言。今天我们以全C++的开发语言为例。

因此,我们可以认为这个EDA工个由多个子模块组成,每个开发人员都身处在每个模块中。

由于EDA软件会有非常强的安全要求,所以,一般公司会将代码放到物理隔离的红区,而且也不允许大家跨组查看其它组的代码。但是,又需要随时获取最新代码来完成集成和测试。这差不多是开发环境的基本需求。

于是,代码仓一定是多个,首先,需要搭建多仓的开发环境。

2.1:多仓开发环境

EDA软件本身是一个非常庞大的工程,需要有多个领域的开发人员参与,模块众多,为了开发效率和代码安全,分成多个代码工程,使用 Git 管理代码,Gitlab作为管理平台,完成代码储存、版本控制、代码权限控制等。

注意:git仓禁止 force push(切记,切记)

考虑不同模块和角色的人拥有的权限不同,使用google 提供的 Repo 进行多仓管理,为不同角色的开发者生成不同的manifest,获得不同的代码工程的组合。对于repo的使用(一般不会用到),

git仓的权限,需要通过公司的流程申请获得。原则上按最小权限授予。

如何获取最新代码呢?

一般会给开发提供一个快速的命令:比如 repo_xxx_clone:基于个人权限拉取工程到开发者本地目录(依次将有权限的git工程clone到本地)。对于每个仓的权限管理,当然是使用gitlab的权限管理工具。

如何更新代码环境?

一般会封装一个 xxx_update命令: 获取最新工程代码,如果权限有变更,将追加新授权的工程,或删除收回权限的工程。这里的好处就是,可以将权限集成到这里。不需要用户去关注自已到底有哪些工程的权限。

2.2:开发环境设置

获取代码后,需要对开发环境进行设置。

【环境设置】

  • 设置软件的主目录——XXX_HOME设置为当前目录,并设置一些与主目录相关的环境变量:注意:这个 XXX_HOME是必须的,因为后续有大量的路径都是基于此。

  • 设置git提交时的用户配置——username , useremail 会取当前用户

  • 装载git commit的拦截程序  这是一种本地检查代码的方法。

好了,这里讲到最关键的点,如果我不能获得全部源代码,我如何进行编译连接?对了,我们会将你没有权限的模块的编译产品(so,dll,以及相应的.h)放入到一个特殊的预置仓,你可以随时拉取最新的预置库,通过链接SO的方式来完成程序的构建。

当然,初期也可以存在全源码的构建方式,但一般随着软件的成型,一般不再允许有人拥有全部代码的权限,这样很不安全。

2.3:三方依赖库管理

这里注意一下,我们一定存在直接引用的三方仓库,但是在引用前,一定要做安全准入审查,保证它是合法的,不会有license上的问题(哪果公司有法务,可交给法务判断)。一般对于MIT,Aparch, LGPL等协议可以安全使用(商务无需开源发布)。如果对于三方库来源不信任,可能还需要做一些安全扫描。

依赖的三方仓一般会有几种用法:

  • 动态库引用,这是最常见的用法。

  • 基于三方开源代码(允许修改),需要做少量的修改和维护。

  • 商业购买的三方代码,这各可以按自研源码处理。

  • 头文件使用,三方库只有头文件,直接在源码仓中引入使用。

  • 静态库方式使用。

这里要注意一点,为了保证三方仓的代码可以溯源,一般最好是建立三方仓的源码仓库,自行按需编译生成相应的动态库,这样,可以保证我们产品出问题,可以找到相应的源码,进行调试。

2.4:多分支协同开发规范

一般是创建main分支作为主干,用于存储完整的最新代码。

所有正式的对外发布版本,会创建一个对应的发布分支。

实际开发时,各开发小组自行创建开发分支,当然,也可以统一建议特性开发分支,这个一般不做强行要求,看项目的复杂度了。

对分支需要有相应的管理,一般来说,main分支,原则上只能通过MergeRequest合入,并且只有Leader可以有最终的Merge权限。

发布分支,一般有更严格的合入要求(因为是要正式发版的),在正式发布前的某个时间点,会锁定分支,集体评审后,专人合并(保证代码质量)。

开发分支,一般可以不做管控,创建,权限管理,销毁由各开发小组自行管理。原则上是在开发分支完成基本模块的开发和测试,然后合并到main分支或者发布分支。所有合并到发布分支的内容,原则上都应该在main分支中存在。

注意:代码入主干和发布仓会触发门禁和冒烟,如果不成功,无法入仓,这样用来保证代码质量。这是最关键的,如何做到,后面会讲。

3:代码质量

代码质量如何保证?最容易想到是单元测试,然后就是各种静态,动态检查工具。

3..1:单元测试

要选定单元测试框架,推荐使用 google test 框架。

这里的单元测试代码会作为入仓前的冒烟用例,用来守护代码的质量。

3.2:代码检查

对于提交的代码,一般会进行一些检查,某些情况会拦截,某些情况给出提示。

建议的检查项如下(只是建议)

检测项检查规则动作备注
FileType检测提交文件类型,检查是否非代码文件拦截不能直接提交编译后的产物,无法保证找到原码。
FileName检测提交文件名字,检查是否重名文件拦截会有编译错误
CopyRight检测提交文件内容,是否有CopyRight声明提示不合规
FuncLen检测提交文件内容,函数的行数超100提示过于复杂的函数
Cpplintcpplint检测提交文件内容,存在error的文件拦截是否出现error,每个工程有不同的配置
MVG检测提交文件圈复杂度,默认拦截超过最大圈复杂度的提交拦截逻辑过于复杂,分支过多

3.3:代码静态检查

CppLint

cpplint是最常用的,检查项目非常多,可以自行网上搜索。

Cloc

主要用于做代码的统计。

Cppncss

主要用于代码(非注释)的统计。

Flawfinder

寻找代码潜在的安全漏洞(主要用于C,C++代码)。

pmd_cpd

检测代码中可能重复(复制,粘贴)的代码,去除冗余,提升代码质量。

Simian

查找分析重复或者相似的代码。

Cccc

专注代码复杂度,代码统计。

代码统计:代码行数(包括注释行,空白行,代码行),用于估计代码规模

代码复杂度:圈复杂度,衡量代码逻辑的复杂性。

代码质量评估:类的耦合性,类之间的继承分析

对代码进行增量检测或定期扫描(注意:需要在流水线中设置,定期检查)。

在开发初期,大家代码质量不太行,可以适度放宽检查,比如:建立一个配置表,让各小组自行选择此阶段要检查的项目。

3.4 代码动态分析

通过测试用例,在运行时统计代码覆盖率,用于覆盖率分析。

gcov

代码覆盖率分析:查找未被测试覆盖的代码。

执行频率分析:代码行执行次数,发现热点代码和冗余代码。

分支覆盖率:测试条件判断分支是否补充分测试。

3.5 代码内存分析

常用的两种方式,ASAN方式,Valgrind 方式

ASAN方式

使用 构建的 ASAN版本(添加可调试的符号),运行用例 ,查看输出的报告。

Valgrind方式

使用普通的调试版本即可。但需要依赖 valgrind工具。无需要源码。

valgrind --leak-check=full --track-origins=yes ./program

3.6 检查策略

为了保证代码质量,采用多种策略进行检查。

本地commit前检查(拦截或提示)

在本地代码执行 git commit 时,可以挂钩自已的程序,然后定制代码检查。

也可以定期生成报告,输出质量报告查看质量。

4:代码构建

好了,开始讲最重要的代码构建,下面以 linux的make方式构建为例:

4.1:make构建(linux)

经典构建框架:

        Makfile.top

        Makefile.temp

        Makefile.com

MakeFile:凡是要参与构建的模块,需要定义Makefile

解析顶层参数:All,Release,Debug,ASAN,Clean,HeadList,checkHeads

MODULES:包含嵌套的需要处理的子目录(模块)

…… 可输出静态库,动态库,可执行文件的参数 ……

Include Makefile.top

  解析Modules,完成向子模块传递构建。

  Include Makefile.temp    Include makefile.com

      定义通用的三方库的引用

       解析编译,输出参数,完成核心构建

 

构建有如下的输出:

  • 子模块构建

在comp/子模块构建,输出 .so 动态库,或者.a 静态库

  • 合并子模块构建

将多个模块合并成一个库,这是常见的,否则容易暴露产品的实现细节,一般最后做一次合并。

  • 构建可执行程序

在prog/子模块构建,输出 .sh 可执行程序。

  • 预置库的构建

      本地缺失的源码,使用 Prebuild_lib的动态库。这是开发端最常见的构建方式。

      请注意,请及时更新最新的Prebuild_lib中的动态库。可使用 update_api

  • 全源码构建

      通常在系统平台的流水线中的使用,完成正式的构建。

  • 清理构建输出物

      清理构建的全部输出。

  • 头文件依赖检测

      检测头文件的依赖关系。

重要命令

  • xxx_build

配置:debug / release / asan

模块:all / gui / clean

预制库的更新

  定时重新生成所有的动态库,更新到 Prebuild_lib 仓库,包括API头文件。

保证开发人员可以及时获取最新的Prebuild_Lib。

构建的定期检查

循环构建,完成预制库的输出的同时,保证代码可正常编译。如有问题,及时报警。

构建加速

        构建速度非常重要,除了需要配置更好的物理资源,也可做如下的优化。

  • 增量编译

  • 缓存处理

  • 分布式编译

对于 cmkae 和 windows的构建,这里就不讲了。

5:代码入仓

5.1:MR入仓

代码进入Main和 Release_XXX仓,原则上不提倡直接Push(少数人也此权限),而是建议采用MergeRequest入仓,因为在MR前会有若干的处理,可以对入仓的代码进行检查,不符合要求将会被拦截。

  • 触发流水线

  通过配置 Webhooks,MR时调用 Jekins提供的流水线,

  • 获取代码

  将需要MR的代码和正式仓代码进行合并,生成完整代码

  • 门禁检查

        尝试对源代码进行多种build,检查是否可正常。

  • 冒烟检查

  运行预置的单元测试,检查关键用例是否可正常执行。

  • Rebase处理

  建议对代码进行Rebase,这样保证可保留所有提交历史。

5.2:门禁检查

调用全源码的构建:(这里并不输出结果,只是借用构建查看代码是否正常)

  • Liunx debug build

  • Linux Release lbuild

  • Windows build

任何一个构建失败,整体门禁检查失败。

这是非常重要和关键的一个步骤,可保证入仓代码的质量。

5.3:冒烟测试

冒烟测试可提供配置文件:让各模块的人员配置对应的单元测试。

  [Basic]:每次必须要执行的用例 这个理解为主流程

  [模块名]:匹配当前MR的工程模块,匹配上的话就执行用例的shell脚本 返回 0 成功

5.4:多仓联合提交

某些情况,存在多仓提交,需要采用多仓联合构建的方式。具体略,需要将仓暂时进行锁定,保证一致性。

5.5:PrebuildLib 入仓

持续构建生成so,定时提交仓库,备用。

同时,达成检测代码可用性的目标。这个很关键,否则,开发人员的工作无法进行。

6: 打包输出

输出多种版本,用于后续的测试或支撑继续开发。这是持续交付的关键,可以让测试的流程快速闭环起来。

6.1 打包输出流程

建议流程如下:打包输出流程主要定义为下面几个步骤,可定制。

  • pre_build

在build前的一些参数预置,根据实际输出的需要,进行设置

  • build

实际的build过程,一般是先清理,然后 make all

  • pre_pack

pack前的预处理,可以交给各模块自行编写脚本插入。比如:生成Primitive 的 HDL templates.

  • Pack

可定制打包最后需要追加和忽略的文件。

  • Post_pack

pack的后处理,比如:将tcl script 进行加密处理。

 

6.2 重要输出

  • 输出的控制点

        选用的代码不同,可能是Main,可能是某个Release分支。

        支持哪些器件

        是否进行License管控

        是否提供内部feature

        parm的默认参数值

        tcl命令开放列表

  • 输出的所有版本

        对控制点不同的配置,形成多种输出

        1:内部测试版本——用于内部的开发测试

        2:软件部的外部测试版本——给到软件部以外的部门,如:市场,validation,回片 进行测试

        3:面向客户的版本——给到正式客户的版本。

        4:合作商的版本——提供给我们的集成商的特殊版本,比如:给到 mentor的合作版本

        5:DFT测试版本——提供给DFT测试的版本

  • 输出的周期

这个按需提供。可能是每日定点,每周……

  • 重要的输出流程

这个看公司的需求,成熟度不同的阶段,会有不同的测试粒度。

7:安装包发布

7.1 制作安装包

分为Linux版本和Windows版本的打包。

完成安装包文件的SHA验证码

安全检查

提供发版文件,提供安装手册。

上架发布(可能是网站或者其它方式)

7.2:License处理

提供浮动版和单机版License。

确定license申请和绑定的流程,提供相应的审批流,并记录背后的申领数据。

8:工具平台支撑

8.1:调度流水线

提供Jekins Pipeline 流水线,按时间,完成定时调度,或主动触发,可以定制完整的flow。

除了为各种输出提供流水线,也为日常的测试提供调度配置。

比如:DailyTest,QoRTest,RuntimeTest,CustomerTest,WeeklyTest,GUITest。

8.2 监控预警

提供预警API,用公司的协同工具完成消息推送。

 预警点:环境输出失败,门禁失败,打包失败……

监控这里更多指的是必要服务的可用性监控,或者说是质量的看护监控,这个都需要自定义脚本来完成。

8.3 数据分析

代码质量看板

提供质量看板,为测试组提供代码覆盖率、缺陷率、代码量的持续监控看板,提高问题洞察效率。 

Git仓授权检视
代码提交量统计

更多…… 注意,这里需要选用一款报表系统,进行可视化的展示。取数和加工根据实际情况进行开发。

8.4 安全加密

提供非对称密钥对,公钥在代码内置,私钥在打包时构建入代码。

加密工具可以将用户的代码进行加密,然后只能在EDA软件中安全使用。这样,可以保护用户和我司的代码。

用户也可以使用提供的加密工具,对代码进行加密,然后在EDA中使用。

这个很重要,因为客户的代码是绝密的,必须要想办法保护,在交付三方时,可以使用,但不可见源码。

8.5 三方集成

CI/CD平台需要与 协同工具,Gitlab,Jenkins等平台进行集成,比如:Git自动授权,代码权限审视,代码仓锁库,消息通知等。

8.6 现场调试

需要提供现场调试的能力,因为某些情况,只能在客户现场重现问题。

我们只能将某部分代码重编后,在客户现场通过GDB来调试。

现关的实现。略。

以我的经验,大概就讲这么多了,也摘自之前的总结。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2252061.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux命令进阶·如何切换root以及回退、sudo命令、用户/用户组管理,以及解决创建用户不显示问题和Ubuntu不显示用户名只显示“$“符号问题

目录 1. root用户(超级管理员) 1.1 用于账户切换的系统命令——su 1.2 退回上一个用户命令——exit 1.3 普通命令临时授权root身份执行——sudo 1.3.1 为普通用户配置sudo认证 2. 用户/用户组管理 2.1 用户组管理 2.2 用户管理 2.2.1 …

网络安全-AAA介绍与配置

前言 AAA是Authentication(认证)、Authorization(授权)和Accounting(计费)的简称,它提供了认证、授权、计费三种安全功能。AAA可以通过多种协议来实现,目前华为设备支持基于RADIUS&a…

[ACTF2020 新生赛]BackupFile--详细解析

信息搜集 让我们寻找源文件,目录扫描: 找到了/index.php.bak文件,也就是index.php的备份文件。 后缀名是.bak的文件是备份文件,是文件格式的扩展名。 我们访问这个路径,就会直接下载该备份文件。 我们把.bak后缀删掉…

软考高项经验分享:我的备考之路与实战心得

软考,尤其是信息系统项目管理师(高项)考试,对于众多追求职业提升与专业认可的人士来说,是一场充满挑战与机遇的征程。我在当年参加软考高项的经历,可谓是一波三折,其中既有成功的喜悦&#xff0…

Kubernetes常见问题解答

云原生学习路线导航页(持续更新中) 快捷链接 Kubernetes架构原则和对象设计 本文对Kubernetes学习中常见的一些问题,进行解答 1.什么时候使用公有云,什么时候使用自建k8s 看公司规模,规模小使用公有云,规…

基于C#+SQLite开发数据库应用的示例

SQLite数据库,小巧但功能强大;并且是基于文件型的数据库,驱动库就是一个dll文件,有些开发工具 甚至不需要带这个dll,比如用Delphi开发,用一些三方组件;数据库也是一个文件,虽然是个文…

C++高阶算法[汇总]

(一)高精度算法概述 高精度算法是指能够处理超出常规数据类型表示范围的数值的算法。在 C 中,标准数据类型通常有固定的位数和精度限制,而高精度算法可以解决大数运算、金融计算和科学计算等领域的问题。 (二&#x…

JS API事件监听(绑定)

事件监听 语法 元素对象.addEventListener(事件监听,要执行的函数) 事件监听三要素 事件源:那个dom元素被事件触发了,要获取dom元素 事件类型:用说明方式触发,比如鼠标单击click、鼠标经过mouseover等 事件调用的函数&#x…

【C语言】二叉树(BinaryTree)的创建、3种递归遍历、3种非递归遍历、结点度的实现

代码主要实现了以下功能: 二叉树相关数据结构定义 定义了二叉树节点结构体 BiTNode,包含节点数据值(字符类型)以及指向左右子树的指针。 定义了顺序栈结构体 SqStack,用于存储二叉树节点指针,实现非递归遍历…

Three.js 和其他 WebGL 库 对比

在WebGL开发中,Three.js是一个非常流行的库,它简化了3D图形的创建和渲染过程。然而,市场上还有许多其他的WebGL库,如 Babylon.js、PlayCanvas、PIXI.js 和 Cesium,它们也有各自的特点和优势。本文将对Three.js 与这些常…

[pdf,epub]228页《分析模式》漫谈合集01-45提供下载

《分析模式》漫谈合集01-45的pdf、epub文件提供下载。已上传至本号的CSDN资源。 如果CSDN资源下载有问题,可到umlchina.com/url/ap.html。 已排版成适合手机阅读,pdf的排版更好一些。 ★UMLChina为什么叒要翻译《分析模式》? ★[缝合故事]…

CAD深度清理工具-AVappsDrawingPurge9.0.0(2024.8.27版本) 支持版本CAD2022-2025-供大家学习研究参考

图形文件DWG体积很大:通常没有明显的数据。同时,还其他症状包括: (1)无法复制和粘贴图元。 (2)悬挂较长时间选择文本与 “特性”选项板上打开。 (3)图形文件需要很长时间…

kafka数据在服务端时怎么写入的

学习背景 接着上篇,我们来聊聊kafka数据在服务端怎么写入的 服务端写入 在介绍服务端的写流程之前,我们先要理解服务端的几个角色之间的关系。 假设我们有一个由3个broker组成的kafka集群,我们在这个集群上创建一个topic叫做shitu-topic&…

Rook入门:打造云原生Ceph存储的全面学习路径(上)

文章目录 一.Rook简介二.Rook与Ceph架构2.1 Rook结构体系2.2 Rook包含组件2.3 Rook与kubernetes结合的架构图如下2.4 ceph特点2.5 ceph架构2.6 ceph组件 三.Rook部署Ceph集群3.1 部署条件3.2 获取rook最新版本3.3 rook资源文件目录结构3.4 部署Rook/CRD/Ceph集群3.5 查看rook部…

[STM32] ADC 模数转换器 (十)

文章目录 1.ADC概述1.1 转换模式(规则组)1.2 数据对齐1.3 转换时间1.4 校准 2.代码步骤 STM32F103C8T6的12位逐次逼近型ADC的工作原理,包括转换模式、数据对齐、转换时间、校准以及程序配置流程,同时涵盖了关键的库函数和中断管理…

Web3.0安全开发实践:代理合约最佳实践总结

代理模式使智能合约能够升级其逻辑,同时维持其链上地址和状态值。对代理合约的调用会通过delegateCall的方式执行来自逻辑合约的代码,以修改代理合约的状态。 本文将为大家概述代理合约的类型、相关的安全事件和建议,以及使用代理合约的最佳…

第29天 MCU入门

目录 MCU介绍 MCU的组成与作用 电子产品项目开发流程 硬件开发流程 常用元器件初步了解 硬件原理图与PCB板 常见电源符号和名称 电阻 电阻的分类 贴片电阻的封装说明: 色环电阻的计算 贴片电阻阻值计算 上拉电阻与下拉电阻 电容 电容的读数 二极管 LED 灯电路 钳位作…

【人工智能基础05】决策树模型

文章目录 一. 基础内容1. 决策树基本原理1.1. 定义1.2. 表示成条件概率 2. 决策树的训练算法2.1. 划分选择的算法信息增益(ID3 算法)信息增益比(C4.5 算法)基尼指数(CART 算法)举例说明:计算各个…

数据结构与算法(排序算法)

我本将心向明月,奈何明月照沟渠。 排序的概念 1. 排序是指将一组数据,按照特定的顺序进行排列的过程。 2. 这个过程通常是为了使数据更加有序,从而更容易进行搜索、比较或其他操作。 常见的排序算法 插入排序 1. 把待排序的记录&#xff0c…

思科实现网络地址转换(NAT)和访问控制列表(ACL)和动态路由配置并且区分静态路由和动态路由配置。

实验拓扑(分为静态路由和动态路由两种) 静态路由互通 动态路由互通 实验背景 这个是想实现外网与内网的连接跟网络的探讨,最终实现互通以及使用并且在网络地址转换后能使用网络然后再这个基础上再配置访问控制列表和网络地址转换的的学习过程。 实验需了解的知识…