磁盘工作原理
原文: https://blog.csdn.net/lengye7/article/details/122522973
四、现代磁盘的基本组成与工作原理
这里写图片描述
现代磁盘的基本组成如上图所示:
串行接口:串行接口往往直接连着磁盘的主控电路板,用来与磁盘的外部设备交互,外部设备通过这个接口从磁盘读出数据,往磁盘中写入数据。
空气过滤片:这种一般是属于空气盘才有的,用来过滤空气中的灰尘,灰尘一旦进入磁盘内部,可能会破坏盘片,从而使磁盘完全损坏。
主轴:磁盘盘片的的马达通过主轴连接磁盘盘片,从而使磁盘盘片高速旋转。
磁盘盘片(图中标示为磁盘):这是真正记录信息的地方,其表面有磁性介质。
磁头:依靠它往磁盘盘片中写入和读出数据。
磁头臂:通过它连接磁头与音圈马达,音圈马达旋转从而能够移动磁头的位置。
音圈马达:外围电路通过驱动它来移动磁头的位置。
永磁铁:这个我真不知道是什么作用,应该是音圈马达的部件,用来给音圈马达提供磁场。
磁头停泊区:磁盘关闭,停止工作的时候,磁头就停在这里。磁头是不能挺在磁盘盘片上的,否则就会很容易刮伤盘片,导致扇区甚至磁道损坏。
现在磁盘的逻辑示意图:
写入数据的工作流程:
磁盘控制器与外部设备交互,外部设备告知磁盘控制器需要写入数据,以及写入的磁盘扇区地址。
磁盘控制器接收到这个地址之后,经过转换(现在都是使用LBA地址来访问磁盘,因此在磁盘内部会根据这个地址来进行计算,算出该扇区所在的盘面和磁道。具体是直接使用,还是转换为C/H/S的形式,我就不得而知了。)放入到磁盘地址寄存器中,然后磁盘地址寄存器根据这个地址选择对应的磁头,并控制磁头定位系统将磁头定位到对应的磁道,磁头到位后,立刻读出磁道上的信息,这些信息就是一连串的高低电平,对应一连串的0和1序列,扇区计数器就不断地在这些0和1序列中查找特定的扇区开始标志(例如0xD5),找到标志后就将后续的扇区号的信息放入到扇区符合比较器,如果扇区号符合,就通知磁盘控制器,找到了对应的扇区;之后,磁盘控制器就通过写命令控制写入电路通过磁头写入对应的信息,于是一次写完成。
在这个过程中我们看到,磁头其实并不能直接定位对应的扇区位置,磁头只能定位对应的盘面和对应的磁道,而扇区的定位依靠外围电路寻找扇区开始标志与比较扇区号来确定。这也说明,磁盘扇区的划分并不是在磁盘盘片上进行物理划分,而是依靠逻辑划分,即依靠扇区开始标志信息来确定,在这个过程中一旦找到对应的扇区,磁盘控制器就立刻会控制写入电路写入对应信息,这就要求磁盘控制器反应迅速,毕竟磁盘的盘片是高速转动的,一旦反应过慢,对应的扇区就已经错过了。
在上面的磁盘写入信息的流程中,磁盘的盘片始终是高速旋转的,不会因为寻找扇区就减慢转动速度,也不会因为找到扇区后需要写入数据就停下来等待磁盘控制器做出响应。后面的介绍中,就可以很清楚的看到,磁盘扇区的结构,磁盘的扇区和扇区之间存在一定的间隔,这些间隔是不会写入数据的,这是为了给磁盘控制器一个缓冲,让其可以转换磁头的读写模式,而在扇区的标志头与扇区的数据区域之间也会有一个间隔,这个间隔也是不会写入任何数据的,目的也是为了给磁盘控制器一个缓冲,让磁盘控制器能够根据标志头的信息判断是否需要写入数据到数据区还是读出数据区的数据。
磁盘即使在空闲的时候,磁盘的盘片也不会停止旋转?
首先,磁盘关闭的时候,磁头是停在停泊区的,这是毋庸置疑的。
另外,硬盘的磁头是绝对不能与磁盘的盘片接触的,否则就会损坏盘片,实际上,当磁盘盘片高速转动的时候,会在磁盘盘片表面形成一圈高速的气流,就是通过这种气流托起磁头,磁头跟磁盘盘片的距离非常近,达到微米级别,从而才能往盘片写入和从盘片读出数据。
那么磁盘空闲的时候,磁盘盘片可以停止运转吗?
如果想让磁盘的盘片停止运转,那当然是可以的,但是,必须通过向磁盘发送关闭指令来使其停止运转,那这个时候,实际上就是关闭磁盘了,关闭磁盘的时候,磁盘首先让磁头回到停泊区,然后才会停止盘片的转动。当然,可以不使用关闭指令,通过其他指令先让磁头回到停泊区,待磁头到位之后,再关闭磁盘盘片的转动。
如果仅仅只是停止磁盘的盘片高速运转,那么就有可能在磁盘的盘片低速运转的时候,气流拖不起磁头,然后磁头与盘片接触,从而刮伤整个磁道。所以,直接断电是很容易损坏磁盘的,开关机的时候,也不要直接断电,而是通过计算机的关闭程序来完成计算机的关机。当然,现代磁盘都有保护措施,一旦遭遇断点,磁头会在极短的时间内回到停泊区,但是也最好不要尝试关闭计算机电源来关机。
曾经,就有操作系统试图在磁盘空闲的时候(没有读写任务),停止电机旋转以省电,结果造成磁盘损坏。
读出数据的工作流程:
外部设备与磁盘交互,外部设备告知磁盘控制需要读出数据,以及所需读出的数据的地址。
磁盘控制器接收到这个地址之后,经过转换(现在都是使用LBA地址来访问磁盘,因此在磁盘内部会根据这个地址来进行计算,算出该扇区所在的盘面和磁道。具体是直接使用,还是转换为C/H/S的形式,我就不得而知了。)放入到磁盘地址寄存器中,然后磁盘地址寄存器根据这个地址选择对应的磁头,并控制磁头定位系统将磁头定位到对应的磁道,磁头到位后,立刻读出磁道上的信息,这些信息就是一连串的高低电平,对应一连串的0和1序列,扇区计数器就不断地在这些0和1序列中查找特定的扇区开始标志(例如0xD5),找到标志后就将后续的扇区号的信息放入到扇区符合比较器,如果扇区号符合,就通知磁盘控制器,找到了对应的扇区;之后,磁盘控制器就通过读命令控制读出电路通过磁头读出对应的信息,并将读出的信息放入到磁盘的缓冲区中,于是一次磁盘内部的读取就完成了。之后,磁盘控制器就会通知外部设备,数据已经读出了。
在这个过程中我们看到,磁头其实并不能直接定位对应的扇区位置,磁头只能定位对应的盘面和对应的磁道,而扇区的定位依靠外围电路寻找扇区开始标志与比较扇区号来确定。这也说明,磁盘扇区的划分并不是在磁盘盘片上进行物理划分,而是依靠逻辑划分,即依靠扇区开始标志信息来确定,在这个过程中一旦找到对应的扇区,磁盘控制器就立刻会控制读出电路去读出对应信息,这就要求磁盘控制器反应迅速,毕竟磁盘的盘片是高速转动的,一旦反应过慢,对应的扇区就已经错过了。
以上过程就是现代磁盘读写的基本过程,可能与具体的磁盘工作有所出入,但是大体流程应该是一致的。
如果将来需要使用低层次的办法访问磁盘,实际上也会非常方便,只需要指出磁盘的LBA地址,然后是写入或者读出即可,其他的一切都在磁盘内部完成。但是,理解磁盘工作流程能够更好的使用磁盘,至少不会做出让磁盘电机突然停转的事儿吧。
关于硬盘地址的形式,后面会特地讲到,因为在硬盘发展的过程中,硬盘地址的形式出现过多次的改变,形式比较混乱。
五、磁盘的逻辑抽象
下面的内容是对磁盘的盘片以及磁头这两部分进行一个逻辑抽象,以帮助加深理解。
é»è¾ç»æå¾2
磁盘的核心部件的逻辑示意图
英文示意图
Platter:盘片,磁盘核心部件往往由多个盘片组成,叠加在一起。
Surfaces:盘面,每个磁盘的盘片其实具有上下两面,每个盘面都可以存储数据,所以每个盘面都对应着一个读写磁头。
R/W head:读写磁头,每个盘面一个。
Track:磁道,每个盘面都在逻辑上划分为多个磁道,磁道和磁道时间有间隔(逻辑上的间隔,实际上,磁盘只是通过控制磁头的移动距离来确定这个间隔,磁盘盘面上没有任何划分。),这个间隔是为了防止读写磁头在读或写的过程中对旁边的磁道产生影响,从而导致相邻磁道的数据丢失。
Cylinder:柱面,所有盘面的磁道的逻辑划分其实都是一样的,所有盘面上的同一位置的磁道都位于同一个柱面上。
Sector:扇区,这个是磁盘对外提供数据访问的基本单位,扇区位于磁道上,每个磁道在逻辑上划分为若干个扇区(物理上不存在划分,扇区的划分依靠的是标志位来进行确定,前面的工作流程中已经讲过。),扇区和扇区之间往往存在着一定的间隔(逻辑上的间隔,这种间隔是为了给外围电路留下时间来控制磁头转换读写逻辑),通过这种间隔来给外围电路一定的缓冲时间,来做一些对下一个扇区的处理准备。
从磁盘的逻辑示意图来说明CHS寻址方式?
早期磁盘时代,磁盘对外界提供的访问方式就是CHS寻址,这种CHS的寻址方式正好是与磁盘的结构对应的。
C------------Cylinder,C对应于柱面,确定了柱面,就确定了多个盘面上的同一磁道。
H------------Head,H对应于磁头,确定了磁头,而磁头与盘片是一一对应的,于是就确定了盘面。
通过C和H,就能够确定唯一磁道。
S------------Sector,S对应于扇区,确定了所有盘片上的同一磁道上的一个扇区。
这样,通过C和H,就可以确定某一个盘面上的某一个磁道,再通过S,进一步确定该磁道上的某一扇区,CHS寻址就确定了磁盘上的一个扇区。
#扇区的逻辑结构
硬盘的读写原理和磁盘碎片的产生说明
扇区的基本示意图
再来看一看一般性的扇区的逻辑结构:
从上图可以看到,扇区作为一个整体来看,扇区包含一个标志头和数据区,在扇区整体两侧包含一定的间隔,标志头与数据区之间也包含一定间隔。
从上图可以看到,对于一个扇区来说其具有标志头,标志头用来确定一个扇区的开始,往往包含但不限于以下信息:
扇区开始标志
扇区地址(应该是CHS地址)
扇区损坏标志
扇区损坏替换地址(这个往往在扇区损坏之后才起作用,后续将会说到坏扇区的修复)
扇区的校验数据
在标志头之后,往往具有一个间隔,这个间隔是为了给磁盘控制器在内的这些外围电路一个缓冲,给予它们一定的时间处理标志头的数据,同时给读取后面数据区内容或者写入数据到数据区做好准备。
标志头之后,就是真正的数据区了,数据区就包含两部分信息:
真正的数据
关于数据的校验数据(即使到现在,硬盘的数据错误率也是很高的,每上万次读写就会出一次错,所以校验数据是必须的,一般就使用简单的ECC校验)
扇区损坏
扇区损坏往往可以分为两类:逻辑损坏和物理损坏。
逻辑损坏:扇区的格式出现错误,导致扇区无法被识别读出,这就是逻辑损坏。
逻辑损坏的修复:逻辑损坏修复起来比较简单,使用低层次格式化工具对逻辑损坏扇区所在的磁道重新进行扇区的逻辑划分。一般这种低层次的格式化工具,每个硬盘厂商都有,最好使用对应的硬盘厂商的工具,而且每一块硬盘在出场的时候都会进行一次低层格式化,以对每个磁道进行扇区的逻辑划分。
物理损坏:扇区所在的区域的盘片出现损伤,导致扇区数据无法识别,这就是物理损坏。
物理损坏的修复:物理损坏其实没法被真正的修复,修复工具所做的事情其实是进行扇区的映射,当一个扇区物理损坏之后,修复工具就会将这个扇区映射到磁盘预留的好的扇区上(现在的磁盘一般厂家都会在磁盘中预留一部分扇区,这部分扇区就是用于修复损坏的,一旦预留的扇区使用完了,则无法继续修复了。)。具体原理就是在扇区的扇区头标志中将扇区损坏标记激活,然后在扇区损坏替换地址中填入映射的扇区的地址,这样做之后,当下一次读取该损坏扇区的时候,磁盘驱动器就会转向到映射的扇区进行读取。
注意:一旦出现物理损坏,则往往意味着硬盘其他部分也会逐渐开始损坏,这种时候,就最好赶快迁移数据到新的硬盘上,以免造成数据丢失。
另外,还有一些物理损坏导致的扇区损坏,这些损坏可能无法通过上述办法修复。
#磁盘盘面的逻辑结构
早期的磁盘的盘面的逻辑结构
早期磁盘的盘面的逻辑结构如上图所示,其内外磁道的扇区数是相同的,这就造成里面的磁道的磁记录密度比外面磁道的磁记录密度要高,而实际上外部磁道的磁记录密度可以做到与里面的磁道的磁记录密度一样,所以这种逻辑划分实际上是一种比较浪费的划分方式。
后来,为了增大磁盘的容量,磁盘的盘面的逻辑划分不再是等扇区了,而是等密度,即内外磁道的磁记录密度一样,这就造成外部区域的磁道的扇区数多于内部区域磁道的数量。
不同区域磁道的扇区划分示意图
当前磁盘的盘片的磁道的逻辑划分应该如上图所示,其磁道按照区域进行划分,每个区域的扇区数量不同,外部扇区的磁道数量远多于内部扇区的磁道数量。这样划分的话,由于外部区域的扇区数量多于内部,但是磁盘盘片的转速是确定的,于是单位时间内,外部磁道被磁头读取的扇区数量更多,所以外部磁道的数据传输率比内部磁道的数据传输率更大。
ps:操作系统都喜欢把自己的文件写入到外部区域的磁道上,毕竟外部磁道的数据传输速度更快。这样,他的文件加载速度就会快一些。
0号磁道:当前磁盘的0号磁道是0号盘面的最外面的磁道。
0号磁道上的第一个扇区有一个著名的名字,那就是MBR(Master Boot Record)。
在CHS寻址方式中,对应于CHS 0 0 1。在LBA寻址方式中,对应于LBA0。
但是需要注意的是,在一些文献中,仍然将现代磁盘的0-63号扇区作为Track0。而在这里所说的Track0,指的是位于0号盘面的最外面的那一条磁道。
磁道之间的间隔
磁道之间的间隔是一种逻辑间隔,是磁盘控制与外围电路在控制磁头写入数据的过程中,预留的一些间隔区域,这些间隔区域的主要作用就是给相邻磁道之间留下一个安全区域,防止磁头在写入数据或读出数据的过程中给相邻的磁道造成影响,引起相邻磁道的磁化区域的退磁,从而导致相邻磁道的数据丢失。
说到磁道之间的间隔就不得不说CMR与SMR了:
CMR(Conventional magnetic recording),传统磁记录,其保持了磁道之间的间隔,自然而然具有更好的数据安全性了。
CMR磁道示意图:
SMR(Shingled Magnetic Recording,),叠瓦式磁记录,它是怎么叠瓦的呢?
假设一条磁道包含3部分,外部磁道距离a+磁道数据区宽度b+c(a=c),那么叠瓦式磁记录在写入数据的时候,假设它从0号磁道开始写,这个时候盘面上0号磁道占据a0+b+c0的距离,接下来写入1号磁道,这个是时候1号磁道就会覆盖掉c0这个间隔,于是1号磁道占据a1+b+c1,其中a1刚好与c0重叠了,其他磁道写入以此类推,这就使0号磁道和1号磁道之间的距离变为a1(甚至更小),这个距离一下就变的比CMR小了,于是smr比cmr具备了更多的磁记录区域,磁记录密度提高了。
而这种磁道结构,就像瓦片叠起来一样,于是被形象的称为叠瓦式磁记录。
SMR磁道示意图:
SMR磁道数据写入示意图:
那么缩短它们之间的距离所带来的后果是什么呢?
如上图的SMR写入示意图:
当磁道距离过近,磁头在写入数据的过程中就可能会影响相邻磁道的剩磁强度(为什么会影响呢?因为磁头的宽度比数据区的宽度要宽,在写入数据的时候,磁头有一部分实际会进入相邻磁道的数据区。),一旦造成相邻磁道的剩磁强度过低,相邻磁道上的数据就无法被读出了,于是数据就丢失了。
那么这种后果是不是随时都会出现呢?
那显然不是的,能用于磁盘的磁性介质的矫顽力都比较高,不会那么容易就退磁,假设SMR硬盘只被写入一次数据,那显然是没有问题的,因为只被写入,所以影响只有一次,那么依靠磁性介质的自身矫顽力,其完全能够抵抗这种磁头的影响,保持磁化区域的剩磁强度。
那么现在假设写入0号磁道之后,又写入了1号磁道,然后0号磁道的数据被删除了,于是0号磁道的扇区都作为空闲扇区回收了,然后再次往SMR硬盘写入数据的时候,0号磁道的空闲扇区被分配了,于是0号磁道被写入数据了,这一次写入过程影响了1号磁道的数据,不过还好,1号磁道因为磁性介质矫顽力的缘故,其数据依然能够被读出。接着,0号磁道的数据又被删除了,然后0号磁道又被写入了数据,1号磁道再一次被影响了,因为磁性介质矫顽力的缘故,它再一次抗住了影响,数据还是能够被读书。如果上面的过程再重复3次、4次、5次呢?它还是抵抗住了磁头写入数据的影响,终于在上述过程发生第6次的时候,1号磁道的剩磁强度减弱到无法被读出的程度,1号磁道的数据永远消失了。
通过上面这一段的过程描述,可以比较直观的看到,SMR通过缩减磁道之间的间隔距离来提高磁记录密度所带来的直接问题就是,如果对某一个磁道进行重复的擦写,那么这对相邻磁道的数据会有比较严重的影响,最终会导致数据丢失。
为了避免数据丢失这种情况,SMR硬盘采用刷新某一磁道的数据的同时,也会对后续的相邻的磁道全部刷新一次,直到所有叠瓦部分中的受影响的磁道全部被刷新一次。这是一种保护办法,但是显然影响了硬盘的写入性能,而且这种办法显然也增加了硬盘的可擦写次数的消耗,而由于磁盘盘片的可擦写次数实际上是有寿命的,这也就导致了SMR硬盘的寿命比较短。
另外,SMR硬盘通常会对磁道进行分组,组内采用SMR磁道技术,组与组之间采用正常的磁道间隔,这也算是一种平衡吧。
此外,SMR硬盘由于需要刷新全部受影响的叠瓦部分的磁道,如果写入的数据位于不同的分组中,那么这样的一次写入就会导致SMR硬盘需要刷新大量的分组中的叠瓦磁道,这样就更加降低了写入性能。而像这样的一次写入过程,实际上就是随机写,可见,SMR硬盘的随机写能力大大低于CMR硬盘。后来有人专门开发了相关算法,通过将随机写转换为连续写来提高SMR的随机写能力。
SMR分组为段示意图:
五、磁盘的寻址方式与容量
1、早期硬盘的寻址方式
早期硬盘的寻址方式采用CHS寻址,这是一种对应于硬盘的3D几何结构的寻址方式,因为直接对应于硬盘的3D几何结构,所以CHS寻址方式并不能用于磁带,光盘等。
C:cylinder,柱面。
H:head,磁头。
S:sector,扇区。
这种寻址方式最早在IBM的BIOS定义中使用,采用24bit的CHS方式寻址,其中C:10bit(柱面从0开始计数),H:8bit(磁头从0开始计数),C:6bit(扇区从1开始计数)。
那么CHS寻址是怎么计算的呢?
通过指定cylinder,确定柱面,从而确定磁道号。
通过指定head,确定磁头,从而确定盘面,根据盘面和磁道号,从而确定某一盘面的某一磁道。
通过sector,确定扇区,从而根据盘面和磁道以及扇区号,确定某一个盘面的某一磁道的某一扇区,最终寻找到特定扇区。例如0,0,1扇区,就是访问0号磁道0号盘面的1号扇区,即注明的MBR扇区。
2、LBA(logical block addressing)寻址方式
早期硬盘都是连接在一个硬盘卡上的,这就造成硬盘厂商与硬盘卡之间的诸多兼容性问题,后来西部数据为了解决这一问题,提出了IDE(Integated Drive Electronics)接口,旨在解决这问题,并同时提出了AT Attechment(即ATA,这一版本的ATA后面被称为Pre-ATA),在ATA中提出了LBA寻址方式,这一寻址方式的提出解决了CHS寻址方式只能用于硬盘寻址的问题,使得LBA可以适用于磁带和光盘等寻址。
这一版本的LBA使用22bit宽度寻址,但是很可惜,由于市场上存在着大量的CHS寻址方式硬盘,而LBA又不能兼容CHS寻址的硬盘,所以推行并不顺利。
后来,1994年,ATA-1发布,提出了28bit的LBA寻址,具备28bit的CHS寻址兼容模式(C:16bit,H:4bit,C:8bit)。
再后来发布了ATA-2、ATA-3、ATA-4、ATA-5,没有提出新的寻址方式,但是保持向后兼容。
2003年发布了ATA-6,提出了LBA-48寻址方式,即LBA寻址的宽度为48bit。
那么LBA是如何寻址的呢?
LBA直接标识每一个扇区,从0号盘面和0号磁道开始,标记0号扇区,1号扇区。。。然后是0号盘面1号磁道,N+1,N+2,以此类推。
当需要访问某一扇区的时候,只需要给出扇区号即可,例如5号扇区。
LBA这一方式,后来也正好可以用于等密度(Zone it Recording)的磁盘,因为这种磁盘内外磁道等密度,所以这种磁盘的内外磁道的扇区数不一样,就不是很适合使用CHS寻址了。
3、硬盘容量的限制突破
1)、BIOS限制的504MiB容量
ATA提出以后,BIOS为了能够兼容ATA硬盘的CHS模式,就把24bit的H的8bit,简单的映射为ATA的CHS模式的4bit,于是此时BIOS所能支持的硬盘大小就变为了(假设512bytes一个扇区)1024*16*63*512=528MB=504MiB,这就是第一次硬盘容量的限制。
为了突破504MiB的限制,BIOS做了一次扩展,将ATA的CHS模式(C:16,H:4,C:8)映射为C:10bit,H:8bit,C:6bit,于是此时BIOS能够支持的IDE硬盘容量为7.875GiB。
2)、BIOS的再一次限制
第一次BIOS的扩展只能支持7.875GiB的容量硬盘,但是硬盘容量越来越大,于是很快就达到了7.875GiB的容量限制。
于是IBM和微软共同发布了BIOS Enhanced Disk Drive Services(2002年)的新的BIOS,该BIOS使用64bit的LBA寻址,于是BIOS的容量限制突破,BIOS所能支持的容量达到2的64次方乘以512字节数。
3)、LBA28所带来的限制
BIOS在2002年采用64bit的LBA寻址之后,容量限制来到了ATA的LBA28这里(只支持128GiB),28bit的LBA寻址所能支持的硬盘容量为128GiB,所以为了突破这个容量, 2003年ATA-6发布了,ATA-6采用了LBA48bit寻址,使得其所能支持的硬盘容量达到128PiB。
但是在这个期间,由于计算机的位数仍然是16位或者32位的,所以硬盘容量仍然被限制在2TiB。
后来64位机器问世,容量便不再是限制了。目前,计算机中所使用的硬盘容量已达20TiB。
六、Serial ATA问世
硬盘的传输速度越来越快,但是ATA-6只能支持133MB/s,于是intel、IBM等,还有其他几家公司联合研发了Sata协议,2003年发布了sata 1.0,传输速度150MB/s,sata从一问世开始就支持LBA48位寻址,同时兼容ATA-1到ATA-6的特性,也就是说sata1.0同时也支持LBA28位和CHS28位兼容模式。
sata协议不仅向后兼容,同时也保持向前兼容,这使得sata1.0的硬盘可以插在sata 2.0的主板上,或者sata 2.0的硬盘插在sata 1.0的主板上,这是非常重要的一个特性,相对于ATA来说,优势也更加明显。
与此同时,sata的传输速度也明显优于ATA,于是很快的,sata就占领了大部分的市场份额,今天(2022年),在市场上基本已经找不到IDE接口的ATA硬盘了,几乎都是sata接口的sata协议硬盘。
sata1.0发布之后,sata2.0和sata3.0也陆续发布,传输速度分别达到300MB/s和600MB/s。
————————————————
版权声明:本文为CSDN博主「lengye7」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lengye7/article/details/122522973