我们来深入分析 libburn、libisofs 和 libisoburn 这三个核心库的实现逻辑、组成部分及其相互关系。
这三个库共同构成了 xorriso 项目的底层引擎,统称为 libburnia 项目。
总体关系概览
首先,用一个简单的比喻来理解它们的关系:
-
libisofs就像建筑师和施工队。它负责设计大楼的结构(文件系统布局),并准备好所有建筑材料(文件数据)。 -
libburn就像地基承包商和吊车。它负责在土地上打好地基(初始化光盘),并把建筑材料精确地放置到指定位置(将数据刻录到光盘轨道)。 -
libisoburn就像总项目经理。它从建筑师那里拿到设计和材料,协调吊车进行作业,确保整个建造过程(从文件到光盘)无缝衔接。它让"造一栋楼的模型(生成ISO文件)"和"直接造一栋真实的楼(直接刻录光盘)"可以使用同一套图纸。
现在,我们分别深入每个库。
1. libburn
核心职责 : 提供对光学介质(CD, DVD, BD)的低级、直接的读写和控制。
实现逻辑与组成部分
-
设备扫描与识别
-
实现逻辑 : 扫描系统(如
/dev/sr0,/dev/sg1),识别出光盘驱动器,并查询其能力和状态(如支持的刻录速度、当前介质类型)。 -
组成部分: 设备枚举模块、SCSI/ATAPI/MMC命令集封装。
-
-
介质处理
-
实现逻辑: 与驱动器交互,完成对空白光盘的格式化(如BD-R的初始化)、获取介质信息(容量、剩余空间)。
-
组成部分: 介质状态查询模块、格式化命令模块。
-
-
刻录引擎
-
实现逻辑 : 这是最核心的部分。它实现了一种 "刻录源" 的概念。刻录源是一个提供连续数据流的对象。
libburn从刻录源读取数据,通过一系列 SCSI/MMC 命令(如WRITE(10))将数据精确地写入光盘的轨道。 -
组成部分:
-
写入模式控制: 支持 Track-At-Once (TAO), Session-At-Once (SAO), Disc-At-Once (DAO) 等刻录模式。
-
数据流管理: 确保数据以恒定的速率供给驱动器,防止缓冲区欠载。
-
纠错编码: 为 CD 模式生成 CIRC 纠错码,为 DVD/BD 模式生成 ECC 块。
-
-
-
会话与轨道管理
-
实现逻辑: 在光盘上创建新的会话(Session)和轨道(Track)。这对于多段刻录至关重要。
-
组成部分: 会话/轨道创建逻辑、TOC(内容表)读取。
-
关键抽象
-
struct burn_drive: 代表一个物理或虚拟的光盘驱动器。 -
struct burn_source: 一个提供数据流的抽象对象。这是libburn与上层数据生产者(如libisoburn)的连接点。
2. libisofs
核心职责 : 在内存中构建一个符合 ISO 9660 及其扩展标准的结构,并能够将此结构序列化为一个线性的、符合规范的数据流。
实现逻辑与组成部分
-
文件系统节点树
-
实现逻辑: 在内存中创建一个逻辑目录树,镜像要生成的ISO映像的目录结构。每个节点(文件或目录)都包含其元数据(名称、时间戳、大小)。
-
组成部分:
-
IsoNode: 基类。 -
IsoFile: 代表一个文件,包含指向其数据源(磁盘文件)的链接。 -
IsoDir: 代表一个目录,包含子节点列表。 -
IsoSymlink: 代表符号链接。
-
-
-
Rock Ridge / Joliet / UDF 支持
-
实现逻辑: 这些是"并行"的文件系统描述,它们共享同一个文件数据,但为目录树提供了不同的元数据视图。
-
Rock Ridge: 使用 ISO 9660 目录记录中的"系统使用"字段来存储类 Unix 的完整元数据(权限、UID、GID、符号链接目标)。
-
Joliet: 在卷中创建一个完全独立的目录树,使用 UCS-2 编码,支持长文件名和 Unicode。
-
-
组成部分: 每个扩展都有对应的生成器,在构建映像时,它们会遍历主节点树,生成自己标准的目录记录和路径表。
-
-
El Torito 引导记录
-
实现逻辑 : 将磁盘映像文件(如
boot.img)标记为可引导映像,并在ISO文件系统的根目录创建一个特殊的引导目录,其中包含引导目录。 -
组成部分: El Torito 规范实现模块。
-
-
空间分配与布局
-
实现逻辑: 遍历整个节点树,计算每个文件和每个目录记录、路径表的位置和大小。它为每个数据块分配逻辑块地址(LBA)。这个过程类似于为文件系统"排版"。
-
组成部分: 布局引擎、块分配器。
-
-
映像生成器
-
实现逻辑 : 这是
libisofs的最终输出阶段。它根据之前计算好的布局,按顺序"渲染"整个ISO映像:-
写入系统区(引导记录等)。
-
写入主卷描述符、 Joliet 卷描述符等。
-
写入路径表。
-
写入目录记录。
-
写入文件数据区。
-
-
组成部分: 一个能够按LBA顺序生成数据块的模块。
-
关键抽象
-
IsoImage: 代表整个ISO映像项目。 -
IsoDataSource: 一个抽象,用于读取文件内容(可以来自磁盘文件、内存缓冲区等)。
3. libisoburn
核心职责 : 桥接 libisofs 和 libburn ,弥合"文件系统对象"和"物理刻录流"之间的概念差距。它实现了 "刻录到文件"和"直接刻录到光盘"的统一抽象。
实现逻辑与组成部分
-
协调
libisofs的生成过程- 实现逻辑 :
libisoburn启动libisofs的布局过程,获取到整个映像的"蓝图"------即每个部分(卷描述符、路径表、目录、文件数据)在逻辑映像中的位置和大小。
- 实现逻辑 :
-
实现
struct burn_source接口-
实现逻辑 : 这是其最核心的魔法。
libisoburn创建一个自定义的burn_source对象。当libburn需要数据来刻录时,它会从这个burn_source读取。 -
内部工作 : 当
libburn请求第N到第N+M个逻辑扇区的数据时,libisoburn的burn_source会:-
根据请求的LBA范围,判断这部分数据对应
libisofs映像的哪个部分(是卷描述符?是某个目录记录?还是某个文件的一段内容?)。 -
即时调用
libisofs的相应生成器 ,在内存中动态生成这块数据,然后返回给libburn。
-
-
组成部分 : 一个复杂的
read回调函数实现,它内部集成了libisofs的生成逻辑。
-
-
多路复用与地址转换
- 实现逻辑 : ISO 9660 映像是一个单一的、连续的数据流。但在多扩展情况下(如 Joliet),同一个文件的数据在映像中只存储一次,但被多个目录树引用。
libisoburn需要管理这种映射,确保当libburn请求 Joliet 目录记录的数据时,它能正确生成并返回。
- 实现逻辑 : ISO 9660 映像是一个单一的、连续的数据流。但在多扩展情况下(如 Joliet),同一个文件的数据在映像中只存储一次,但被多个目录树引用。
-
目标抽象
-
实现逻辑 :
libisoburn向上层(如libxorriso)提供一个统一的 API。无论是创建一个.iso文件还是刻录到光盘,上层代码的流程几乎是相同的。-
输出到文件 :
libisoburn会将其burn_source连接到一个小型的"文件写入适配器",这个适配器简单地读取整个burn_source的数据流并写入磁盘文件。 -
输出到光盘 :
libisoburn将其burn_source直接传递给libburn进行刻录。
-
-
组成部分: 目标管理模块。
-
相互关系与数据流
下图清晰地展示了三个库在直接刻录到光盘时的协作关系:

总结:
-
libisofs知道 "写什么" (What)和 "结构是什么" (Structure)。 -
libburn知道 "往哪里写" (Where)和 "如何物理地写" (How-Physical)。 -
libisoburn知道 "如何把'什么'转换成'物理写操作'" (How-Logical)。它通过实现一个 "按需生成"的burn_source,使得libisofs的复杂、非线性的文件系统构建过程,能够适配libburn简单的、线性的、流式的刻录接口。
这种解耦和桥接的设计是 libburnia 栈强大和灵活性的根本原因。