【整理】nand相关
记录nand相关知识。主要是mtd和ubi
什么是UBI
它是一种flash管理方式
flash是一系列连续的物理擦除块组成的。
UBI卷是一系列连续的逻辑擦除块(eraseblock),每一块都能够被映射到物理分区。这样的映射是由UBI管理的。
UBI是靠什么来管理这些物理擦除块的呢??
首先要区分一些层次:
- MTD subsystem :
provide ubiform interface to access flash (e.g. /dev/mtd0) - UBI subsystem
UBI works on top of MTD devices ,provide a notion of UBI volumes - UBIFS file system
work on top of UBI volume
UBI介绍
综述
UBI全称Unsorted Block Images,是一种原始flash设备的卷管理系统。这个系统能在一个物理的flash设备上管理操纵多个卷而且能在整个flash芯片上实现损耗均衡。
从某种意义上说,UBI和LVM有点相似,LVM将逻辑扇区映射到物理扇区上面。UBI映射逻辑擦除块到物理擦除块。可是除了映射。UBI还实现了全局的损耗均衡和透明的I/O错误处理。
- 一个UBI卷就是一串连续的逻辑擦除块。
每个逻辑擦除块能够被映射到不论什么一个物理擦除块上面。这个映射是由UBI管理。这样的映射对用户是透明的,同一时候这样的映射也是UBI实现全局的损耗均衡的基础。
通过每个物理擦除块记录的擦除计数,能够将数据从损耗严重的物理块转移到损耗较少的擦除块。
- UBI卷的大小在卷被创建的时候被指定。这个大小也能够动态的被改变。实用户空间工具能够用来操作UBI卷。
- 总共同拥有两种类型的UBI卷,一种是动态卷。一种是静态卷。
静态卷是仅仅读的,内容被CRC-32校验保护。
动态卷可读可写,上层软件负责数据完整性。
- UBI能管理flash的坏块,这样上层软件能够不须要考虑坏块。UBI有一个预留的物理块池,当一个物理擦除块坏掉了,UBI会利用预留的块来替代这个坏块。UBI将数据从新出现的坏块上转移到预留的好块上面。这个功能的优点就是应用层软件不会感知究竟层的I/O错误。
NAND Flash在读写的时候可能会出现bit翻转,bit翻转能够被ECC校验来纠正,可是这样的现象长期积累会导致数据丢失。UBI将出现bit翻转块上的数据转移到其他块上面。这样的机制叫做冲刷,冲刷过程在后台完毕,对上层软件是透明的。
以下是UBI特性的列表
UBI提供一种卷的机制。能够动态创建、删除、重设置卷大小等操作
UBI在整个Flash设备上提供了损耗平衡的机制,你能够不断的对某一个逻辑擦除块进行擦除,UBI会将你的操作均匀分散到其他各个物理块上面。
UBI透明的处理Flash上面的坏块
UBI通过冲刷机制最大限度的减小数据丢失的几率
UBI和MTD分析对照,有例如以下的特点。
两者都由擦除块组成,在UBI中是逻辑擦除块,在MTD分区中是物理擦除块。
两者都支持三种主要的擦做,read、write和erase
UBI卷没有擦除块损耗均衡的限制,用户层软件不须要关注损耗均衡,简化了用户层软件的设计
UBI卷没有坏块的情况须要考虑。这也使得上层软件设计简单
UBI卷能够被动态创建、删除和又一次分配大小。而MTD分区是静态的。
UBI能处理bit翻转的情况,用户层软件不须要考虑bit翻转
UBI提供了卷升级操作,这样能够简单的探測软件升级的中断而且予以恢复
UBI提供了原子逻辑擦除块更换操作,这个操作同意更改逻辑擦除块中的内容过程中假设遇到了断电重新启动等情况不会丢失原来逻辑擦除块中的内容。这个功能对上层软件比方文件系统特别实用。
UBI提供un-map操作,这样的操作仅仅是将逻辑块和物理块之间的映射去除掉。然后调度物理块进行后台擦除操作,这个过程很迅速,上层软件不须要等待较长的擦除时间。
UBI 对外提供一种块设备,同意随机訪问,块适应的文件系统挂载在UBI卷上面。实现这样的功能的主要原因是UBI卷不须要考虑坏块。
另外UBI还额外提供一种叫做gluebi的驱动来在UBI卷上模拟MTD设备,这样的做法看起来有一点奇怪。由于UBI本身工作在MTD设备上面。而gluebi又要在UBI上模拟一个MTD设备。
可是这样的做法实际是可行的,这样能够在UBI上执行诸如jffs2之类的软件。虽然如此。新软件还是能充分利用UBI的特性,让UBI来处理Flash技术引入的一些问题。
UBI用户空间工具
以下列举了UBI相关的一些工具 ubinfo - 提供从系统中找到的UBI设备、UBI卷的相关信息
ubiattach - 链接MTD设备(MTD设备描写叙述原始Flash设备)到UBI而且创建对应的UBI设备;
ubidetach - ubiattach相反的操作,将MTD设备从UBI设备上去链接;
ubimkvol - 从UBI设备上创建UBI卷;
ubirmvol - 从UBI设备上删除UBI卷;
ubiblock - 管理UBI卷上的block;
ubinize - 制作UBI镜像;
ubiformat - 格式化恐的Flash设备,擦除Flash,保存擦除计数。写入UBI镜像到Flash;
mtdinfo - 报告从系统中找到的UBI设备的信息.
UBI头
UBI存储两个64字节的文件头在每个非坏块的起始位置
擦除计数头(或者称为EC头)包括物理擦除块的擦除次数以及其他一些不太重要的信息
卷标记头(或者称为VID头)包括了属于这块物理擦除块的卷ID和逻辑块号,另外包括了其他一些不太重要的信息
全部的UBI头都使用CRC-32校验来保护。用户能够參考/drivers/mtd/ubi/ubi-media.h文件获得更加具体的文件头内容的信息。
当UBI链接一个MTD设备时,UBI系统会扫描整个MTD设备,读取全部的文件头,而且校验CRC-32的校验值。之后UBI系统会记录每一个物理擦除块的擦除操作计数,同一时候建立逻辑块到物理块的映射到内存中。用户能够參考后面相关的章节了解这个过程的具体描写叙述。
当UBI系统擦除了一个物理块。它会在这个物理块上写入一个EC头而且添加擦除计数。这意味着物理擦除块除了在擦除物理块到写入EC头的这段短临时间内总有一个EC头,假设在上述短临时间内系统发生了断电等情况,EC头会丢失或者损坏。这样的情况下UBI系统又一次写入一个EC头而且使用一个整个扫描计算得到的UBI的平均擦除计数作为EC头的擦除计数。
逻辑擦除块的去映射操作仅仅是将逻辑块从映射的物理块去映射然后调度物理块进行擦除操作。
擦除操作中EC头会被直接写入物理块中,而VID头并不写入物理块
逻辑擦除块的映射操作以及当往一个还没有映射的逻辑块中写入内容的时候。
UBI寻找一个合适的物理块而且向当中写入VID头(此前EC头已经被写入到物理块中了)。须要注意的是假设向一个已经映射的逻辑块中写入内容的话仅仅直接写入数据到映射到的物理块而不须要操作UBI头。
UBI系统为每个物理块维护了两个文件头,基本的原因是UBI须要在不同的时间向Flash中写入不同的信息。这两个不同的时间点如以下所述。
当一个物理块被擦除后,UBI须要迅速向物理块中写入EC头记录这个物理块的擦除次数。以免这个擦除计数因为断电重新启动而被丢失的概率。
当UBI映射一个物理块到逻辑块时,VID头会被写入到物理块中。
当EC头被写入到物理块中的时候,UBI还不清楚这个物理块将要相应的卷ID和以后将要被映射的逻辑块号。
这就是UBI须要使用两个分立的文件头的原因。
UBI 卷表
卷表示UBI系统保存在Flash上的一个数据结构,这个数据结构保存了一个UBI设备上面每一个卷的信息。一个卷表是每一个卷记录信息的数组。每一个卷记录信息包括了以下的详细内容:
- 卷大小。卷名称。卷类型(静态卷或者动态卷),卷对齐。升级标识(假设这个标记被设置标识在卷升级操作中操作被打断)。自己主动重分配大小标记,这个卷记录的CRC-32校验。
- 每一条记录描写叙述一个UBI卷,卷表上记录的索引表示卷ID。
比方说卷0由卷表的第0条表项来描写叙述,以此类推。
卷表中的表项由逻辑卷的大小来限制,可是最大不能超过128条表项。这就是说UBI设备不能创建超过128卷。
- 每次创建、删除、又一次分配卷大小、又一次命名卷名、升级操作都会改变对应的卷表项。UBI维护了同样的两份卷表来添加UBI系统的可靠性。
详细实现细节
在UBI系统内部,卷表存储在特殊用途的卷上面,这个特殊用途的卷被叫做层卷。这个卷仅仅包括了两个逻辑块,每个中都包括了一个卷表的拷贝。层卷是一种UBI系统的”内部”卷,用户不能訪问到这个卷。当UBI系统读写卷表时。使用和普通卷同样的机制。
UBI使用以下的算法来更新卷表记录项。
- 将卷表的内容在内存中准备好。
- 将层卷中的LEB0逻辑块进行去映射操作。
- 将新的卷表项写入到层卷的LEB0逻辑块中。
- 将层卷中的LEB1逻辑块进行去映射操作。
- 将新的卷表项写入到层卷的LEB1逻辑块中。
- 刷新UBI的工作队列确保之前去映射的逻辑块被擦除掉了
当UBI链接MTD设备的时候。必须确保两份卷表内容一致。
假设两份卷表的内容不一致,就用LEB0逻辑块的卷标拷贝覆盖LEB1逻辑块的内容。
假设当中某一份的内容损坏了,就用那份完整的拷贝覆盖损坏的内容。
Flash最小的输入/输出单位
UBI使用了一种抽象的Flash模型。简而言之就是,UBI将MTD设备看成事由一个个擦除块组成的。擦除块分为好块和坏块。好块能够进行读取。写入,擦除操作。
对Flash的读写操作都仅仅能以最小擦除块的大小进行。这个大小取决于Flash的类型
NOR Flash通常的最小IO大小事1字节。NOR Flash通常同意单字节的对Flash进行读写操作,NOR Flash甚至能够对设备上单比特进行操作
NAND Flash通常以512、2048、4096字节作为设备IO的最小单位。一般这个最小单位就是NAND Flash的一页的大小。
NAND Flash将每一页的ECC校验值存储到OOB区中,这就意味着整个NAND Flash的一页内容必须一次写入从而能够计算出整个页的ECC校验值。整个页的内容页必须一次性读出以校验ECC校验值。
Flash设备的最小IO大小是一个非常重要的概念,对UBI系统有非常多影响。比方说:
UBI系统中VID头部的位置就取决于Flash设备的最小IO大小,还有UBI系统中逻辑擦除块的大小也取决于Flash设备的最小IO大小。一般来说,最小IO值越大。逻辑擦除块反而会越小,原因是UBI头占用的空间会越大。
全部对逻辑擦除块的写操作都必须是和最小IO值对齐的。必须是最小IO值的整数倍。
对于读操作没有这种限制。其实在MTD设备层面也是依照最小IO值大小进行读取的。读入到一个缓冲空间后,最后仅仅拷贝了用户请求的字节数目给用户。
UBI 文件头位置
EC头都放置在擦除块的開始偏移位置,占用64字节空间。
之后防止VID头,VID头要么放置在偏移最小IO大小的位置,要么放置在子页位置,也占用64字节空间。一般有例如以下的三种情况
对于NOR Flash情况,最小IO为1byte。全部VID头紧接着就放置在EC头的后面
对于有子页的NAND Flash的情况。VID放置在第一个页的子页上面
对于没有子页的NAND Flash情况。VID头放置在第二个页上面
Flash空间的开销
UBI系统会使用一些Flash空间作为其系统管理的开销。这样就减小了UBI系统用户可用的Flash大小。
一般一个UBI系统Flash系统开销有例如以下:
两个物理擦除块保存卷表
一个物理擦除块保留给磨损均衡使用
一个物理擦除块保留给原子改变逻辑擦除块使用
另外另一些物理擦除块保留给坏块替换。这个仅仅对NAND Flash是这样。保留物理擦除块多少是能够配置的,默认是1024个物理擦除块中保留20个擦除块。
在物理擦除块最開始的一部分空间还要保留出来给EC头和VID头使用。保留的这部分空间大小取决与Flash的种类。
保留擦除计数
当使用UBI的时候,非常重要的一个概念就是你必须意识到UBI保存了擦除计数在Flash介质上面。
也就是每个可用的物理块都保存了一个记录了擦除次数的EC头在物理块的開始部分。不丢失这部分数据是非常重要的。这样用来操作这些物理块的工具必须是能检測到UBI的存在。MTD工具中相关的工具能正确的操作UBI系统上的物理擦除块。
UBI镜像和擦除相关
以下的步骤就是擦除UBI镜像的一般过程
首先,扫描整个UBI分区,收集每一个擦除块上面的EC值,也就是读出没一个PEB的VID header,检查CRC-32校验。而且记录擦除计数到内存中,一般这个过程没有必要读取VID Header。遇到坏快就跳过去。
计算出平均的EC 记述值,这个值会被用来又一次写入到EC Header丢失或者坏掉的PEB块上面。
这种EC Header丢失或者损坏的情况出如今掉电重新启动等情况下。
这种PEB不会非常多。
假设仅仅是单纯的擦除掉flash,没一个PEB块会被擦除。合适的EC 头会被写入到PEB的起始位置。EC Header中擦除计数应该对应的加1,坏块应该跳过。对于NandFlash,擦除和写入过程中假设遇到了IO错误,对应的块就应该被标记为坏快。
假设是烧写UBI镜像,对应的步骤例如以下
首先将一块PEB大小的镜像读入到内存buffer中。将buffer中余下的空间所有设置成0xff,擦除PEB。改动EC Header的buffer空间,添加EC counter计数。又一次计算CRC-32的校验值。
将buffer写入到物理擦除块中。
通常,假设遇到坏快的话须要跳过坏快,在擦除和写入Flash过程中假设遇到了坏块就须要将对应的Flash块标记为坏块。
通常来说。UBI的镜像会比Flash要大一些,所以擦除程序须要将UBI镜像区域正确的写入,而且将多余的Flash区域正确的擦除
须要了解的是,当写入一个UBI镜像的时候,没有必要关心UBI镜像写到擦除块上面的顺序,地一个输入块能够写如到地一个物理块。也能够写入到第二个。第三个上面。
假设你为产线上写一个擦除程序,你没有必要关心去改变EC Header的擦除计数的添加。由于,产线上的Flash基本上都是新的。擦除计数能够觉得是0
UBI标记擦除块为坏块
这一节仅仅和NANDflash相关,由于仅仅有NAND Flash才存在坏块。有两种情形UBI会标识擦除块为坏块。
一种情况是写擦除块操作失败,这个时候UBI将数据从这个物理块写入到其他物理块,进行数据恢复,并将发生写错误的物理块传递到后台进行測试判定是否为坏块。
假设是擦除操作发射IO错误,直接将这个物理块标记为坏块。
坏块拷问(bad block torturing)是在系统后台进行的,目的是为了检測物理块是否真的是坏块。由于发生写错误会有多种原因。比方驱动程序写得有问题。或者上层软件写得有问题,对同一块Flash区域进行了多次写入。所以坏块拷问是非常有必要的。避免坏块的误判。
坏块的拷问步骤例如以下:
擦除物理块
又一次读入擦除块,检查是不是全0xFF字节
写入測试模式的字节
将数据读回并检查測试字节
检查多个測试式样的字节(0xA5,0x5A。0x00)
假设上面的坏块拷问过程都能顺利通过,那么这个物理块不会被标识为坏块。在坏快拷问过程中假设出现了bit反转,则这个块就被标记为坏块。
torture_peb()函数就是坏块拷问的详细过程。
可扩展性问题
很遗憾,UBI的初始时间和Flash擦除块多少成正比。这意味着Flash越大,UBI系统初始化的时间就越长。
从linux V3.7開始UBi系统推出了一个新的特性叫做FastMap,这个特性使得系统链接初始化UBI的时间是一个常数。
UBI链接一个MTD设备的时候,首先去扫描这个MTD设备,从每一块物理块中读取EC和VID头。也就是从norflash中读取头128字节,或者从NandFlash中读取每一个擦除块的头两页(对于有子页的就是读取头两个子页)。无论怎么样。这都要比jffs2挂载mtd设备读取的内容少非常多。UBI链接一个mtd设备比jffs挂载一个mtd设备要快非常多倍。
UBI要为没一个EC头和VID头做CRC校验,这会花费一定的cpu运算时间。可是和Flash的IO时间相比是很微小的。
UBI的实现细节
要实现UBI的功能,UBI系统必须管理三张表,例如以下
第一张表就是 volume table,这个表记录了和卷相关的一些信息,比方卷大小,标记flag等等。
这个表直接记录在Flash上面。
第二张表就是eraseblock association table。这个表的作用就是记录逻辑卷到物理卷的映射,当上层软件操作写一个逻辑卷的时候,UBI系统首先将逻辑卷号转换为物理卷号,然后将内容写入到相应的物理卷上面。
这个表仅仅存在于内存中,并没有记录在Flash上面,内存生成这样的表的方法是在UBI初始化的时候对系统中的全部物理块进行扫描,然后形成这张表。
第三张表就是物理块上擦除计数的表。这个表主要是在损耗均衡系统中使用到。这个表也不是存在flash上,而是UBI系统初始化的时候通过扫描物理块建成的。
UBI系统中每一个擦除块都要花费掉两个page来记录EC header和VID header。这中额外的花费会损耗掉Flash存储数据的空间。在UBI2中,EC header和VID header都会被存储到OOB区域。由于不会损耗Flash存储数据的空间
bit位翻转
Nand Flash因为本身硬件的内在特性,会导致(极其)偶尔的出现位反转的现象。
所谓的位反转。bit flip,指的是原先Nand Flash中的某个位。变化了,即要么从1变成0了。要么从0变成1了
翻转原因
1. 漂移效应(Drifting Effects)
漂移效应指的是,Nand Flash中cell的电压值,慢慢地变了,变的和原始值不一样了。
2. 编程干扰所产生的错误(Program-Disturb Errors)
此现象有时候也叫做,过度编程效应(over-program effect)。
对于某个页面的编程操作,即写操作。引起非相关的其它的页面的某个位跳变了。
3. 读操作干扰产生的错误(Read-Disturb Errors)
此效应是,对一个页进行数据读取操作,却使得相应的某个位的数据。产生了永久性的变化,即Nand Flash上的该位的值变了。
假设仅仅是对于单个位的跳变。或许问题看起来并非非常严重。然而。假设恰巧是某个关键文件的某位变化了,那么问题就严重了。
假设位反转,仅仅是读取数据出来时候报告出来的位反转。那么非常easy。仅仅须要又一次再去读取一次数据,就可以解决此问题。
可是。假设是Nand Flash物理上的某个位真正的翻转了,那么须要通过相应的ECC校验去解决。
相对Nor Flash来说,Nand Flash中,位反转的现象,相对更加easy发生。因此。Nand Flash厂家都推荐。在使用Nand Flash的时候,最好要应用ECC算法。
当Nand Flash应用于多媒体信息,比方存储音视频文件,那么位反转所造成的问题。并不严重。
当用于存储操作系统,配置文件和其它敏感信息的时候,必需要用ECC。以实现数据的校验,保证数据的正确性。
mtd
MTD,Memory Technology Device即内存技术设备
字符设备和块设备的差别在于前者仅仅能被顺序读写。后者能够随机訪问;同一时候,两者读写数据的基本单元不同。
字符设备。以字节为基本单位,在Linux中,字符设备实现的比較简单,不须要缓冲区就可以直接读写。内核例程和用户态API一一相应。用户层的Read函数直接相应了内核中的Read例程,这样的映射关系由字符设备的file_operations维护。
块设备。则以块为单位接受输入和返回输出。对这样的设备的读写是按块进行的。其接口相对于字符设备复杂,read、write API没有直接到块设备层。而是直接到文件系统层。然后再由文件系统层发起读写请求。
同一时候,因为块设备的IO性能与CPU相比非常差。因此,块设备的数据流往往会引入文件系统的Cache机制。
MTD设备既非块设备也不是字符设备,但能够同一时候提供字符设备和块设备接口来操作它。
MTD总概述
Linux中MTD的全部源代码位于/drivers/mtd子文件夹下,
相关链接
http://www.linux-mtd.infradead.org/doc/ubi.html
http://www.crifan.com/order_nand_flash_bit-reversed_bit_flipped/
http://blog.chinaunix.net/uid-28236237-id-4217118.html
http://blog.csdn.net/bugouyonggan/article/details/9167213
【整理】nand相关的更多相关文章
- 整理volatile相关知识点
前言:volatile关键字在面试中经常被问到,从volatile关键字可以引申出许多知识点,因此有必要对此进行总结.本文根据<深入理解Java虚拟机——JVM高级特性与最佳实践>中的相关 ...
- 微信小程序入口场景的问题整理与相关解决方案
前言 最近一段时间都在做小程序. 虽然是第二次开发小程序,但是上次做小程序已经是一年前的事了,所以最终还是被坑得死去活来. 这次是从零开始开发一个小程序,其实除了一些莫名其妙的兼容性问题,大多数坑点都 ...
- 最近整理AI相关感想
前言 目前笔者致力于 在AI 开发研究,四大平台里,百度AI 提供 的开发者资料是最全,开发的友好度也是最高的,很多都已经集成在SDK中,支持许多语言体系. 其实 作为公司层面的考虑,针对技术的研究出 ...
- 前端基础问题整理-HTML相关
DOCTYPE的作用以及常见的DOCTYPE类型 <!DOCTYPE>声明位于文档中的最前面的位置,处于 <html> 标签之前,用来告知浏览器页面目前的文件是用哪种版本的HT ...
- 整理Ruby相关的各种概念(rvm, gem, bundle, rake, rails等)
转自:http://henter.me/post/ruby-rvm-gem-rake-bundle-rails.html Ruby 这个就不用多说了 RVM 用于帮你安装Ruby环境,帮你管理多个Ru ...
- 整理windows相关软件的环境变量
java: JAVA_HOME [安装java的home目录] PATH [在最后添加] ;%JAVA_HOME%\bin; CLASSPATH [文本框的起始位 ...
- 容易遗忘的JS知识点整理—hasOwnProperty相关
为了判断一个对象是否包含自定义属性而不是原型链上的属性,我们需要使用继承自 Object.prototype 的 hasOwnProperty方法.hasOwnProperty 是 JavaScrip ...
- 前端面试题整理——webpack相关考点
webpack是开发工具,面试考点重点在配置和使用,原理理解不需要太深. 一.基本配置 1.拆分配置和merge 将公共配置跟dev和prod的配置拆分,然后通过webpack-merge对配置进行整 ...
- 前端面试题整理——VUE相关题目与回答
1.v-if与v-show的区别? v-if的原理是根据判断条件来动态的进行增删DOM元素, v-show是根据判断条件来动态的进行显示和隐藏元素,频繁的进行增删DOM操作会影响页面加载速度和性能所以 ...
随机推荐
- 入门人工智能的首选语言为什么会是Python?
为何人工智能(AI)首选Python?当你读完这篇文章就会明白了.为何人工智能(AI)首选Python?读完这篇文章你就知道了.我们看谷歌的TensorFlow基本上所有的代码都是C++和Python ...
- PAT Basic 1028
1028 人口普查 某城镇进行人口普查,得到了全体居民的生日.现请你写个程序,找出镇上最年长和最年轻的人. 这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过200岁的老人,而 ...
- 解决vm安装centos7网络无法启动问题
采用以下命令: systemctl stop NetworkManager systemctl disable NetworkManager
- python基础——12(包的概念)
一.模块 1.模块的加载顺序 加载顺序:内存-->内置-->sys.path(一系列自定义模块) import sys sys.path #环境变量:存放文件路径的列表 重点:默认列表的 ...
- linux查找和替换命令
http://blog.csdn.net/imyang2007/article/details/8105499 命令的东西应该多练,熟能生巧.
- wordpress需要FTP用户名密码的问题
wordpress安装删除插件需要FTP用户名密码的问题 方法一: 服务器命令操作: 1.在wordpress目录下面wp-config.php末尾加入下面代码: if(is_admin()) { ...
- Leetcode 372.超级次方
超级次方 你的任务是计算 ab 对 1337 取模,a 是一个正整数,b 是一个非常大的正整数且会以数组形式给出. 示例 1: 输入: a = 2, b = [3] 输出: 8 示例 2: 输入: a ...
- HDU——4549M斐波那契数列(矩阵快速幂+快速幂+费马小定理)
M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Su ...
- 【二叉树】hdu 1710 Binary Tree Traversals
acm.hdu.edu.cn/showproblem.php?pid=1710 [题意] 给定一棵二叉树的前序遍历和中序遍历,输出后序遍历 [思路] 根据前序遍历和中序遍历递归建树,再后续遍历输出 m ...
- Moya 与 RxSwift 使用
如在OC中使用AFNetworking一般,Swift我们用Alamofire来做网络库.而Moya在Alamofire的基础上又封装了一层: 1.关于moya moya 官方说moya有以下特性-_ ...