资料:数据恢复知识基础

计算机上只有数据是最关键的,数据的丢失才是最大的损失。下面我来讲解一些数据恢复的基本知识。
首先申明一点,对于重要数据,备份数据才是防止数据丢失的根本方法,而数据恢复依赖于很多因素,很难完全恢复数据,一般是仅仅可以恢复部分数据。
数据恢复就是找回丢失的数据,例如彻底删除某个文件或文件夹,重新格式化磁盘,重新分区磁盘等等都会造成数据的丢失。更严重的数据丢失是存储介质硬件损坏,例如,硬盘不小心摔坏了、硬盘根本就不认了、硬盘有大量坏道等等。最值得注意的一点是,一旦意识到数据丢失了,立刻停止一些不必要的*作,误删、误格后,不要再往磁盘里写数据了!磁盘摔坏后,不要再加电了!磁盘出现坏道读不出来,不要反复读盘了等等。
硬盘故障大致可分为硬故障和软故障两大类。硬故障即PCBA板损坏、盘片划伤、芯片及其它原器件烧坏、断针断线、磁头音圈电机损坏等,是由于硬盘自身的机械零件或电子元器件损坏而引起。剧烈的震动、频繁开关机、电路短路、供电电压不稳定等比较容易引发硬盘物理性故障,硬件故障一般表现为CMOS不认硬盘,常有一种“咔嚓咔嚓”的磁组撞击声或电机不转、通电后无任何声音、磁头不对造成读写错误等现象,对上面描述的大部分情况,一般都要送到专门的数据恢复中心检测和恢复数据。
硬盘软故障即硬盘数据结构由于某种原因,比如说病毒导致硬盘数据结构混乱甚至不可被识别而形成的故障。一般来说,主板BIOS硬盘自动检测(IDE HDD AUTO DETECTION)功能能够检测到硬盘参数,均为软故障。一般情况下,硬盘在发生故障时系统会在屏幕上显示一些提示信息,所以我们可以按照屏幕显示的提示信息找到故障原因,有针对性地实施解决方案。软故障包括误分区、误格式化、误删除、误克隆、MBR丢失、BOOT扇区丢失、病毒破坏、黑客攻击、分区信息丢失、RAID0磁盘阵列、RAID1磁盘阵列、RAID5磁盘阵列失效等因素造成的数据丢失。硬盘软故障相对于物理故障来说,更容易修复些,而它对数据的损坏程序也比硬盘物理故障来得轻些。
下面主要说明一下硬盘发生软故障后数据恢复的大概方法,部分原理可以用于优盘,光盘等的数据恢复。

基础知识-硬盘, 分区和文件系统的介绍

硬盘内部结构

关于硬盘结构的文章已经非常多了,不过真正要说清楚的话,就算专门出一本书也说不完,因此这里就不再从头细细讲述了。
硬盘最基本的组成部分是由坚硬金属材料制成的涂以磁性介质的盘片,不同容量硬盘的盘片数不等。每个盘片有两面,都可记录信息。盘片被分成许多扇形的区域,每个区域叫一个扇区,每个扇区可存储128×2的N次方(N=0.1.2.3)字节信息。在DOS中每扇区是128×2的2次方=512字节,盘片表面上以盘片中心为圆心,不同半径的同心圆称为磁道。硬盘中,不同盘片相同半径的磁道所组成的圆柱称为柱面。磁道与柱面都是表示不同半径的圆,在许多场合,磁道和柱面可以互换使用,我们知道,每个磁盘有两个面,每个面都有一个磁头,习惯用磁头号来区分。扇区,磁道(或柱面)和磁头数构成了硬盘结构的基本参数。在老式硬盘中,采用的都是这种比较古老的CHS(Cylinder/Head/Sector)结构体系。因为很久以前,在硬盘的容量还非常小的时候,人们采用与软盘类似的结构生产硬盘。也就是硬盘盘片的每一条磁道都具有相同的扇区数,由此产生了所谓的3D参数(Disk Geometry),即是磁头数(Heads)、柱面数(Cylinders)、扇区数(Sectors)以及相应的3D寻址方式。对于现在的新硬盘来说,都已经全部不采用这样的结构,而是采用了更加科学的结构方式,目前的硬盘都是线性寻址也就是直接使用扇区号来访问硬盘,137G以下的硬盘使用32位整数作为扇区号,而137G以上的硬盘使用48位整数作为扇区号。

CHS结构体系

其中:磁头数表示硬盘总共有几个磁头,也就是有几面盘片,最大为255(用8个二进制位存储);柱面数表示硬盘每一面盘片上有几条磁道,最大为1023(用10个二进制位存储);扇区数表示每一条磁道上有几个扇区,最大为63(用6个二进制位存储);每个扇区一般是512个字节,理论上讲你可以取任何一个你喜欢的数值,但好像至今还没有发现取别的值的。所以磁盘最大容量为:

255×1023×63×512/1048576=8024MB(1M=1048576Bytes)

或硬盘厂商常用的单位:

255×1023×63×512/1000000=8414MB(1M=1000000Bytes)

由于在老式硬盘的CHS结构体系中,每个磁道的扇区数相等,所以外道的记录密度要远低于内道,因此会浪费很多磁盘空间(软盘也是一样)。为了进一步提高硬盘容量,现在硬盘厂商都改用等密度结构生产硬盘。这也就是说,每个扇区的磁道长度相等,外圈磁道的扇区比内圈磁道多。采用这种结构后,硬盘不再具有实际的3D参数,寻址方式也改为线性寻址,即以扇区为单位进行寻址。而为了与使用3D寻址的老软件兼容(如使用BIOSInt13H接口的软件),厂商通常在硬盘控制器内部安装了一个地址翻译器,由它负责将老式3D参数翻译成新的线性参数。这也是为什么现在硬盘的3D参数可以有多种选择的原因(不同的工作模式可以对应不同的3D参数,如LBA、LARGE、NORMAL)。而随着磁盘密度的增加、机构的进一步复杂、功能和速度上的提高,如今的硬盘都会在磁盘里面划分出一个容量比较大的,称为“系统保留区”的区域,用于储存硬盘的各种信息、参数和控制程序,有的甚至把硬盘的Fireware也做到了系统保留区里面(原来这些信息都是储存在硬盘控制电路板的芯片上的)。这样虽然可以进一步简化生产的流程,加快生产速度和降低生产成本,但是从另一方面,却又大大增加了硬盘出现致命性损坏的几率和缩短了硬盘的使用寿命。

恢复数据的原理和方法

发觉硬盘故障,需要恢复数据的时候,第一步所要做的就是检测,判断磁盘的故障原因和数据损坏程度
只有明确磁盘的损坏程度和故障原因,才能采取正确的步骤恢复数据:

硬盘内部故障,表现形式一般是CMOS不能识别硬盘,硬盘异响,那么可能的故障原因物理磁道损坏、内电路芯片击穿、磁头损坏等等,可以采用的修复手段有:内电路检修、在超净间内打开盘腔修复,这种情况只能送到专业的数据恢复公司。

硬盘外电路故障,如果CMOS不能识别硬盘,硬盘无异响,那么可能的故障原因是外电路板损坏、芯片击穿、电压不稳烧毁等等,可以采取的手段是外电路检修,或者更换相同型号的硬盘的电路板,一般需要送到专业的数据恢复公司。

软故障,如果CMOS能识别硬盘,一般是硬盘软故障,破坏原因一般是系统错误造成数据丢失,误分区、误删除、误克隆、软件冲突、病毒破坏等等,可以采用的方法有专用数据恢复软件或者人工方式。

下面具体讲解软故障的数据恢复方法
1.        确认数据丢失的故障原因 
1.        硬盘数据丢失,故障原因包括:

病毒破坏,误克隆,硬盘误格式化,分区表失丢,误删除文件,移动硬盘盘符认不出来(无法读取其中数据,硬盘零磁道损坏),硬盘误分区,盘片逻辑坏区,硬盘存在物理坏区。

2.        文档数据损坏,如Office 系列数据文件损坏,Zip、MPEG、asf、RM 等文件数据损坏。

2.        根据故障原因,采用相应的手段和步骤

1.        备份数据,根据数据的重要程度,决定是否需要备份数据,备份数据的一般步骤是

1.        卸下损坏硬盘,接到另外一台完好的机器,注意新机器上有足够的硬盘空间备份

2.        使用ghost的原始模式(raw),一个扇区一个扇区的把损坏磁盘备份到一个镜像文件中。如果硬盘上有物理坏道,最好是采用ghost的方式制作一个磁盘镜像,然后所有的*作都在磁盘镜像上进行,这样可以最大限度的保护原始磁盘不被进一步损坏,可以最大限度的恢复数据。 ——我猜想作者是说把磁盘内容克龙到另一块磁盘上做恢复的做作,以避免在原磁盘的写*作。

3.        修复硬盘数据。修复硬盘数据有2种类型,一种直接在原始硬盘修改,一种是把读出数据存储到其他的硬盘上。基本思路就是就是根据磁盘现有的信息最大限度的推断出丢失的分区和文件系统系统的信息,把受损的文件和系统还原,所以如果信息损失太多,那么是不可能恢复数据的。比如错误删除一个文件后,随即又拷贝了较大的文件过来,那么多半是被删除的文件被新拷贝过来的文件所覆盖,几乎是无法恢复了。

一个常识就是,如果想要恢复数据,那么不要在出问题的磁盘上运行scandisk或者Norton Disk Doctor等直接修复文件系统错误的软件,切记。

零磁道,MBR和分区表DPT:

零磁道处于硬盘上一个非常重要的位置,硬盘的主引导记录区(MBR)就在这个位置上。零磁道一旦受损,将使硬盘的主引导程序和分区表信息遭到严重破坏,从而导致硬盘无法自举。
MBR:
当通过Fdisk或其他分区工具对硬盘进行分区时,分区软件会在硬盘0柱面0磁头1扇区建立MBR(Main Boot Record),即为主引导记录区,位于整个硬盘的第一个扇区,在总共512字节的主引导扇区中,主引导程序只占用了其中的446个字节,64个字节交给了DPT(Disk Partition Table硬盘分区表),最后两个字节(55 AA)属于分区结束标志。主引导程序的作用就是检查分区表是否正确以及确定哪个分区为引导分区,并在程序结束时把该分区的启动程序调入内存加以执行。
DPT:
分区表DPT(Disk Partition Table),把硬盘空间划分为几个独立的连续的存储空间,也就是分区。分区表DPT则以80H或00H为开始标志,以55AAH为结束标志。分区表决定了硬盘中的分区数量,每个分区的起始及终止扇区、大小以及是否为活动分区等。
通过破坏DPT,即可轻易地损毁硬盘分区信息。分区表分为主分区表和扩展分区表。
主分区表位于硬盘MBR的后部。从1BEH字节开始,共占用64个字节,包含四个分区表项,这也就是为什么一个磁盘的主分区和扩展分区之和总共只能有四个的原因。每个分区表项的长度为16个字节,它包含一个分区的引导标志、系统标志、起始和结尾的柱面号、扇区号、磁头号以及本分区前面的扇区数和本分区所占用的扇区数。其中”引导标志”表明此分区是否可引导,即是否活动分区。当引导标志为”80″时,此分区为活动分区;”系统标志”决定了该分区的类型,如”06″为DOS FAT16分区,”0b”为DOS FAT32分,”63″为UNIX分区等;起始和结尾的柱面号、扇区号、磁头号指明了该分区的起始和终止位置。
分区表项的16个字节分配如下:
第1字节: 引导标志 
第2字节: 起始磁头
第3字节: 低6位为起始扇区, 高2位与第4字节为起始柱面
第4字节: 起始柱面的低8位
第5字节: 系统标志
第6字节: 终止磁头
第7字节: 低6位为终止扇区, 高2位与第8字节为终止柱面
第8字节: 终止柱面的低8位
第9-12字节: 该分区前的扇区数目
第13-16字节: 该分区占用的扇区数目
扩展分区作为一个主分区占用了主分区表的一个表项。在扩展分区起始位置所指示的扇区(即该分区的第一个扇区)中,包含有第一个逻辑分区表,同样从1BEH字节开始,每个分区表项占用16个字节。逻辑分区表一般包含两个分区表项,一个指向当前的逻辑分区,另一个则指向下一个扩展分区。下一个扩展分区的首扇区又包含了一个逻辑分区表,这样以此类推,扩展分区中就可以包含多个逻辑分区。为方便说明,我们把这一系列扩展分区和逻辑分区分别编号,主扩展分区为 1号扩展分区,第一个逻辑分区表所包含的两个分区分别标为 1号逻辑分区和 2号扩展分区,依次类推。
主分区表中的分区是主分区,而扩展分区表中的是逻辑分区,并且只能存在一个扩展分区。
FS即文件系统,位于分区之内,用于管理分区中文件的存储以及各种信息,包括文件名字,大小,时间,实际占用的磁盘空间等。windows 目前常用的文件系统包括FAT12,FAT16,FAT32和NTFS系统。
DBR(Dos Boot Record)是*作系统引导记录区。它位于硬盘的每个分区的第一个扇区,是*作系统可以直接访问的第一个扇区,它一般包括一个位于该分区的*作系统的引导程序和相关的分区参数记录表。
簇,是文件系统中最小的数据存储单元,由若干个连续的扇区组成,硬盘的扇区的大小是512字节(几乎是用于所有的硬盘),也就是既是一个字节的文件也要分配给它1个簇的空间,剩余的空间都被浪费了,簇越小,那么对小文件的存储的效率越高,簇越大,文件访问的效率高,但是浪费空间比较严重。
FAT(file allocation table)即文件分配表,记录了分区中簇的的使用情况,FAT表的大小与硬盘的分区的大小有关,为了数据安全起见,FAT一般做两个, 二FAT为第一FAT的备份,用于FAT12,FAT16,和FAT32文件系统。
DIR是DIRECTORY即根目录区的简写,根目录区存储了文件系统的根目录中的文件或者目录的信息(包括文件的名字,大小,所在的磁盘空间等等),FAT12,FAT16的DIR紧接在第二FAT表之后,而FAT32的根目录区可以在分区的任何一个簇。
MFT(Master File Table)是NTFS中存储有关文件的各种信息的数据结构,包括文件的大小,时间,所占据的数据空间等等。
以FAT32为例,FAT32分区的的0-2扇区为FAT32文件系统的DBR即引导扇区,3-5扇区为0-2扇区的备份。6-31扇区为空,32扇区开始为第一个FAT表,FAT表的大小与硬盘的分区的大小有关。随后是第2个FAT表,剩余的空间都是实际的文件所占用的,包括目录和文件。FAT32文件系统的根目录并不一定是数据区的第一个簇,它可以位于数据区的任何一个簇,这也是FAT32的根目录大小不在受255个文件限制的原因,这也是FAT32的文件名可以支持长文件名的原因之一。
分区表丢失,表现为硬盘原先所有分区或者部分分区没了,在磁盘管理器(winxp win2000 win2003)看到未分区的硬盘或者未分区的空间。有多种可能:
病毒,当年的cih病毒会用无效的数据填充分区表和第一个分区的数据,这种情况下,从前面介绍的分区的性质来看,c盘的数据很难恢复,而随后d盘和e盘等分区的实际数据并没有被破坏,而仅仅是分区表丢失而已,所以只要找到D盘和E盘等分区的正确的起始和结束位置,很容易恢复。
重新分区,使用fdisk对磁盘重新划分空间分布,那么原来的分区表被新的分区表取代,这个时候,同样是原来分区的数据没有损坏,仅仅是分区表指向了不正确的位置。

误删除文件的恢复

误删除文件的恢复的原理是什么呢?为什么删除文件后,又可以恢复回来?是不是所有的删除的文件都可以恢复?

当我们存储一个文件的时候,*作系统首先在一个记录所有空间使用情况的表格中,找到足够容纳我们的新文件的空间,然后把文件内容写到相对应的硬盘扇区上,最后在表格中标出该空间被占用了。

当我们删除一个文件的时候,一般并不对实际文件所占用的扇区进行*作,而是仅仅在该表格中指明那些空间是空白的了,可以分配给别的文件使用。在这个时候,被删除的文件的实际内容并没有受到破坏,可以恢复回来。如果我们删除一个文件后,又重新创建了一个文件,那么被删除文件所占用的扇区就有可能被新创建的文件所使用,这时候就无法恢复原来被删除的文件了。所以一旦错误的删除了文件,必须注意的就是不要对该文件所在的分区进行写*作了,否则有可能覆盖原来删除的文件,从而导致数据无法恢复。

对于误删除的文件,我们有很多选择,如finaldata,recover4all,easyrecovery,这些软件使用很简单,直接按照向导的指示就可以了。

下面介绍一种手工恢复被删除数据的方法,特别是使用这种自动化的方法恢复无效的时候,这种方法适合恢复有明显特征的结构简单的文件,如文本文件,如果格式复杂,就需要写一个类似的程序来恢复了。原理就是直接在分区中寻找被删除的文件的内容。

一个实例就是微软公司的vc6,vc6的ide有一个bug,一直没有修复,就是存储写好的程序代码的时候,偶然会弹出一个对话框说无法存储文件,这个时候必须再存一次才可以,如果你直接关闭vc6,就会发现刚才那个文件被删除了(这个bug是微软确认的,一直到vc6的sp5补丁也没有修复)。

我的一个朋友使用vc6的时候遇到了这个bug,而且他以为vc6出了问题,直接关闭了vc6,结果很费劲才调试好的很长的一的文件就失踪了。

我首先试用了finaldata和easyrecovery,结果找出很多以前删除的文件,就是没有需要的。没有办法的情况下,只好使用强行搜索的方法了

1.        运行winhex,选择tools菜单中的opendisk,选择误删除的文件所在的逻辑盘c盘,

2.        选择search菜单,使用find text命令,在打开的c盘上直接搜索程序代码中的特征串“增加了处理Reg_Expand_SZ”,

3.        经过一段时间后,把找到的代码所在扇区的前后几个扇区全部复制下来,拷贝到一个新的文件中,这样就找回了原来的代码。

对于恢复结构性很强的文档,如果自动化的方式不起作用,可以写一个小程序来搜索的同时加以判断,或者直接利用winhex提供的接口写一个脚本,如果数据很重要,这样的手段也是很需要的。如果文件分散在分区的多个位置,还需要根据文档的内部结构来重新组织文档,才能彻底恢复数据。

误格式化的原理也是非常类似,仅仅是快速格式化的时候,并没有覆盖原来的数据,所以可以恢复。

(0)

相关推荐

  • 资料:数据恢复知识基础

    计算机上只有数据是最关键的,数据的丢失才是最大的损失.下面我来讲解一些数据恢复的基本知识. 首先申明一点,对于重要数据,备份数据才是防止数据丢失的根本方法,而数据恢复依赖于很多因素,很难完全恢复数据,一般是仅仅可以恢复部分数据. 数据恢复就是找回丢失的数据,例如彻底删除某个文件或文件夹,重新格式化磁盘,重新分区磁盘等等都会造成数据的丢失.更严重的数据丢失是存储介质硬件损坏,例如,硬盘不小心摔坏了.硬盘根本就不认了.硬盘有大量坏道等等.最值得注意的一点是,一旦意识到数据丢失了,立刻停止一些不必要的

  • Cookies的各方面知识(基础/高级)深度了解

    一,前言 Cookies想必所有人都了解, 但是未必所有人都精通.本文讲解了Cookies的各方面知识. 二,基础知识 1.什么是Cookies Cookie 是一小段文本信息,伴随着用户请求和页面在 Web 服务器和浏览器之间传递.Cookie 包含每次用户访问站点时 Web 应用程序都可以读取的信息. 例如,如果在用户请求站点中的页面时应用程序发送给该用户的不仅仅是一个页面,还有一个包含日期和时间的 Cookie,用户的浏览器在获得页面的同时还获得了该 Cookie,并将它存储在用户硬盘上的

  • Python魔术方法详解

    介绍 此教程为我的数篇文章中的一个重点.主题是魔术方法. 什么是魔术方法?他们是面向对象的Python的一切.他们是可以给你的类增加"magic"的特殊方法.他们总是被双下划线所包围(e.g. __init__ 或者 __lt__).然而他们的文档却远没有提供应该有的内容.Python中所有的魔术方法均在Python官方文档中有相应描述,但是对于他们的描述比较混乱而且组织比较松散.很难找到有一个例子(也许他们原本打算的很好,在开始语言参考中有描述很详细,然而随之而来的确是枯燥的语法描述

  • python编程培训 python培训靠谱吗

    我们在论坛和贴吧上看到无论是老的程序员和新手都想更快的入门和精通python编程,但是市面上众多的书籍让大家无从下手,很多书籍和视频都声称能够快速学习,时间有限,大家哪有精力一个个尝试呢,我们的小编和技术人员根据大家这方面的困惑,全面分析一下关于python编程培训等方面的问题,希望我们的分析能让你的python学习之路有一个方向. 如果你是新手还没有入门,那么找一本不错的书籍是你学习python的比较好的途径之一,我们先给大家分享基本有价值的python编程书籍: python编程学习电子书

  • 简单了解 MySQL 中相关的锁

    本文主要是带大家快速了解 InnoDB 中锁相关的知识 基础概念解析和RocketMQ详细的源码解析 http://xiazai.jb51.net/202105/yuanma/RocketMQ_jb51.rar 为什么需要加锁 首先,为什么要加锁?我想我不用多说了,想象接下来的场景你就能 GET 了. 你在商场的卫生间上厕所,此时你一定会做的操作是啥?锁门.如果不锁门,上厕所上着上着,啪一下门就被打开了,可能大概也许似乎貌似有那么一丁点的不太合适. 数据也是一样,在并发的场景下,如果不对数据加锁

  • python 利用PyAutoGUI快速构建自动化操作脚本

    一.背景 大家好,我是安果! 我们经常遇到需要进行大量重复操作的时候,比如:网页上填表,对 web 版本 OA 进行操作,自动化测试或者给新系统首次添加数据等 这些操作的特点往往是:数据同构,大多是已经有了的结构化数据:操作比较呆板,都是同一个流程的点击.输入:数据量大,极大消耗操作人精力 那么能不能自动化呢? 二.自动化的方案 如果你在 web 上进行操作, Python 的 Selenium 可以满足要求.如果需要对 GUI 界面进行操作,你恐怕得试验下"按键精灵"能不能满足要求.

  • python机器学习朴素贝叶斯算法及模型的选择和调优详解

    目录 一.概率知识基础 1.概率 2.联合概率 3.条件概率 二.朴素贝叶斯 1.朴素贝叶斯计算方式 2.拉普拉斯平滑 3.朴素贝叶斯API 三.朴素贝叶斯算法案例 1.案例概述 2.数据获取 3.数据处理 4.算法流程 5.注意事项 四.分类模型的评估 1.混淆矩阵 2.评估模型API 3.模型选择与调优 ①交叉验证 ②网格搜索 五.以knn为例的模型调优使用方法 1.对超参数进行构造 2.进行网格搜索 3.结果查看 一.概率知识基础 1.概率 概率就是某件事情发生的可能性. 2.联合概率 包

  • Unity游戏开发之2048游戏的实现

    目录 一.前言 二.游戏开发知识储备 2-1技术栈 三.休闲类游戏<2048>开发实战 3-1玩法概述 3-2实现分析 3-3搭建场景 3-4实现代码 一.前言 写今天这篇文章的缘由,其实是来自于前段时间和粉丝的一个聊天,最近他打算参加游戏创作大赛,问我需要准备学习什么知识,以及参加比赛的注意事项一类: 我相信因为热爱游戏而前来投身于U3D学习的粉丝想来不是少数,兴趣可以驱动学习,在完善自己心爱游戏的过程中,要不断的去学习,不断的提高自己. 而参与游戏设计比赛,更是提高自身技术实力.增长眼界见

  • 搭建Consul服务发现与服务网格

    目录 第一部分:Consul 基础 1,Consul 介绍 2,安装 Consul Ubuntu/Debian 系统 Centos/RHEL 系统 检查安装 3,运行 Consul Agent 启动 agent 发现数据中心成员 查看 UI 4,在 Consul Service Discovery 中注册服务 端口 定义服务 使用配置启动服务 如何重新加载配置文件 5,查询服务 通过 HTTP API 通过 UI 查询 6,DNS 知识与查询基础知识 基础知识 通过 DNS 查询 Consul

  • Pthread并发编程之线程基本元素和状态的剖析

    目录 前言 深入理解 pthread_create 基础例子介绍 深入理解参数 thread 深入理解参数 arg 深入理解参数 attr 设置线程栈空间的大小 自己为线程的栈申请空间 使用 malloc 函数申请内存空间 使用 mmap 申请内存作为栈空间 深入理解线程的状态 关于栈大小程序的一个小疑惑 总结 前言 在本篇文章当中讲主要给大家介绍 pthread 并发编程当中关于线程的基础概念,并且深入剖析进程的相关属性和设置,以及线程在内存当中的布局形式,帮助大家深刻理解线程. 深入理解 p

随机推荐