Wenguang's Introduction to Universal Disk Format (UDF)
是初学UDF格式的有用文档,可惜是英文,对于大多数不熟悉英文的工程人员读起来费劲,当然对于读spec还是要容易一些。于是有想法把它翻译成中文,希望能把这个工程完成吧。
尊重作者,把链接贴出,也许不是原始链接:
"Wenguang's Introduction to Universal Disk Format (UDF)"
上面的是来自Google网址,由于你懂得的原因打不开,我是从百度文库里面找到的一个副本:
http://wenku.baidu.com/link?url=9nqTcMpbbRhSL5HfQCeCOb18ghHcUSHDSuIhXsyjlq4-a7HfEPSVcn3vorvM4STInLHabpS0b_T1RtdCRiaQC9UBDrDOgsfZ2wuOirnjiH3
下面是翻译:
Wengang的UDF介绍
注意,由于MobileMe的政策改变,这个页面在2009年7月之后已经不在可编辑。链接到这个页面的新版本会发出外部链接到关于UDF的文章在Wikipedia网站。
大纲目录:
1. 什么是UDF?
2. 为什么用UDF?
3. UDF的历史版本
4. UDF的结构标准
5. UDF规格书简介
5.1 UDF格式的重点说明
5.2 UDF的卷结构和加载流程
5.3 UDF的分区结构
5.4 UDF的文件和目录结构
5.5 UDF的一些专业名词解说
5.6 在UDF标准里面没有提到的提示和注意事项
1. 什么是UDF?
英文全称Universal Disk Format (UDF),通用碟片格式,是一种由OSTA组织制定的文件规格. 其目的是取代光盘(CD,DVD等)上面使用的ISO9660文件系统。它也是在可移动存储媒体使用的FAT格式的不错的替代选择.(尽管目前情况不是这样,看来UDF的野心很大)
2. 为什么要用UDF?
任何一种可移动媒体(CD,DVD,Flash驱动器,外置硬盘等)都需要一种满足以下特征的文件系统:
a. 它应该能够被不同的平台理解。使得可以允许在不同的操作系统(windows,mac,unix)之间复制文件。 FAT 和 ISO9660是2种能被大多数平台理解的文件格式,然而他们有很多限制。他们的规格是公开的,ISO9660是开放标准,然而FAT属于微软的标准。
b. 它应该有丰富的功能,当文件被复制的时候不会丢失信息,能支持多种物理媒体,光盘类的媒体与硬盘有很大的区别。有些媒体只允许写入一次,(例如CD-R,DVD-R,DVD+R,BD-R)有些则需要失效管理,有些需要扩充序列化之后才可以重复写入(如大多数的RW媒体)。
c. 它的格式应该尽可能简单。这一点对于要在嵌入式设备上面实现这种格式的应用案例非常重要。(比如DVD播放器,摄像机,相机等)。像多路搜索树这样的复杂的数据结构就不适合用在这上面。
d. 它的格式升级应该符合向下兼容进行演进。新的系统应该能访问用旧格式存储的媒体。
UDF是唯一符合这些标准的文件系统,因为UDF当初设计的目的就是为了信息交换。
a. UDF 是一种开放标准。
b. UDF的设计和演进一直保持兼容性。UDF自身能支很多种现代文件系统特征:
大的分区空间(当块为512B时最大2TB,当块单位为2KB时最大支持8TB)
64bit文件长度。
不受限制的扩展属性(例如:文件名流,分支)
长文件名(最大254字节,任何字符都能在文件名里显示)
文件名支持Unicode编码
稀松文件支持(或者叫空洞文件,假定这个文件长为1M,而且内容全部为0,当用ls命令查看文件时,得到的1M,但用du命令查看文件占用的磁盘空间时,得到的是8k,也就是是全0的部分不占用物理空间)
硬链接
符号链接
元数据校验
元数据冗余(在元数据分区,UDF2.5或更新版本中可选)
失效管理(针对那些内部没有失效管理的媒体如CD-RW,DVD-RW和DVD+RW)
c. UDF定义了不同平台之间如何互动。比如,它定义了如何保存Mac的Finder信息和资源分支信息,或者NTFS的ACL,UNIX的ACL,OS/2的EA等等。它还需要平台去保护那些即使他们不理解的信息。
d. UDF是一种名副其实的通用文件系统。它能应用在各种各样的光盘,包括只读式光盘,一次性写入的光盘和可重复擦写光盘,而且理所当然的支持块设备(硬盘)。即使是一次性写入的媒体在UDF的管理下也可以表现为一个大的可重复写入磁盘。
当前2.60版本的UDF的缺点:
a. 分区大小的限制,32位的块数量使得当扇区为512字节时最大分区只有2TB。虽然对于当前的光盘来说没有问题,但有可能将来不够用。
b.没有提供一种快速的崩溃恢复机制。当媒体的容量越来越大,崩溃恢复变得越来越重要。对于某些慢速的上百G的光盘,想在加载之前做全碟扫描变得不可行。虽然用一个日志去保护媒体的数据完整性是一个方案,但并不能保证不同平台之间能顺利交互操作因为它不属于标准的一部分。
c.不支持压缩、加密文件和目录。由于设备变得越来越大,压缩显得不是特别的重要。然而加密的需求则相当紧迫特别是UDF主要应用在可移动媒体上面。
d.变得越来越复杂化。在UDF 2.50版本时为了提高效能增加了元数据分区。文件系统的元数据在元数据分区里被分为簇以便他们能被快速访问。可选性地,为了提高健壮性,元数据分区可能需要双重备份,通过这样的方式来提高效能也付出了很大的代价。这样的设计不必要地增加了文件的复杂性。为了这一点效率而把元数据分区搞得这么复杂真的值得吗?如果UDF的实现组织合理地处理元数据,它同样可以获得跟元数据分区同样或者更好的效能。不幸的是,在UDF 2.50和以后的版本,在可重新光盘和硬盘上使用元数据分区变成强制要求。而且在UDF2.60上还要求在使用虚拟复写分区的一次性写入媒体上使用元数据分区。如果某个UDF应用希望避免这么复杂的话,它需要用回老的UDF 2.00/2.01。
e.它目前没有FAT和ISO9660那么流行。但越来越多系统会使用UDF,这个问题将不是问题。
3. UDF版本的历史
UDF是一种不断进化的标准。他们各个版本的特点总结如下表格。
版本 | 日期 | 主要特征 |
1.02 | 08/1996 | 第一个版本,适合用于只读媒体上 |
1.50 | 02/1997 | 支持一次写入媒体,支持失效管理 |
2.00 | 04/1998 | 支持名字流 |
2.01 | 03/2000 | 修改一些小问题 |
2.50 | 04/2003 | 支持元数据分区获得更高性能 |
2.60 | 03/2005 | 支持虚拟可重写分区 |
总共有6个版本的发布:1.02, 1.50, 2.00, 2.01, 2.50, 和2.60. 版本2.00和2.01非常相似,2.50和2.60也很相近。因此实际上有4代的UDF。下面来详细讨论他们。
a. UDF 1.02是第一个UDF版本。它是被DVD电影使用的标准。它适合于只读和硬驱动之类的媒体。
b. UDF 1.50增加了虚拟分区和可备份分区。虚拟分区允许一次写入媒体看起来变成多次写入媒体。一个一次性写入媒体表现得像一个可复写的软盘(但比软盘的容量大了上千倍),但是它的剩余容量在使用中是不断变小的。即使你把文件删除也不能恢复已经用过的空间。可备份分区则负责处理实效管理,类似于现代的硬盘上面那些由驱动的固件做的事情。这是因为可复写的媒体只能进行有限次数的重写(大概几千次)然后就会实效。备份分区使得一张有很多失效区块的碟片逻辑上看起来是完整而且连续的。
c. UDF 2.00对文件和目录增加的命名流,以及对卷增加系统流。命名流能在其他文件系统上扩展属性,例如在Mac OS里的资源分支和ALC,以及ACL在NTFS里。同时,虚拟分区的映射表的格式也改变了。
d. UDF 2.01修正了2.00的一些小错误,没有引入新的主要特征。
e. UDF2.50引入元数据分区,这样把UDF的复杂度提升了一个档次。元数据分区包含所有元数据如目录和文件空间分配的块。元数据分区的目标是通过聚合元数据来提升文件系统的效能。元数据分区可以可选性地做成镜像,这样有2套元数据在维护。这个功能为了提升文件系统的健壮性而付出了一些性能的代价,同时使得文件系统变得更加复杂。这个版本是为了即将来临的高清DVD准备的。
f. UDF 2.60对于支持假重写模式和一次性写入的媒体增加假的重写分区。假的复写意思是驱动管理一个逻辑上的物理地址映射表,类似于虚拟分区,这样文件系统能简单地把它看作可重写分区来处理。为了减少文件系统的复杂度,UDF定义了某些驱动不必支持假重写分区。因此文件系统必须用虚拟分区来管理这样的媒体。因此在一段长时间里2种类型的驱动会同时存在,文件系统必须能被处理2种驱动.这样显得事情相当复杂和讽刺。
4. UDF标准的架构
UDF标准包含2套规范,ECMA-167和UDF。
a. ECMA-欧洲计算机生产商协会,是一个标准制定方,他们制定计算机技术的标准。ECMA-167是一个卷和文件架构标准。它也是ISO/IEC13346. ECMA-167主要针对光盘媒体(一次写入和重复写入媒体)定义了一个通用的卷和文件格式。ECMA主要做通用框架。它留下了相当多的可选空间和未定案的细节给另一个标准。ECMA-167有第二个版本和第三版本。在它的第三版本中加入了命名流。因此UDF的1.x版本基于ECMA-167/2,然而UDF版本2.x基于ECMA-167/3. ECMA-167的第三版本和第二版本几乎一样除了对命名流的支持以及一个更高的版本和其他小地方。这些不同在第三版有详细讨论,你可以查找“167/2”就可以找到。
b. UDF是OSTA定义的标准,OSTA是光学存储技术协会。UDF基于ECMA-167的框架,在其基础上填充所有必需的细节,明确化那些有歧义的地方。
因为UDF由ECMA-167和UDF组成,你需要同时把2个标准拿在手上进行阅读。为了简单一点,这个标准就像一本参考书。从参考书中学习不大好玩。就像拿着一本字典从A看到Z来学外语,而且把所有语法和所有关联的碎片一起放在字典里。同时读2个标准的情况更加糟糕:好比你需要同时从2本字典里面学习2门外语。同时读2种标准的另一个副作用就是使人很容易昏昏入睡。
学习的过程应该是交互式的。首先从ECMA-167开始得到一点点感觉,然后切换到UDF得到一些反馈,又增加了一点感觉,然后再回去。在某些时候,拿一张UDF的碟片, 使用dump工具把它的数据结构抓取出来,然后看看有什么,从而印证你心中的想法。你无需完整读完ECMA-167并且完全理解了它才去读UDF,因为里面很多细节UDF根本没有用到。
以下关于UDF的简介会解释UDF到底看上去是什么模样。我不假设你已经有其他文件系统的知识例如Unix文件系统。但如果你知道这些系统,那就会更容易理解UDF。
5. UDF规范简介
5.1 UDF格式的重点
与Unix文件系统(UFS,FFS,ext2)相比,UDF的主要架构在下面重点列出。
UDF与FFS类似的地方
a. 使用一个节点来代表一个文件或者目录。UDF的节点是一个文件入口。在UDF 2.x版本中,还有跟文件入口差不多的扩展文件入口,只是后者支持命名流。我们在下面提到文件入口的时候,意思是指所有的文件入口,包括普通文件入口和扩展文件入口。
b.一个目录是一个特殊的包含很多不同大小的目录入口的文件。每一个入口有一个不同大小的文件名和文件的入口地址(如节点)。目录的结构是线性的。需要根据文件的名字用线性查找去查找一个文件。
c. 实现了硬链接从而允许同一个文件可以有不止一个目录的入口点(例如节点)。每一个文件入口维护一个链接数,但不含有究竟是哪一个目录入口指向它这样的信息。
d.符号链接是一种特别的包含路径的文件。
e. 位图被用于管理文件系统的剩余空间,尽管只读和一次写入媒体不使用位图。
UDF和FFS有什么地方不一样:
a. 每一个文件入口(例如节点)消耗一个碟片块(在硬盘上是512字节,在大多数光盘上是2K字节)。文件入口以块地址来识别文件的入口。它不像FFS,文件系统里面的文件入口数不会有数量限制。
b.小文件(和目录)可以储存于文件入口的块空间里,类似于NTFS的嵌入式文件。
c.扩展文件入口节点块能指向另一个叫命名流目录的文件入口,它里面有可能包含没有数量限制的命名流。
d.当碟片空间分配给一个文件或目录时是通过扩展来管理的。稀松文件的支持是通过一个叫稀松的标记来实现。当某些文件有很多碎片,这些文件不能保存到文件的入口块时,能分配更多的磁盘块来存放它的扩展信息。这些碟片块作为单链表相互连接起来。
e. UDF的文件结构不是直接建立在原生的设备空间上面,而是基于分区的概念。UDF具有现存的文件系统里面最复杂的分区管理办法。尽管所有的这些不同的分区(类型1,稀松式,虚拟,元数据型和假可复写式)具有不同的物理属性,他们提供了几乎统一的接口给上层(文件和目录结构):每一个分区是连续的逻辑空间,它包含的块地址的逻辑地址是0到n-1,其中n是分区的大小。
5.2 UDF的卷结构和加载过程
卷结构对于文件和目录来说是一种透明的存在。它仅仅提供一个框架使得不同的格式能共存在同一个媒体上面。这一部分的标准是最为抽象的枯燥的文字。它里面定义了很多名词,这些很多在UDF文件系统的实现里几乎是不需要费心去理解的,因为用不到。
这个部分对于那些负责卷加载模块(识别这是一个UDF的卷,例如mount_udf命令的实现)和媒体格式化模块(允许其他系统能识别到这是一个UDF卷,如 newfs_udf命令的实现)的这写程序猿会有参考意义。
为了更好地解释卷的结构,我们会一步一步来看看这个的加载过程中UDF卷是怎样被识别的。加载命令总是在主机能够对一个UDF媒体进行使用之前发生的。通常是当一个可移动的UDF媒体插入到系统之中时会自动加载,或者是手动输入命令进行加载(如在Unix类系统里面的mount命令)。
加载的过程可以分解为2个部分:卷的识别和文件系统的识别。
卷的识别是第一步,主要是确认这个是UDF卷。它仅仅告诉我们这个是一个UDF媒体但不会告诉我们文件系统的真实数据在哪里。快速格式化工具能够通过简单地擦除卷的识别序列标记来完成。卷的识别过程会从一个基础地址里查找VRS(卷识别序列码)。对于大多数媒体类型来说,基础地址就是媒体的起始地址。对于多段刻录光盘(CD-R,DVD-R,DVD+R,BD-R 等),基础地址指向最后一个刻录段的起始地址。VRS包含以下的存放在第一个32kB后们的3个连续扇区:
a. 起始扩展区域描述符(BEA)
b. 卷顺序描述符(VSD),它的id是“NSR02”或“NSR03”
c. 结束扩展区域描述符(TEA)
当卷被识别成功之后,加载器必须找到UDF的真实数据以便确认UDF的卷是有效的而且它的版本能被系统处理。UDF的真实数据结构在标准中被称为描述符。所有描述符的开始地址都以扇区对齐。大多数描述符的大小都小于一个扇区(bitmap和稀松表是2个例外)。有些描述符包含指向其他描述符的指针(如地址)。这些描述符以特定对顺序链接起来。加载器按以下的步骤来确认一个UDF媒体是可以加载的:
定位卷描述指针(AVDP):在扇区地址256找到AVDP。在AVDP里包含主卷描述符序列(VDS)以及保留的VDS的地址和大小。加载器只需要读取主VDS的资料。
VDS在它遇到TD结束描述符之前包含很多描述符。以下是最关键的一些描述符:分区描述符(PD)和逻辑卷描述符(LVD):
分区描述符(PD):PD指出一个分区的起始地址和大小。所有文件和目录都存储在分区里。大多数UDF媒体都有PD。UDF还允许存在2个PD,其中一个描述只读的分区,另一个描述可复写分区。
逻辑卷描述符(LVD):LVD通过逻辑卷识别符来明确卷的名字,它通过分区表来定义所有物理和逻辑分区,同时通过文件集来指出根目录的地址。分区表定义的分区有一个分区代号,如在分区表里从分区0开始索引。分区里面的任意扇区能被通过分区参考号和逻辑地址寻址。UDF支持很多不同类型的分区。其中细节会在后面的5.5小节里讨论。LVD的完整序列扩展包含逻辑卷完整性描述符(LVID)的地址。LVID记录上一次媒体被写入的记录时间。LVID的存在告诉我们UDF文件系统处于一个连续状态。当一次性写入媒体中使用虚拟分区时发生异常,虚拟分配表(VAT)文件入口(FE)的写入代替了LVID的功能。有一些操作系统(例如Mac OS X)在加载文件系统时需要一个有效的根目录。因此加载器可以选择性地在加载文件系统之前验证根目录是否可用。在LVD中的分区表中有足够关于分区信息。LVD中的文件集会告诉我们跟目录的入口地址。加载器可以通过读取这个FE来确认卷是有效的。
5.3 UDF的分区结构
UDF定义了5种不同类型的分区。分区给文件系统层面提供了一个统一格式的接口,同时隐藏了底下的物理层面的属性。每一种分区有一个分区参考书值,这个是LVD的分区表里的0基准索引。分区里的小块能通过一个范围从0到N-1的块编号被寻址到,N是分区的大小。分区的大小有可能是不固定的。它有可能会增加(对于虚拟分区,元数据分区和假写分区)或者缩小(对于元数据分区)。
5.3.1 类型1分区
这种分区是最简单的分区。此种分区有一个起始地址S和大小N。一个逻辑块数值A在分区中能被转化成媒体的物理地址(按UDF的说法,称之为逻辑扇区地址)S+A。在某些光盘媒体中,分区的起始地址和大小必须按包的大小对齐(例如32KB)。这些特别的要求被定义在UDF标准的附加补充里面。分区的剩余空间通过未分配空间位图描述符来管理。它里面用一个bit来表示一个块被分配。如果这个bit被设置为1,相对应的块就是空的,如果它被清0,则对应的块就已经被分配了。这种做法跟FFS/UFS使用位图的方式相反,因为在UDF中的位图被称之为未分配的空间位图。
5.3.2 可备份分区
可备份分区用于可重写媒体,这种媒体有可能在做了多次重写(数千次)之后发生失败,如CD-RW。在文件系统中,那些常被重写打位置往往是最重要的元数据,例如位图部分。可备份分区允许失效的区域重新映像到媒体上其他好的部分从而使上层看上去失效的地方仍然是好的。
在某些地方可备份分区类似于类型1分区,它有一个起始地址和大小。另外,它定义了2到4个备份表,这些表指向媒体上保留的备份空间。每一个备份表指向同一个备份空间。如果其中一个备份表失效了,其他备份表能代替它被读取。这样的媒体上以包作为写入单元。例如,CD-RW的包大小是32个2K的扇区。如果包里面的一个扇区失效了意味着整个包失效。当这样的情况发生,这个包的内容将被写入到备份的空间中,同时它的新地址会写到备份表中。当把某个逻辑地址转换为物理地址时,总是要查看备份表的信息。如果逻辑地址没有出现在备份表中,转换出来的地址跟类型1分区的地址一样。否则,它会返回在备份表中的新地址。这样,备份表在地址转换中作为一个异常处理表。这个机制保障了当原始包失效之后逻辑地址不会变化。
我们通过一个例子来详细解释备份表和地址转换的原理。为了使事情更加直观,我们假定包的大小是10个扇区,尽管实际上包的大小应该是2的n次方。假设分区从物理地址的1000开始,然后它的长度是8000个扇区。我们有2个备份分别从500和9000开始。备份的空间是50.这样,我们每个备份空间里可以有5个包。既然每个备份表里有同样的内容,我们仅仅显示第一个备份表中的内容。在媒体还没有任何失效之前,备份表看起来像下面的样子:
原始的逻辑地址 | 映射的物理地址 |
可用 | 500 |
可用 | 510 |
可用 | 520 |
可用 | 530 |
可用 | 540 |
可用 | 9000 |
可用 | 9010 |
可用 | 9020 |
可用 | 9030 |
可用 | 9040 |
UDF使用0xFFFFFFFF来指出这个备份包是可用的。既然没有失效,地址转换的结果就跟类型1分区一样。因此逻辑地址67会被转换成物理地址1067.假设经过一段时间的使用,当要写入时系统发现在包含93块的包发生了错误。它就会把这个包写入到物理地址为500的备份包中,然后更新备份表:
原始的逻辑地址 | 映射的物理地址 |
90 | 500 |
可用 | 510 |
可用 | 520 |
可用 | 530 |
可用 | 540 |
可用 | 9000 |
可用 | 9010 |
可用 | 9020 |
可用 | 9030 |
可用 | 9040 |
表格
现在逻辑地址转换跟之前一样除了当逻辑地址为90-99之间。例如,逻辑地址67仍然指向物理地址1067,但逻辑地址97现在会指向物理地址507.
如例子中指出,备份是以包为单位进行的。备份表记录的是这个包里面第一个块的地址。
在这个例子中,备份空间在分区的外面。实际上,它也可以在分区的里面,此时分区必须把备用空间标识为已占用。
对于可备份分区,它必须从一个包的边界开始,它的大小必须是一个包的长度的整数倍。
5.3.3 虚拟分区
虚拟分区应用在一次性写入媒体中。只有3种类型的元数据被存放在虚拟分区中:文件集描述符,文件入口(包括扩展文件入口),和分配扩展描述符。如果文件数据被嵌入在文件入口,这些文件数据也存在虚拟分区中。虚拟分区使一次性写入媒体看起来像多次可写媒体。虚拟分区层处于类型1分区的上面。虚拟分配表(VAT)被用于映射虚拟分区的逻辑地址到底下的类型1分区的逻辑地址。
我们用一个简单的例子爱解释它的原理。假设类型1分区起始地址是物理块地址100.文件集描述符的虚拟地址是0,那么它实际上在物理块100(例如,逻辑地址0),然后根目录的文件入口的虚拟地址是1,它实际上位于物理地址的101(如,逻辑地址1)。VAT是一个整数的数组。想获取虚拟地址x的逻辑地址是VAT[x]。当前VAT有2个入口:
0 |
1 |
上面的表格看出暂时地虚拟地址与物理地址相同。假设上一次在媒体的写入地址是101.如果有一个空文件foo被加到根目录,则根目录的FE被更新同时写入到物理地址102(即,逻辑地址2),然后文件foo的FE写入到物理地址103.这样VAT变成:
0 |
2 |
3 |
根目录的FE仍然有虚拟地址1,但现在逻辑地址是2.文件foo的FE的虚拟地址是2,同时它被映射到逻辑地址3,也就是,物理地址103. 当根目录被再次更新时,VAT会再次改变。
VAT被存放在一个特别的类型1分区的文件里。没有其他UDF数据结构指向VAT的FE(也叫UDF的VAT ICB),同时最后一个VAT的FE总是指向最后一个写入媒体的扇区。当弹出一个有虚拟分区的媒体时,VAT和VAT的FE会在刷入所有暂存数据之后被写入媒体。UDF读取器首先查找最后一个被写入的扇区,然后它才能获得可以进行地址转换的VAT。
5.3.4 元数据分区
元数据分区被用于聚合媒体的元数据从而提升效率。元数据包括文件入口,分配描述符,目录,但不包括命名流或者扩展属性。元数据分区处于下面分区的上层,他们可能是类型1分区,可备份分区或者假装可擦写分区。元数据分区包含3种文件:元数据文件,元数据镜像文件和元数据位图文件。元数据文件和元数据镜像文件有重复的元数据--文件入口喝分配扩展描述符。他们能可选性地拥有重复的数据。例如,每一个元数据在同一个媒体上有2个副本。为了简化以下的讨论,我们假设元数据镜像文件不会重复它的元数据文件内容。
所有元数据分区里的数据都被存在元数据文件里。元数据分区的逻辑块号码是文件相对于元数据文件的偏移。由于元数据文件里的某些空间可能没有被用到,元位图文件一般会跟踪元数据文件里的剩余空间。元数据文件里面的元数据,元数据镜像文件和元数据位图文件都被存放在基于底层类型1分区里。(或者可备份分区和假写分区)。这些是唯一不存放在元数据分区里的元数据。元数据文件和元数据镜像文件里的数据必须跟媒体的ECC块长度或者包长度对齐,具体看哪个更大,它的长度必须是媒体ECC块的长度或包长度的整数倍,也是看具体以最大那个为准。
我们通过一个例子来解释元数据分区的工作原理。我们假定ECC块的长度以及包长度是10,虽然UDF要求它要大于32,而且实际上它的长度要求是2的幂。假设底层的分区是类型1分区,起始地址是1000,长度有8000个扇区。元数据文件的内容(元数据分区)有2个扩展:第一个从逻辑地址100开始长度是300扇区,第二个从2000开始长度500扇区。因此,元数据分区的总长度是800扇区。在元数据分区里的逻辑地址5意味着元数据文件里偏移了5个块,也就是转换成类型1分区中的逻辑地址105,或者物理媒体地址的1105. 我们在以下的表格里给出更多的地址转换的例子。
元数据分区逻辑地址 | 类型1分区逻辑地址 | 物理地址 |
0 | 100 | 1100 |
134 | 234 | 1234 |
300 | 2000 | 3000 |
700 | 2400 | 3400 |
750 | 2450 | 2350 |
表格
元数据位图文件的内容是一个未分区空间位图描述表。类似于类型1或可备份分区中的位图,它每一个对应于分区中的一个块。
5.3.5 假写分区
假写分区(POW)用于下一代一次性写入媒体(蓝光刻录碟片或BD-R)在下一代的智能驱动器上。这些驱动器管理地址在驱动内部实现转换(像之前虚拟分区所作的那样)使得一次性物理媒体的分区看起来像连续可重复擦写的分区。当使用POW分区时,元数据分区应当也用于元数据,目的是为了元数据聚合以及获得更好的效率。然而,在一次性写入媒体中,即使当数据逻辑上已经聚会在一个分区,他们也可能在物理媒体上离开得很远。由于物理上距离越远意味着效率越低,使用元数据分区能否提升效率还是一个问题。
在一个支持POW的媒体中,媒体能被分开成几个轨道。每一个轨道有一个下一个可写入地址(NWA)。一个新的块能被写入到任何轨道的NWA。一个存在的块可以被重写。任何轨道的NWA能在任何时候改变。因此必须在写入任何新块之前先查询NWA。
5.3.6分区描述符和分区地图
在媒体中有2种方法来对一个块进行寻址,物理地址(逻辑扇区号或者叫LSN)和逻辑地址(逻辑块号或者LBN)。物理地址用于给分区外面的元数据进行寻址(例如逻辑卷描述符)。逻辑地址用于给任意分区内的元数据进行寻址。由于一个UDF卷有可能存在多个分区,需要一个分区参考数值(PartRef)以便用于跟LBN相加来给一个块寻址。我们先介绍分区是如何描述的然后再解释PartRef的计算方式。
UDF卷上的分区由一到多个分区描述符(PD)来描述,同时一个分区有一个或多个入口。分区地图存放在逻辑卷描述符里。PD描述一个分区的物理属性。一个PD中关系最大的信息是他的分区号,分区起始地址和长度。它也让我们知道分区是否为只读,一次写入,重复写入还是可直接覆盖写入。下面的表格演示了2个PD的基本信息。为了尽量减少疑惑,分区号特意地选择使得他们不会跟PartRef重叠,尽管实际中的真实UDF卷,分区号经常从0开始。
PD1 | 分区号 | 7 |
分区起始LSN | 600 | |
分区长度 | 400 | |
读写类型 | 只读 | |
PD2 | 分区号 | 4 |
分区起始LSN | 1000 | |
分区长度 | 8000 | |
读写类型 | 可读写 |
一个分区地图有一个描述分区逻辑属性的入口的编号。每一个分区地图有一个分区号用来指出这个分区地图指向那个PD。有2种类型的分区地图,类型1或类型2. 类型1分区是简单地一个在PD里有信息描述的分区有对应的分区号。类型2分区可以是一个可分开的分区,虚拟分区,元数据分区或假写分区。下面的表格给出一个可能的分区地图给上面2种PD定义。以0作为基准索引的每个地图入口被称之为分区参考号。UDF文件系统可以以任何顺序写入分区地图的入口,它也会相应地改变PartRef的值。
PartRef | 分区参数 | |
0 | 分区号 | 4 |
分区地图类型 | 2 | |
分区类型 | 可备份分区 | |
备份表地址 | 500和9000 | |
1 | 分区号 | 7 |
分区地图类型 | 1 | |
2 | 分区号 | 4 |
分区地图类型 | 2 | |
分区类型 | 元数据分区 | |
元数据文件入口地址 | 0 | |
元数据镜像文件FE地址 | 7000 | |
元数据位图文件FE地址 | 1 |
这个分区地图中看出来有3个分区。第一个分区(PartRef为0)是一个可备份分区后面是被第二个PD描述的可复写分区。第二个分区(PartRef = 1)是一个类型1只读分区后面是被第一个PD描述的只读分区。第三个分区是一个元数据分区处于PartRef为0的可备份分区,因为2个分区地图的入口有相同的分区编号4. 这种多分区的场景里,每个逻辑块都通过PartRef和逻辑块编码被识别。例如,在元数据分区里的第10个块被识别为(PartRef=2,LBN=9),在只读分区里的第一个块被识别为(PartRef=1,LBN=0)。
5.4 UDF文件和目录结构
5.4.1文件入口和扩展文件入口
不管底层的分区结构是如何定义的,UDF卷里的文件和目录结构都是一样的。主要负责描述文件和目录结构的元数据叫做信息控制块。他们的大小最大为1个块,而且他们的数据结构要么是文件入口(FE)要么就是扩展文件入口(EFE)。除了FE/EFE,分配扩展描述符(AED)也用于代表那些非常碎片化的文件。EFE在UDF2.0被引入来表示有命名流的文件。EFE非常类似于FE,除了一点点额外的地方。
文件这个词在FE/EFE比通常的文件系统里的文件有更宽的含义。它用于表示有某些属性的字节流。在字节流中的文件偏移从0开始直到文件结束。一个FE/EFE可能代表一个文件,一个目录,一个具有扩展属性的逻辑空间,一个流目录,一个命名流,一个符号链接,一个特殊的设备节点,或者甚至是整个元数据分区和元数据位图。我们仍然使用文件这个词来表示字节的流。
5.4.2扩展基础空间分配
FE/EFE使用扩展基础空间分配来标示哪个块属于这个文件。有4种类型的扩展格式,它通过FE/EFE的ICB中的最低的2个位来标示。在UDF中只用到了他们之中的3个。扩展分配描述符没有在UDF中用到。这3种格式分别是:
a.短分配描述符。文件数据和分配描述符在同一个分区。每一个分配描述符记录起始逻辑块编号和扩展的长度。
b. 长分配描述符。文件数据有可能和分配描述符不在同一个分区里。对于记录在短分配描述符里的信息,分区参考号也被记录来指出扩展时用到的分区。
c. 单独分配描述符。文件数据嵌入在FE/EFE块里面。
每一种扩展可能有3种不同的类型,通过扩展长度的最高2位来表示。通常的类型是已记录和已分配。当表示稀松文件的空洞时用未记录未分配类型来表示。未记录但已分配用于表示预先分配但没有被初始化的空间。每一个扩展的大小必须是块大小的整数倍除了文件的最后一个扩展。
5.4.3 目录结构
目录跟文件很像只是在ICB的文件类型里目录的标志位被设置为1.目录的入口是变长度的入口线性地存放在文件中。每一个入口通过一个文件识别描述符(FID)来描述。第一个FID必须保护一个空的名字以及它的文件属性必须把父入口标志位设置为1。这一点等同于FFS/UFS目录的“..”入口。但与FFS不同的是,UDF没有“.”入口来代表它自身。FID包含文件名(在UDF中称之为文件识别符),文件的FE/EFE的地址,和可选的实际使用的可变空间大小。当一个文件被从目录中删除时,文件的FID的特征项被标记为已删除。如果允许的话,被删除后留下的空间可以被新的入口随意使用。
5.4.4剩余空间管理(空间位图)
UDF使用空间位图来管理剩余空间,类似于很多文件系统。它的位图通过空间位图描述符(SBD)来描述,一个或多个的描述符有可能大于一个块。SBD有一个UDF标签,2个长度项指出位图中位的数量和字节的数量,这些数量是根据剩余空间的位图。位图必须连续地存放在卷里。由于这个问题被称为剩余空间位图,因此位图中标记为1的位意思是这个块是可分配使用的,标记为0的则表示这个空间以及被用掉了。这一点与通常的文件系统不同。元数据位图文件的内容也是一个SBD。它在类型1或可备份分区中的分配可以是碎片化的。
5.4.5 扩展属性
扩展属性用于存储额外的文件属性,例如在Mac平台上的Finder信息和资源分支,和NTFS的ACL。EA可以被存放于2种不同的地方:嵌入在EA空间里和外部的EA空间。
嵌入的EA空间是指文件入口块中剩余的空间。它能快速访问但只有很小短EA能被存放。
外部EA空间是指专用的文件入口(EA文件入口)通过主要文件入口来指定。EA被存放在EA文件入口描述的逻辑空间里。每一个EA有一个头和可变长度的主体。在外部EA空间,所有EA被串联在一起。每一个外部EA空间的EA头必须从块的边界开始。
有3种类型的EA:标准EA,实现使用EA和应用使用EA。标准EA的例子是文件时间EA(备份时间,创建时间等),针对设备节点的设备规格EA。实现使用EA的例子是Mac的Finder信息和资源分支。应用使用EA由应用程序定义和使用。每一种EA的类型都有一个特殊的EA称之为未分配空间EA,用于占据其他EA没有用完的空间或者填充目的。
在嵌入式或外部EA空间里,EA总是按他们的类型成组排列。标准EA先被存储,后面如果有的话跟着实现使用EA,然后跟着应用使用EA。
因为所有EA都被一起存放在一个逻辑空间里,如果中间的一个外部EA的空间增大了,所有它后面的EA必须被移位。这样使得对可写媒体的支持很困难。幸运的是,UDF2.x版本之后后中引入了命名流解决了EA的问题。大多数使用EA的定义在UDF2.x之后改为了使用命名流。
5.4.6 命名流
命名流中UDF 2.x中被引入。它的概念跟MAc中的分支和NTFS中的流相似。每一个文件或者目录把他们的数据存放在主流里。一定数量的命名流被存放在一个文件或目录里。每一个流都有一个名字。如果一个文件或目录包含有命名流,那么它必须使用EFE。EFE包含流目录的文件入口的地址。流目录的内容与普通目录一样。它从一个没有名字的父入口开始,后面跟随不同大小的目录入口。流目录里每一个目录入口指向一个命名流文件入口,这个入口描述存放了命名流的逻辑空间。
5.5 UDF的一些专有名词
UDF比大多数常见的硬盘文件系统多得多的专有名词。其中一个原因是ECMA-167企图定义一个很多可能的文件系统的框架而不是一种特定的文件系统。另一个原因是UDF不仅仅是定义了文件系统的架构,还定义了卷和分区的架构。有些UDF(或者说ECMA-167)的专有名词对于一般的文件系统实现人员来说非常抽象。幸运的是,其中许多不在 UDF 中有意义。有些可能会造成误解的专有名词将在下面简单讨论。
启动块:在UDF中可以忽略。
物理扇区:UDF中可以处理为逻辑扇区。逻辑扇区:在媒体中的扇区,使用物理地址进行寻址。
逻辑块:分区里的一个扇区,使用这个分区的逻辑块编号进行寻址(从0到n-1,n是分区的大小)。逻辑块的大小等于逻辑扇区的大小。对于大多数光盘通常是2KB。有些UDF处理程序写死成2KB从而不支持其他的扇区大小。如果用于硬盘UDF不定义扇区大小。然而,既然物理扇区的大小是用于UDF,大多数现存的硬盘可能需要用512B作为扇区大小。
标记符:意思是名称。例如,逻辑卷标记符是卷的名称,文件标记符是文件的名称。
卷识别空间:对于大多数媒体,VRS从媒体到开始地方开始(逻辑扇区0);对于多段刻录光盘,VRS从最后一次刻录的开始点开始。
卷空间:媒体上所有可用的空间。
卷集:可被处理为逻辑卷,因为UDF中一个卷集只能包含一个逻辑卷。
逻辑卷:可用理解为媒体上的所有UDF数据结构。它包含一些分区外的元数据结构,和分区里的数据。
分区:分区就是用来放文件系统数据的地方(文件,目录等)。只有元数据可以不在分区里。一个逻辑卷可以有一个或多个分区。多分区图是一个特例在其他文件系统中是没有的。对于现在,你可以认为分区是一个连续的逻辑空间,这个空间上面逻辑块从0到n-1被编号,n是分区的大小。关于分区的更多细节讨论在UDF分区结构的部分。
文件集:文件集意思是从根目录开始的一个目录树。在UDF中,每一个逻辑卷都有唯一的一个文件集。唯一的例外是在一次刻录媒体里,有多个文件集用于记录多个归档映像。查看UDF 2.3.2可以获得更多细节。
描述符:描述符描述UDF的元数据。描述符通常不会超出一个扇区的大小,但有一些例外(例如位图和牺牲表描述符)。所有描述符的开始都有一个16字节的头称为描述符标签。
描述符标签:一个16字节的头。主要保护一个标签号告诉描述符的类型,描述符的校验码以及标签本身的校验码。
ICB(信息控制块):描述文件的一些描述符类型。这些描述符总有一个20字节的ICB标签跟着描述符标签。这里文件的意思是任何管理一个逻辑上的字节流。它可以是一个常规的用户文件,一个目录,一个命名流,一个扩展属性等等。一个有ICB标签的描述符类似于一个FFS/UFS/ext3的节点。ECMA-167定义了多种复杂的ICB体系架构策略。这些对UDF来说是没有用的。实际上UDF仅仅用了最简单的一种:策略4. 在策略4里,仅仅有一个ICB描述符描述文件,而且根本没有使用ICB体系架构。
字符集和编码:ECMA-167定义了9种字符集,CS0-CS9,UDF只使用CS0,也就是unicode。实际中,UDF可以忽略掉其他的字符集。unicode可以用16位字符或者8位字符(称为压缩形式)。8位字符只能在当所有高位都为0时使用。字符串的第一个字节告诉我们使用8位还是16位字符。16位字符采用大字节序。
记录结构:在UDF中可以被忽略,由于UDF中所有文件都被看作字节流而且没有定义任何记录结构。
字节序:UDF的所有碟片上的结构都适用小字节序,即使用x86处理器的字节序。只有一个例外:对于字符串(卷名,文件和目录名等),如果使用16位unicode的话,他们将会使用大字节序。
5.6一些提示和注意,UDF标准里面没有的
5.6.1 字符集:复合或分解
UDF使用unicode标准来存放文件名。这种标准定义了2种方法(我们在这里把他简化了,因为实际上不止2种方法)来存放相同的字符:复合形式(NFC)和分解形式(NFD)。Mac使用分解形式,windows使用复合形式。最近在UDF委员会通过的一个文档修改通知要求在UDF媒体上使用复合形式。
5.6.2 对于UDF读者的假设
Philips提供一个开源的UDF验证程序来验证一个媒体是否完全符合UDF标准。这个验证器即可以运行于Mac也可以在windows上。想获取UDF验证器程序,请按照这些步骤:登入网站 http://www.ip.philips.com/ 1.选择合作伙伴。
2.在合作伙伴那里找到UDF 验证器。
3.如果你有伙伴验证区的注册账号则登陆进入伙伴区。如果你没有则按下面步骤创建一个:点击登入然后按照新用户的指示操作,账号会以邮件的方式激活。
4.糟糕的是,并不是所有生产商会先用这个软件工具验证完才发布他们的产品。由于市场上存在太多坏的UDF媒体,因此负责实现UDF读取器的那些工程师需要想尽办法去解读这些坏的媒体。因此非常重要的一点是UDF读取器需要尽可能大量地测试UDF的媒体(大部分是DVD电影和游戏)。
翻译者的话:
有一些地方不知道用什么词最好:
比如说named stream,我翻译成命名流,是不是有更好的翻译呢,感觉这个东西就是UDF制造的名称,具体就是一个名字
block跟sector是一样的吗?总之我的认知里,他们没有分别,一个block是2KB,一个sector也是2KB。之所以叫sector估计是由于磁盘是圆形的,它的一小块是一个扇形。一个blcok通常是一个方形。
meta跟raw有什么不同?中文看到有人写元数据,这个元是什么概念?就是真实的意思吗?raw有的说是原生,未处理过的。结合上下文,我想metadata就是那些非logical的东西。