计算机组成原理----计算机系统

news2025/1/15 14:35:00

目录

1.计算机的硬件和软件

2.硬件的发展

3.软件的发展

4.计算机硬件的基本组成

(1)早期冯诺依曼机的结构

(2)现代计算机的结构

5.各硬件的工作原理

(1)主存储器

(2)运算器

(3)控制器

(4)计算机工作过程:

取指令:

分析指令:

执行取数指令:

6.计算机系统的多级层次结构

(1)低级语言

机器语言:

汇编语言:

(2)高级语言

(3)计算机系统的层次结构

(4)三种级别的语言


1.计算机的硬件和软件

计算机组成原理由硬件和软件组成:

硬件:计算机的实体,如主机,外设等。

软件:由具体各类特殊功能的程序组成。

计算机性能的好坏取决于"软","硬"件功能的总结

软件又可分为系统软件,应用软件:

系统软件:用来管理整个计算机系统。例如,操作系统、数据库管理系统(DBMS)、标准程序库、网络软件、语言处理程序、服务程序。

应用软件:按任务需要编制成的各种程序。例如各类APP等。

2.硬件的发展

第一代(电子管时代):

这一代计算机采用电子管作为逻辑元件,体积大,耗电量超大,程序员在纸带机上用机器语言编程,若纸带机上出现"死了的小虫子",可能会导致读程序错误,这就是bug(小虫子)的起源。

第二代(晶体管时代):

使用晶体管作为逻辑元件的电脑,体积比使用电子管作为逻辑元件的电脑体积更小,功耗较低,晶体管是手动焊接在电路板上的,所以很容易导致焊接错误。这一代中,出现了面向过程的程序设计语言:FORTRAN

第三代(中小规模集成电路时代):

集成电路就是将元件集成在基片上,集成电路的可靠性,比晶体管手动焊接的方式更可靠。这一代计算机主要用于科学计算等专业用途,高级语言迅速发展,开始有了分时操作系统。

第四代(大规模、超大规模集成电路时代):

开始出现"微处理器"、微型计算机,并且个人计算机(PC)萌芽

操作系统:Windows、MacOs、Linux...

3.软件的发展

(1)应用软件

编程语言的发展,决定了应用软件的丰富度。在计算机发展初期,程序都需要用机器语言编写,由于机器语言可读性差,所以发明了汇编语言。汇编语言将机器语言翻译为了更易懂的符号。而后出现了高级语言(C++,Java等)。

(2)系统软件

初期的操作系统,如DOS操作系统,只能用命令行操作,后期则出现了包含图形化界面的操作系统,如Windows,Android等

目前计算机存在"两极"分化的发展趋势:

一极是微型计算机,向更微型化、网络化、高性能、多用途方向发展。

另一极是巨型机,向更巨型化、超高速、并行处理、智能化方向发展。

4.计算机硬件的基本组成

(1)早期冯诺依曼机的结构

早期的ENIAC计算机是通过手动接线来控制计算的,即说一步做一步,为了解决这个问题,冯诺依曼提出了”存储程序“

“存储程序”的概念是指将指令以二进制代码的形式事先输入计算机的主存储器,然后按其在存储器中的首地址执行程序的第一条指令,以后就按该程序的规定顺序执行其他指令,直至程序执行结束。

冯诺依曼机的结构如下:

输入设备将信息转换成机器能识别的形式

数据程序通过输入设备的处理后,流向运算器,通过运算器中转,传递给存储器,存储器用于存放数据和程序。

运算器将数据进行算术运算和逻辑运算的处理后,会将数据传递给输出设备,输出设备会将结果转换成人们能看懂的形式。

控制器用于协调部件间协调工作,同时控制器也用于解析存储器中存储的数据,控制器解析数据后,才会指挥运算器进行相应操作。

在计算机系统中,软件和硬件在逻辑上是等效的,也就是说,对于某一种功能,既可以通过软件实现,也可以通过硬件实现,用软件实现成本更低,但效率不高,硬件实现成本更高,但效率也会提升很多。例如,对于乘法运算,可以设计一个专门的硬件电路实现乘法运算,也可以用软件的方式,执行多次加法运算来实现。

冯诺伊曼计算机的特点:

1.计算机由五大部件组成:输入/输出设备(I/O设备),控制器,运算器,存储器

2.指令和数据以同等地位存于存储器,只是存储位置不一样而已。可按地址寻访,无论要读出指令或数据,都需要给出其在主存中的位置。

往后看计算机工作过程会更加理解的,这里不太理解没关系。

3.指令和数据用二进制表示

4.指令由操作码地址码组成,地址码可以有多个,例如二地址指令就有2个地址码

5.存储程序,将指令以二进制代码的形式事先输入计算机的主存储器,然后按其在存储器中的首地址执行程序的第一条指令,以后就按该程序的规定顺序执行其他指令,直至程序执行结束。
6.以运算器为中心,输入/输出设备与存储器之间的数据传送通过运算器完成。

运算器本来的工作为数据的运算,现在还要兼任数据的中转,这会导致数据计算的效率降低。所以改进了计算机的结构。

(2)现代计算机的结构

现代计算机以存储器为中心,也就是输入设备输入的数据都是直接存储在存储器中的,当运算器处理完数据后,输出设备也直接从存储器取走数据。

由于运算器和控制器两者的逻辑关系十分紧密,所以这两个芯片通常被集成在同一芯片中,这一芯片就是CPU:CPU=运算器+控制器

如下图所示,控制器通过控制线告诉运算器执行何种运算,同时控制器会控制主存储器的读/写,也会控制外设的启动和停止。

主存储器与CPU会进行数据交换,例如需要参与运算的数据,如x,y等变量,还有一些是指令,指令会放到控制器中,由控制器解析指令的含义,并且发出相应的控制信号。

输入/输出设备会与主存储器进行数据交换。 

所以现代计算机的结构如下:

5.各硬件的工作原理

(1)主存储器

主存储器包含存储体,MAR(Memory Address Register,存储地址寄存器),MDR(Memory Data Register,存储数据寄存器),地址寄存器用于保存地址相关的二进制数据,数据寄存器用于保存数据。

CPU往主存储器读数据流程如下:

CPU想从主存中取某个数据,那么CPU会将该数据的地址保存在地址寄存器中,主存储器会根据MAR的地址信息,从存储体中取相应数据,并写到数据寄存器中,最后CPU就可以通过数据线,取走他想要的数据了。

CPU往主存储器写数据流程如下:

CPU会指明写入到主存的什么位置,该地址会通过地址线保存在MAR中,要写入的数据则通过数据线保存在MDR中,并且CPU会通过控制总线,告诉主存储器这次执行的操作是写操作。通过CPU发出的这3个信息,主存储器就能在相应的位置写入信息了。

存储体:

数据在存储体内按地址存储,每个地址对应一个存储单元。一个存储体会被分为一个个的存储单元,每个存储单元存放一串二进制代码,这个二进制代码就是存储字(word),而二进制代码的位数就是存储字长。通常每个单元存放的二进制数的位数为8bit的整数倍。存储元就是存储二进制的电子元件,每个存储元可存 1bit。

存储单元:每个存储单元存放一串二进制代码

存储字(word):存储单元中二进制代码的组合

存储字长:存储单元中二进制代码的位数
存储元:即存储二进制的电子元件,每个存储元可存1bit

MAR指明了MAR的地址,所以MAR位数反映存储单元的个数,而MDR是要保存存储单元数据的,所以MDR位数=存储字长。

例如MAR=4位,那么总共有24个存储单元。MDR=16位,那么每个存储单元可存放16bit,也就是1个字(word)

注:其实现在的计算机通常把MAR、MDR也集成在CPU内

(2)运算器

用于实现算术运算(如:加减乘除)、逻辑运算(如:与或非)

运算器的结构如下:

ACC:累加器,用于存放操作数,或运算结果。
MQ:乘商寄存器,在乘、除运算时,用于存放操作数或运算结果。

X:通用的操作数寄存器,用于存放操作数。
ALU:算术逻辑单元,通过内部复杂的电路实现算数运算、逻辑运算。由于电路成本复杂,所以成本也是最高的。

ACC,ALU,MQ三个部件在进行不同运算时,存放的数据各不相同:

(3)控制器

控制器的结构如下:

CU(control Unit):控制单元,分析指令,给出控制信号

IR(Instruction Register):指令寄存器,存放当前执行的指令

PC(Program Counter):程序计数器,存放下一条指令地址,有自动加1功能

计算机执行一条指令需要完成以下阶段:

1.取指令:根据PC记录的下一条指令的地址,取出指令。

2.分析指令:取出的指令会被放到IR中,CU就会分析这条指令的功能。

3.执行指令:分析过后,CU这一部件就会配合其他部件执行指令。

(4)计算机工作过程:

计算机会将高级语言翻译为机器能读懂的机器语言,并且将其装入主存储器中,如下图所示,存储体中每个存储单元的存储字长为16bit

取指令:

程序运行前,(PC)=0,指向第一条指令的存储地址

PC的值通过地址总线传送到主存储器的MAR中。此时(PC)=0,所以(MAR)=0,即

(PC)--->MAR

经过这个操作,控制器向主存指明了此时需要访问0号主存地址对应的数据,同时通过控制总线告诉主存,此时要进行的是读操作。

主存储器会根据MAR记录的信息去存储体中找到0号主存地址对应的存储单元,并且将存储单元的数据存放到MDR中,此时MDR中存放的就是CPU想读取的第一条指令,即

M(MAR)--->MDR        主存储器中MAR存放的地址对应的存储单元的数据放到MDR中

(MDR)=000001 0000000101

这个数据起始就是一条指令,解释为"取数a至ACC",这条指令会通过数据总线放到IR中,导致(IR)=000001 0000000101,即

(MDR)-->IR

分析指令:

该指令的操作码(前6bit)会被送到CU中,CU分析后得知这是"取数"指令,即

OP(IR)--->CU,OP(IR)表示取操作码

执行取数指令:

接下来就需要将指令中的地址码指明的主存中数据取出来,并且放到ACC寄存器中,既然要读取地址码指向的数据,那么就需要先将地址码放到主存的MAR中,如下图所示,该存储单元存放的地址码=0000000101,就是要取5主存地址中的数据到ACC中,即

Ad(IR)--->MAR,Ad(IR)表示取地址码         (MAR)=5

⑥ 接下来主存会根据MAR的地址到存储体中找相应的数据,并把这一数据放到MDR中,即

M(MAR)---->MDR        导致(MDR)=0000000000000010=2

⑦ 最后在控制单元的指挥下,MDR中的数据会被送到ACC(累加寄存器)中,即

(MDR)--->ACC        导致(ACC)=0000000000000010=2

:之前提到PC有自动+1的功能,在取指令这个动作完成后,PC就会自动+1了,即指明了下一条会执行的指令(主存地址为1的位置)

所以上一条指令完成取指后,(PC)=1,执行完该条指令后,(ACC)=2

如图所示,第二条指令是乘法指令:

对应上面的第⑦步,现在MDR中数(3),就会被放到MQ(乘商寄存器)中,即

MDR--->MQ        导致(MQ)=0000000000000011=3

接下来把a的值放到通用寄存器X中,即CPU执行乘商操作时,会把被乘数放到通用寄存器X中,即ACC寄存器中的数据放到X中,而乘数放到MQ中,就是下面的第10步

(ACC)--->X        导致(X)=2

接下来CU会通过控制总线告诉ALU(算术逻辑单元),让其进行乘法运算,那么ALU会将X与MQ中的数据进行相乘操作,并将最终的结果放到ACC中,如下面的11所示,即

(MQ)*(X)--->ACC        由ALU实现乘法运算,导致(ACC)=2*3=6,如果乘积太大,则需要MQ辅助存储,MQ会用来存储乘商运算结果的低位

此时ACC就存放了a*b的值了。

借这个例子就很好理解下图了:

分析完两条指令后,我们可以看到,取指令与分析指令的流程都是一样的,只有当CU分析出指令的不同功能时,操作才会产生区别,所以接下来就从CU分析指令后讲解:

第三条指令的执行:

上一条指令取指后(PC)=2,执行完上一条指令后,(ACC)=6,即ACC中存放了上一条指令执行的结果。

同理,CU分析后,得知这是一个"加法"指令。CPU将指令的地址码送到MAR(0000000111),导致(MAR)=7,即:Ad(IR)--->MAR

接着主存储器会根据MAR,到存储体中寻找对应数据,即主存地址为7的位置存放的数据,放到MDR中

M(MAR)--->MDR        导致(MDR)=0000000000000001=1

由于是"加法"指令,MDR会将数据传送到通用寄存器X中

(MDR)--->X        导致(X)=0000000000000001=1

到这一步,ACC中存放的是被加数,而X中存放的是加数,控制单元CU会向ALU发出信号,指明这是一个加法操作,那么ALU就会将ACC与X中的值相加,并且将加和的结果放到ACC中,即下面的第10步:

(ACC)+(X)--->ACC        导致(ACC)=7

此时ACC就存放了a*b+c的值了。

第四条指令的执行:

上一条指令取指后(PC)=3,执行后,(ACC)=7

由CU分析后,这是一条"存数"指令,接着IR会将该数据的地址码(0000001000)送到MAR中,导致(MAR)=0000001000=8,即:Ad(IR)--->MAR

另外ACC会通过数据总线将数据送到MDR中,即(ACC)--->MDR,导致(MDR)=7,此时MDR中存放的就是a*b+c的值了。

(MAR)=8,(MDR)=7,CU通过控制总线告诉主存储器此次是一次写主存的操作,那么主存储器会根据MAR所指明的地址,把MDR中的数据放到相应的位置中,也就是将a*b+c的值7存放到主存地址为8的位置。

第五条指令的执行:

上一条指令取指后(PC)=4

CU分析后,得知这是一条"停机"指令,那么利用中断机制通知操作系统终止该进程。

总结:

根据指令周期的不同阶段(取指令,分析指令,执行指令),CPU就能区分其从主存中取出的是指令还是数据,例如"取指令阶段"就是取的指令,"执行指令阶段"就是取的数据。

6.计算机系统的多级层次结构

(1)低级语言
机器语言:

传统意义的计算机只能识别机器语言,也就是二进制表示的指令,CPU在执行二进制表示的指令时,还需要将这些机器指令细分为更细的指令执行,即微指令或微操作。也就是用微指令解释并执行每一条机器指令。

例如下图,主存地址为0的指令,就需要分为9个微操作。

汇编语言:

由于二进制指令用于编程是很不方便的,所以出现了汇编语言,使用汇编语言的程序员看到的机器就是"虚拟机器",为什么是"虚拟机器"?

因为在使用汇编语言的程序员看来,好像机器能直接识别汇编语言,但是机器其实无法直接识别汇编语言,而是需要通过汇编程序翻译成等价的机器语言程序,才可以执行。

一条汇编语言对应一条机器指令:

用汇编语言编写的程序,只是更便于理解而已,但本质上依然属于低级语言。

(2)高级语言

在程序员看来,可以识别高级语言的机器,也称为"虚拟机器",因为机器不能直接识别高级语言,高级语言需要用编译程序翻译成汇编语言程序,用汇编程序翻译成机器语言程序,机器才能识别。

(3)计算机系统的层次结构

高级语言编写的程序可能会用到操作系统提供的服务,例如通过系统调用请求操作系统的服务,汇编语言编写的程序同理,那么完善的层次如下图所示:

操作系统与操作系统之上的部分就为软件部分用机器语言的机器及以下的部分就为硬件部分

下层是上层的基础,上层是下层的扩展。

(4)三种级别的语言

如上图所示,高级语言需要用编译程序翻译成汇编语言程序,用汇编程序翻译成机器语言程序,机器才能识别。事实上也有一些语言,经过编译程序的编译后,就能直接得到机器可识别的机器语言程序。

还有一些高级语言的执行,并不是通过编译程序编译,而是通过解释程序,将高级语言翻译为对应的机器语言指令,例如:JavaScript、Python、Shell

编译程序与解释程序的区别:

编译程序:将高级语言编写的源程序全部语句一次全部翻译成机器语言程序,而后再执行机器语言程序(只需翻译一次),例如执行完C语言后生成的.exe文件,这个文件就是用机器语言描述的程序,只要生成这一文件,之后就不需要再进行编译了。

若要运行这一程序,只需要加载这一文件即可。

解释程序:将源程序的一条语句翻译成对应于机器语言的语句,并立即执行。紧接着再翻译下一句(每次执行都要翻译)

所以编译程序执行效率更高,解释程序执行效率较低。

注:编译、汇编、解释程序,可统称“翻译程序”,他们的作用都是将更高级的语言翻译为更低级的语言。

补充:计算机体系结构与计算机组成原理的区别

计算机体系结构探讨的是如何设计硬件与软件之间的接口。而计算机组成原理探讨的是如何用硬件实现所定义的接口。这对程序员来说是“透明”的,即程序员是看不见的。

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

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

相关文章

01 Qt自定义风格控件的基本原则

目录 1.继承原生控件 2.组合原生控件 3.仿写原生控件 PS:后续将继续分享开发实践中各类自定义控件的方法、思路以及组件库 1.继承原生控件 关键字:继承、paintEvent 这里想说的是,Qt的Gui框架在封装原生控件的同时, 也为开发者提供了各…

opencv鼠标操作与响应

//鼠标事件 Point sp(-1, -1); Point ep(-1, -1); Mat temp; static void on_draw(int event, int x, int y, int flags, void *userdata) {Mat image *((Mat*)userdata);if (event EVENT_LBUTTONDOWN) {sp.x x;sp.y y;std::cout << "start point:"<<…

【面试题】谈谈MySQL的索引

索引是啥 可以把Mysql的索引看做是一本书的目录&#xff0c;当你需要快速查找某个章节在哪的时候&#xff0c;就可以利用目录&#xff0c;快速的得到某个章节的具体的页码。Mysql的索引就是为了提高查询的速度&#xff0c;但是降低了增删改的操作效率&#xff0c;也提高了空间…

HarmonyOS—@Observed装饰器和@ObjectLink嵌套类对象属性变化

Observed装饰器和ObjectLink装饰器&#xff1a;嵌套类对象属性变化 概述 ObjectLink和Observed类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步&#xff1a; 被Observed装饰的类&#xff0c;可以被观察到属性的变化&#xff1b;子组件中ObjectLink装饰器装饰的状…

两分钟秒懂Android控件设置

导言 本文从整体到局部,从常用布局(layout)到控件的设置,层层递进,一定要从前往后依次看 目录 1.常用布局方式 1.1 ConstraintLayout 约束布局 1.2 LinearLayout 线性布局 1.3 TableLayout 表格布局 1.4 GridLayout 瀑布布局 2.关于控件属性整合 2.1 放置位置 2.2 如…

三相逆变器拓扑结构的分析及应用场景

三相逆变器是电力电子领域中广泛应用的一种设备&#xff0c;用于将直流电转换为交流电。不同的拓扑结构在性能、成本、复杂度和应用领域上存在差异。小编将在本文中将进一步拓展对三相逆变器拓扑结构的分析&#xff0c;并探讨其适用的应用场景。 1. 单桥逆变器 优点&#xff…

CAN FD一致性测试:便捷、高效的自动化测试系统

后起之秀——CAN FD&#xff1a;随着各个行业的快速发展&#xff0c;消费者对汽车电子智能化的诉求越来越强烈&#xff0c;这使得整车厂将越来越多的电子控制系统加入到了汽车控制中&#xff0c;且在传统汽车、新能源汽车、ADAS和自动驾驶等汽车领域中也无不催生着更高的需求&a…

【硬核】Log4j2 与 Logback 当初的选型以及在当前云原生环境下的反思与展望

个人创作公约&#xff1a;本人声明创作的所有文章皆为自己原创&#xff0c;如果有参考任何文章的地方&#xff0c;会标注出来&#xff0c;如果有疏漏&#xff0c;欢迎大家批判。如果大家发现网上有抄袭本文章的&#xff0c;欢迎举报&#xff0c;并且积极向这个 github 仓库 提交…

革命性进展!OpenAI推出全新视频生成模型Sora,开启视频创作新纪元!

OpenAI发布文生视频模型Sora——视频模型的奇点或许来临&#xff01;&#xff01; 初七啦&#xff0c;得开始工作了&#xff0c;没想到第一天就这么劲爆&#xff01; 今天OpenAI迎来重大更新——发布视频模型Sora&#xff01;&#xff01; 官网Sora (openai.com) 说实话有点…

Laravel Reverb 强势降临:全新风潮,引领未来开发潮流!

终于有官方 Websocket package 了&#xff01;&#xff01;&#xff01; Laravel Reverb &#xff01;&#xff01;&#xff01; reverb.laravel.com/ Laravel Reverb的引入使得Laravel框架在实时通信方面更加强大和灵活&#xff0c;为开发者提供了更多的选择和可能性。通过利…

C++结合Lambda表达式在函数内部实现递归

529. 扫雷游戏 已解答 中等 相关标签 相关企业 让我们一起来玩扫雷游戏&#xff01; 给你一个大小为 m x n 二维字符矩阵 board &#xff0c;表示扫雷游戏的盘面&#xff0c;其中&#xff1a; M 代表一个 未挖出的 地雷&#xff0c;E 代表一个 未挖出的 空方块&#xff…

01_02_mysql06_视图-存储过程-函数

视图 使用 视图一方面可以帮我们使用表的一部分而不是所有的表&#xff0c;另一方面也可以针对不同的用户制定不同的查询视图。比如&#xff0c;针对一个公司的销售人员&#xff0c;我们只想给他看部分数据&#xff0c;而某些特殊的数据&#xff0c;比如采购的价格&#xff0…

Rabbitmq入门与应用(三)-RabbitMQ开发流程

RabbitMQ开发流程 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency>配置MQ 最简配置 spring:rabbitmq:host: mq的安装机器ipport: 5672username: ad…

手撕C语言习题

定义一个表示公交线路的结构体&#xff0c;要求有线路名称(例如 616)&#xff0c;起始站&#xff0c;终点站&#xff0c;里程等成员&#xff0c; 定义结构体数组&#xff0c;用来存储多条条公交线路信息&#xff0c;要求能够输出从指定起始站发车的所以公交线路信息。 2、定义…

C++11---(3)

目录 一、可变参数模板 1.1、可变参数模板的概念 1.2、可变参数模板的定义方式 1.3、如何获取可变参数 二、lambda表达式 2.1、Lamabda表达式定义 2.2、为什么有Lambda 2.3、Lambda表达式的用法 2.4、函数对象与lambda表达式 三、包装器 3.1、function 3.2、bind …

Web3探索加密世界:什么是空投?

随着加密货币行业的迅速发展&#xff0c;人们开始听说各种各样的术语&#xff0c;其中包括"空投"&#xff08;Airdrop&#xff09;。在这里&#xff0c;我们将深入探讨什么是空投&#xff0c;以及它在加密世界中扮演的角色。 什么是空投&#xff1f; 空投是指在加密…

Spring Boot应用集成Actuator组件以后怎么自定义端点暴露信息

一、 前言 在平时业务开发中&#xff0c;我们往往会在spring Boot项目中集成Actuator组件进行系统监控&#xff0c;虽然Actuator组件暴露的端点信息已经足够丰富了&#xff0c;但是特殊场景下&#xff0c;我们也需要自己暴露端点信息&#xff0c;此时应该怎么操作呢&#xff1…

4款AI写作软件推荐,让文章撰写更加轻松! #学习方法#知识分享

国外ChatGPT爆火&#xff0c;AI写作在国内也引起不小的瞩目&#xff0c;目前国内的AI写作工具少说也有几十上百个&#xff0c;要在这么多AI写作中找出适合自己的工具&#xff0c;一个一个尝试是不太现实的&#xff0c;所以今天就给大家推荐一些款AI写作工具。帮助你少走弯路&am…

请你设计一个抢手机F码的排队的场景,并且需要显示等待时间

package com.example.demo1.service.impl;import lombok.Data;import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.Date;Data public class User {//用户idprivate Integer id;//姓名private String name;//插入的时间private LocalDate…

NestJS入门8:拦截器

前文参考&#xff1a; NestJS入门1&#xff1a;创建项目 NestJS入门2&#xff1a;创建模块 NestJS入门3&#xff1a;不同请求方式前后端写法 NestJS入门4&#xff1a;MySQL typeorm 增删改查 NestJS入门5&#xff1a;加入Swagger NestJS入门6&#xff1a;日志中间件 Nes…