当前位置: 首页 > news >正文

HNU-计算机体系结构-实验2-Tomasulo算法

计算机体系结构 实验2

计科210X 甘晴void 202108010XXX
在这里插入图片描述

1 实验目的

熟悉Tomasulo模拟器同时加深对Tomasulo算法的理解,从而理解指令级并行的一种方式-动态指令调度。

掌握Tomasulo算法在指令流出、执行、写结果各阶段对浮点操作指令以及load和store指令进行什么处理;给定被执行代码片段,对于具体某个时钟周期,能够写出保留站、指令状态表以及浮点寄存器状态表内容的变化情况。

学习ScoreBoard和Tomasulo算法,并且进行Tomasulo算法的模拟实验,同时熟悉动态指令调度相关知识。

【注】由于老师之前花了三节课时间详细讲解了ScoreBoard和Tomasulo算法,故本实验实际上较为简单,主要是理解。

参考资料:

  • Tomasulo算法模拟器使用方法.doc
  • 芜湖韩金轮:https://blog.csdn.net/qq_51684393/article/details/134891988

2 实验过程

2.0 环境配置

本实验单独使用模拟器Tomasulo.exe,无其它环境配置问题。

2.1 基础知识

①动态调度算法Tomasulo

主要与ScoreBoard差不多,不同点大致在将READ和EXE合并为一个EXE步骤,另外就是寄存器重命名(保留站只保留副本而不是寄存器本身),和广播机制。

我做了一个总结如下,按照这个操作基本上就能跑起来了。

在这里插入图片描述

下面是使用模拟器的教程。

②设置指令和参数

指令种类

  • L.D指令:从主存读取一个双精度浮点数;
  • ADD.D:双精度浮点加法指令;
  • SUB.D:双精度浮点减法指令;
  • MULT.D:双精度浮点乘法指令;
  • DIV.D:双精度浮点除法指令。

各指令执行时间

  • 不同部件,尤其是浮点功能部件,它们的执行时间往往是不同的。特别是除法部件,往往要延迟很多周期。模拟器中可以设置这个时间。

复位

  • 所有设置恢复默认值
③执行
  • 点击“执行”按钮,就进入执行状态。可以用中间的按钮来控制指令的执行,包括“步进”、“退1步”、“前进5个周期”、“后退5个周期”、“执行到底”、“退出”等。还可以用“go”按钮直接跳转到指定的时钟周期。
  • 如果想修改被执行的代码,按“退出”按钮,即可回到设置指令和参数页面。
  • 向前执行后,状态表中抹色的字段表示其内容发生了变化。
④对比状态表
  • 每一个状态表的右上角外侧都有一个小三角,用鼠标左键点击它,会弹出该表在上一个时钟周期的内容。
  • 在弹出表以外的区域再次点击鼠标,就可以将其收回。
⑤各表内容

【指令状态表】列出了各指令什么时候执行到了哪一步。其中的数字表示时钟周期,“~”表示时钟周期期间。

【保留站】给出了各执行部件是否被占用,以及其在该时刻的寄存器依赖信息(是在执行?还是因为哪个寄存器而不能执行?)。其中各字段的名称和含义如下:

  • Time:表示相应的保留站还有要执行多少个时钟周期;
  • 名称:保留站的名称。用于唯一地标识相应的保留站;
  • Op:要对源操作数进行的操作;
  • Qj,Qk:将产生源操作数的保留名称。等于0表示操作数已经就绪且在Vj或Vk中,或者不需要操作数。
  • Vj,Vk:源操作数的值。对于每一个操作数来说,V或Q字段只有一个有效。
  • Busy:为“Yes”表示该保留站 “忙”。

【Load部件】按队列方式工作,每次处理新的访存都是从队列头部取走一条。其中各字段的含义如下:

  • 名称:相应单元的名称(标识);
  • Busy:“忙”标志,为“Yes”表示已被占用;
  • 地址:访存的有效地址;
  • 值:存放从存储器读来的数据。

【寄存器】指明此时寄存器是否被指令占用(需要写回),以及此时的值。该缓冲器各字段的含义如下:

  • 【请注意】这里指导手册上写的是有问题的,与课堂上老师讲的不同,这里有一个BUSY字段比较隐晦难以看到。Qi表示将把结果写入该寄存器的保留站的站号,BUSY字段表示是否被占用。老师上课讲的是,指令写回后擦除Qi字段,但是这个模拟器是把BUSY置空即可,相当于擦除了Qi。也即:只有BUSY为被占用,Qi才有效。
  • Qi:寄存器状态,用于存放将把结果写入该寄存器的保留站的站号。
  • 值:寄存器的值。
  • BUSY:是否被占用。为空则表示当前没有正在执行的指令要写入该寄存器,也即该寄存器中的内容就绪。

最下面,把上面两个值压缩一下,就会出现BUSY字段(这个UI界面怎么这么糟糕)

在这里插入图片描述

当上述表中的内容写不下时,模拟器会采用缩写的方法。这时,在上面中间的区域中会显示缩写及其值。

2.2 模拟算法,回答问题

使用模拟器进行以下指令流的执行并对模拟器截图、回答问题

L.D   F6, 21(R2)
L.D   F2, 0 (R3)
MUL.D  F0, F2, F4
SUB.D  F8, F6, F2
DIV.D  F10,F0, F6
ADD.D  F6, F8, F2

假设浮点功能部件的延迟时间:加减法2个周期,乘法10个周期,load/store2个周期,除法40个周期。

设置如下:

在这里插入图片描述

问题如下:

  • 分别截图(当前周期2和当前周期3),请简要说明load部件做了什么改动
  • 请截图(MUL.D刚开始执行时系统状态),并说明该周期相比上一周期整个系统发生了哪些改动(指令状态、保留站、寄存器和Load部件)
  • 简要说明是什么相关导致MUL.D流出后没有立即执行
  • 请分别截图(15周期和16周期的系统状态),并分析系统发生了哪些变化
  • 回答所有指令刚刚执行完毕时是第多少周期,同时请截图(最后一条指令写CBD时认为指令流执行结束)
问题1

分别截图(当前周期2和当前周期3),请简要说明load部件做了什么改动

当前周期2

在这里插入图片描述

第一条Load指令进入执行1阶段,计算出R[R2]+21并保存在Load1的寄存器中。

第二条Load指令发射,分配使用Load2部件,Busy位置Yes。

当前周期3

在这里插入图片描述

第一条Load指令进入执行2阶段,访存并获得M[R[R2]+21],保存在Load1部件的值寄存器中。

第二条Load指令进入执行1阶段,计算出R[R3]+0并保存在Load2的寄存器中。

问题2

请截图(MUL.D刚开始执行时系统状态),并说明该周期相比上一周期整个系统发生了哪些改动(指令状态、保留站、寄存器和Load部件)

MULT.D开始执行前一步的系统状态

在这里插入图片描述

MULT.D开始执行时的系统状态

在这里插入图片描述

下面比较指令状态、保留站、寄存器和Load部件发生的改动。

  • 指令状态:由于MULT和SUB使用的部件不同,且该步没有寄存器相关的冲突(在前一步,也就是第5步,Load操作写回F2,解除了F2的依赖),故可以同时进入执行状态。又第6条ADD指令的写回寄存器F6刚被Load1指令释放,恰好可以被ADD指令使用,故ADD指令被发射。
  • 保留站:主要是把ADD指令相关的信息写入部件ADD2,BUSY位置1,Op位为ADD,此时ADD需要F2和F8的值,但是F8此时还被前面的SUB指令(ADD1部件)占用(寄存器中F8的Qi字段为ADD1),故Vj空置,Qj写入Add1,由于F2此时已经被释放,Vk可以写入F2的对应值M2(具体问题能算出M2的具体数值,但这里直接给了个未知数代替,是一样的)
  • 寄存器:ADD的目的地址是F6,故F6的Qi字段写入F6.
  • Load部件:该两部未发生访存,也没有Load指令在执行,故无事发生。
问题3

简要说明是什么相关导致MUL.D流出后没有立即执行

简单来说,MULT.D依赖的F2寄存器直到第5周期才被Load2指令写回,故MULT.D只能在第6周期进入执行阶段。

MULT.D指令在第3步流出(即被发射),

目的寄存器是F0,写入【寄存器】部件,

其源寄存器分别是F2和F4,查表【寄存器】部件,发现F2此时被Load2部件占用,将这一信息写入【保留站】中,即Qj字段,

那么只有在F2的占用结束时,MULT.D才能执行。

在这里插入图片描述

问题4

请分别截图(15周期和16周期的系统状态),并分析系统发生了哪些变化

第15周期

在这里插入图片描述

第16周期

在这里插入图片描述

该两步主要聚焦MULT结束它漫长的执行周期后发生的事情。

主要是两件事情:释放部件,更新保留站。

第15周期,MULT结束了它的执行。第16周期,MULT写回F0的结果。并释放自己占用的MULT1部件。同时系统检索整个【保留站】,并释放所有在Qj或Qk字段被打上【因为MULT1部件,而不能执行】的这些行,在vj或vk补上F0的结果。

事实上,这里的DIV指令在第5周期被发射之后,就一直在等待F0被解除占用,现在在第16周期,终于由于MULT更新F0值解除了占用。

下一周期,第17周期,DIV指令进入执行阶段。

问题5

回答所有指令刚刚执行完毕时是第多少周期,同时请截图(最后一条指令写CBD时认为指令流执行结束)

所有指令刚刚执行完毕是第57周期。DIV.D指令在第56周期被执行完毕,在第57周期被写回。

在这里插入图片描述

2.3 思考题

问题1

Tomasulo算法相比Score Board算法有什么异同?(简要回答两点:1.分别解决了什么相关问题,2.两者分别是分布式还是集中式)

分别解决的问题

  • Tomasulo算法和Scoreboard算法都解决了指令级并行处理器中的数据相关性问题。
  • Tomasulo算法通过寄存器重命名和乱序执行技术更有效地解决了数据相关性,允许指令乱序执行,提高了并行度和吞吐量。
  • Scoreboard算法通过中心化的控制单元管理指令的发射和执行,依赖于指令执行的严格顺序,处理数据相关性。

分布式与集中式

  • Tomasulo算法是一种分布式的指令调度算法,每个执行单元都具有独立的调度器,能够并行地调度指令,处理器中各个部分之间通过共享总线或其他通信方式进行通信。
  • Scoreboard算法是一种集中式的控制方法,通过中心化的控制单元管理指令的发射和执行,指令的执行顺序由中心控制器决定,整个处理器的调度是由中心控制器统一管理的。

为什么Tomasulo比ScoreBoard效率更高:

①ScoreBoard存在结构冲突,未使用定向技术

②Tomasulo的WAW和WAR不需要stall,而scoreboard需要检测与stall

问题2

Tomasulo算法是如何解决结构冒险、RAW、WAR和WAW相关的数据冒险?

Tomasulo算法通过以下3个方法解决数据相关性引起的结构冒险、RAW、WAR和WAW相关的数据冒险:

  • 寄存器重命名(Register Renaming):Tomasulo算法使用物理寄存器来存储指令操作数的结果,而不是使用程序中的逻辑寄存器。这样,即使多个指令试图同时写入相同的逻辑寄存器,也不会导致WAR和WAW相关。每个操作数都与一个唯一的物理寄存器相关联,从而避免了数据冒险。(即取了副本而不是寄存器本身)
  • 乱序执行(Out-of-order Execution):Tomasulo算法允许指令按照它们的操作数可用性而不是它们在程序中的顺序来执行。这种乱序执行可以有效地解决RAW相关,因为当一个指令的操作数可用时,它就可以立即执行,而不必等待前面的指令。(这一点ScoreBoard也做到了)
  • 数据依赖检测(Data Dependency Checking):Tomasulo算法中的每个执行单元都会检查指令的操作数是否已经准备好。如果操作数还未准备好,执行单元将等待,直到相关的操作数变为可用。

通过这些技术,Tomasulo算法能够在执行指令时动态地解决结构冒险、RAW、WAR和WAW相关的数据冒险,从而提高了指令级并行处理器的性能和效率。

下面我给出具体示例来说明。

读后写(WAR)冒险

在这里插入图片描述

写后读(RAW)冒险

在这里插入图片描述

写后写(WAW)冒险

在这里插入图片描述

【更进一步讨论极端情况】若两条WAW之间有需要读取F10,第一个W写完之后要更新【保留站】内的逻辑寄存器,但不更新回【寄存器】表内的物理寄存器,因为它已经被后一个W给锚定了。

3 实验总结

本次实验中,我深入研究了动态指令调度算法以及其在指令级并行处理器中的优化应用。通过对Tomasulo算法和相关概念的探索,我得以更全面地理解现代处理器如何通过动态指令调度来提高性能,并在模拟环境中进行了实际操作和观察。

  • 算法原理的理解与应用: 通过实验,我对Tomasulo算法及其在处理器设计中的作用有了更深入的理解。该算法通过寄存器重命名、乱序执行和指令调度等技术,有效解决了数据相关和控制相关问题,实现了指令级并行,从而提高了处理器的吞吐量和性能。
  • 模拟实验的操作与观察: 通过使用Tomasulo模拟器,我能够模拟指令的执行过程,观察指令之间的依赖关系和执行顺序,以及调度单元的工作状态。这些实际操作让我更直观地理解了动态指令调度算法的实际应用,以及在不同场景下的性能表现。
  • 理论与实践相结合的学习: 这次实验不仅强调理论知识的学习,更注重将理论知识应用于实际情境的实践。通过理论分析和模拟实验相结合的方式,我不仅学会了算法的原理,还能够将其应用于实际的处理器设计中,从而更好地理解和掌握动态指令调度的核心思想和实现方式。
  • 深化对处理器性能优化的认识: 通过这次实验,我进一步认识到动态指令调度在处理器性能优化中的重要性。优秀的动态指令调度算法能够有效地提高处理器的并行度和吞吐量,从而加速程序的执行,提升系统的整体性能。

通过本次实验,我不仅加深了对动态指令调度算法的理解,还学会了如何将其应用于指令级并行处理器的优化设计中。这为我今后在计算机体系结构和并行计算领域的学习和研究提供重要的理论基础和实践经验。

相关文章:

HNU-计算机体系结构-实验2-Tomasulo算法

计算机体系结构 实验2 计科210X 甘晴void 202108010XXX 1 实验目的 熟悉Tomasulo模拟器同时加深对Tomasulo算法的理解,从而理解指令级并行的一种方式-动态指令调度。 掌握Tomasulo算法在指令流出、执行、写结果各阶段对浮点操作指令以及load和store指令进行什么…...

深入分析 Android Activity (一)

文章目录 深入分析 Android Activity (一)1. Activity 的窗口管理2. Activity 的生命周期管理onCreateonStartonResumeonPauseonStoponDestroyonRestart 3. Activity 与 Fragment 的交互添加 FragmentFragment 的生命周期 4. Activity 的任务和返回栈5. 配置变化处理 总结 深入…...

Python 调整PDF文件的页面大小

在处理PDF文件时,我们可能会遇到这样的情况:原始PDF文档不符合我们的阅读习惯,或者需要适配不同显示设备等。这时,我们就需要及时调整PDF文档中的页面尺寸,以满足不同应用场景的需求。 利用Python语言的高效性和灵活性…...

支付功能、支付平台、支持渠道如何测试?

有学员提问:作为一个支付平台,接入了快钱、易宝或直连银行等多家的渠道,内在的产品流程是自己的。业内有什么比较好的测试办法,来测试各渠道及其支持的银行通道呢? 作为产品,我自己办了十几张银行卡方便测…...

永久代(Permanent Generation)和元空间(Metaspace)

永久代(Permanent Generation)和元空间(Metaspace)是Java虚拟机(JVM)内存管理中的两个概念,主要区别在于它们的实现方式和内存分配策略。 永久代(Permanent Generation)…...

前端面试题23-34

23. 说说你对 Promise 的理解 Promise 是 ECMAScript6 引入的一种异步编程解决方案,用于处理异步操作。它表示一个尚未完成但最终会结束的操作,具有三种状态:pending(进行中)、fulfilled(已完成&#xff0…...

Hadoop3:HDFS中DataNode与NameNode的工作流程

一、DataNode中的数据情况 数据位置 /opt/module/hadoop-3.1.3/data/dfs/data/current/BP-823420375-192.168.31.102-1714395693863/current/finalized/subdir0/subdir0块信息 每个块信息,由两个文件保存,xxx.meta保存的是数据长度、校验和、时间戳&am…...

MySQL(一) 库和表的基础操作

1. 数据库基础 1.1 什么是数据库 存储数据用文件就可以了,为什么还要弄个数据库? 文件保存数据有以下几个缺点: 文件的安全性问题文件不利于数据查询和管理文件不利于存储海量数据文件在程序中控制不方便 数据库存储介质:磁盘内存 为了解…...

python -【二】判断语句

判断语句 一、 布尔类型 True&#xff1a;真(1)False&#xff1a;假(0) 比较运算符 运算符实例1 1 True!1 ! 1 Flase<1 < 1 Flse>1 > 1 Flse<1 < 1 True>1 > 1 True b1 True b2 False print(f"b1值是{b1},类型是{type(b1)}") print(…...

高通Android 12/13 设置和获取ADB状态

/*** 设置ADB状态** param isEnable*/public void setADB(boolean isEnable) {Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ADB_ENABLED, isEnable ? 1 : 0);}/*** 获取ADB状态** return*/public boolean getADB() {return Settings.Global.getIn…...

存储器和CPU的连接与TCP的流量控制

存储器与CPU的连接 存储容量的拓展 &#xff08;1)位拓展&#xff1a;增加存储字长 &#xff08;2&#xff09;字拓展 增加存储器字的数量 例题&#xff1a;设CPU有16根地址线&#xff0c;8根数据线&#xff0c;并用MREQ作为访问存储控制信号(低电平有效)&#xff0c;WR作为…...

红蓝对抗提权篇之一文看懂提权

一、计算机中的权限 1.1 不同的权限系统 权限在不同的应用中有着不同的分类&#xff0c;与安全相关的大致上我们分为&#xff1a; 匿名访问权限 来宾权限 用户权限 管理员权限 系统权限 不同的权限对应的权力各不相同&#xff0c;我们对自己电脑一般是用户权限和管理员权限。…...

【Tlias智能学习辅助系统】01 准备工作

Tlias智能学习辅助系统 01 创建员工、部门表创建springboot工程&#xff0c;引入对应的起步依赖(web、mybatis、mysql驱动、lombok)准备 Mapper、Service、Controller 等基础结构MapperServiceControllerpojo封装类application.properties 接口开发规范 创建员工、部门表 -- 创…...

yq—2024/5/29—零钱兑换

代码实现&#xff1a; #define min(a, b) ((a) > (b) ? (b) : (a))int coinChange(int *coins, int coinsSize, int amount) {int dp[amount 1];// 初始化for (int i 0; i < amount 1; i) {dp[i] INT32_MAX;}dp[0] 0;// 01背包 -----先遍历物品&#xff0c;再遍历背…...

【 Quartz框架中各个表及其字段含义】

Quartz框架中各个表及其字段含义 Quartz是一个强大的任务调度框架,它通过在数据库中维护多张表来存储和管理任务信息。了解这些表的结构和字段含义,有助于我们更好地理解Quartz的工作原理,并在实际应用中进行有针对性的优化和管理。 想了解Quartz框架其他信息可以参考下面的博…...

SAP_SD模块 物料科目分配/成本简介

SAP系统各模块与财务都有个方面的集成。文本主要说明销售模块中的科目分配和成本的一个对应关系。 1、首先是在物料主数据上销售视图中的物料科目分配组&#xff0c;S1主营、S2材料等字段&#xff0c;物料销售的时候会将这个物料产生的记录到对应的科目中。 首先是物料主数据中…...

el-select 组件获取整个对象

法一&#xff1a;要获取整个对象的话&#xff0c;如果有列表就可以遍历列表&#xff0c;找到指定对象 let obj this.chainTaskList.find((item) > item.chainTaskNo e); if (obj) {this.form.storeNo obj.storeNo;this.form.storeName obj.couponVO.storeName; }或 fo…...

基础—SQL—DQL(数据查询语言)基础查询

一、引言 1、介绍&#xff1a; 分类全称描述DQL英文全称&#xff1a;Data Query Language(数据查询语言)主要是学习对数据库表中的记录进行查询的语句 2、讲解 日常的开发中或者对于一个正常的业务系统中&#xff0c;对于查询的操作次数是远远多于数据的增删改的频次。例如…...

【QT八股文】系列之篇章2 | QT的信号与槽机制及通讯流程

【QT八股文】系列之篇章2 | QT的信号与槽机制及通讯流程 前言2. 信号与槽信号与槽机制介绍/本质/原理&#xff0c;什么是Qt信号与槽机制&#xff1f;如何在Qt中使用&#xff1f;信号与槽机制原理&#xff0c;解析流程Qt信号槽的调用流程信号与槽机制的优缺点信号与槽机制需要注…...

excel表格里怎样不删除0,又不显示0呢?

在单元格里不显示0&#xff0c;大体上有这么几种方法&#xff1a; 1.设置单元格自定义格式 选中数据区域&#xff0c;鼠标右键&#xff0c;点一下设置单元格格式&#xff0c;选中数字&#xff0c;自定义&#xff0c;在右侧的类型栏&#xff0c;设置格式&#xff1a; [0]&quo…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...