# 20.5.创建和使用 CD

光盘（CD）介质提供了一些功能，使其与传统磁盘有所不同。它们的设计使得可以连续读取，而无需像传统硬盘那样在轨道之间移动磁头。虽然 CD 媒体也有轨道，但这些轨道指的是一段连续读取的数据，而不是磁盘的物理属性。ISO 9660 文件系统就是为了处理这些差异而设计的。

FreeBSD 的 Ports 提供了多个工具，用于刻录和复制音频和数据 CD。本章展示了多个命令行工具的使用方法。如果需要带有图形界面的光盘刻录软件，可以考虑安装 [sysutils/xcdroast](https://cgit.freebsd.org/ports/tree/sysutils/xcdroast/) 或 [sysutils/k3b](https://cgit.freebsd.org/ports/tree/sysutils/k3b/) 软件包和 Ports 。

## 20.5.1. 支持的设备

**GENERIC** 内核提供了对 SCSI、USB 和 ATAPICD 读取器及刻录机的支持。如果使用自定义内核，内核配置文件中需要根据设备类型添加相应的选项。

对于 SCSI 刻录机，确保在配置文件中有以下选项：

```sh
device scbus	# SCSI 总线（ATA/SCSI 必须）
device da	# 直接访问（磁盘）
device pass	# 直通设备（直接 ATA/SCSI 访问）
device cd	# 需要 CD 和 DVD 刻录机
```

对于 USB 刻录机，确保在配置文件中有以下选项：

```sh
device scbus	# SCSI 总线（ATA/SCSI 必须）
device da	# 直接访问（磁盘）
device pass	# 直通设备（直接 ATA/SCSI 访问）
device cd	# 需要 CD 和 DVD 刻录机
device uhci	# 提供 USB 1.x 支持
device ohci	# 提供 USB 1.x 支持
device ehci	# 提供 USB 2.0 支持
device xhci	# 提供 USB 3.0 支持
device usb	# USB 总线（必须）
device umass	# 磁盘/大容量存储 - 需要 scbus 和 da
```

对于 ATAPI 刻录机，确保在配置文件中有以下选项：

```sh
device ata	# 传统 ATA/SATA 控制器
device scbus# SCSI 总线（ATA/SCSI 必须）
device pass	# 直通设备（直接 ATA/SCSI 访问）
device cd	# 需要 CD 和 DVD 刻录机
```

> **注意**
>
> 在 FreeBSD 10.x 之前的版本中，如果刻录机是 ATAPI 设备，还需要在内核配置文件中添加这一行：`device atapicam`。或者，可以通过将以下行添加到 **/boot/loader.conf** 来在启动时加载此驱动程序：`atapicam_load="YES"`。这需要重启系统，因为该驱动程序只能在启动时加载。

要验证 FreeBSD 是否识别了设备，可以运行 `dmesg` 并查找设备的条目。在 10.x 之前的系统中，输出的第一行设备名称将是 **acd0** 而不是 **cd0**。

```sh
% dmesg | grep cd
cd0 at ahcich1 bus 0 scbus1 target 0 lun 0
cd0: <HL-DT-ST DVDRAM GU70N LT20> Removable CD-ROM SCSI-0 device
cd0: Serial Number M3OD3S34152
cd0: 150.000MB/s transfers (SATA 1.x, UDMA6, ATAPI 12bytes, PIO 8192bytes)
cd0: Attempt to query device size failed: NOT READY, Medium not present - tray closed
```

## 20.5.2. 刻录光盘

在 FreeBSD 中，可以使用 `cdrecord` 来刻录光盘。这个命令是通过安装 [sysutils/cdrtools](https://cgit.freebsd.org/ports/tree/sysutils/cdrtools/) 软件包和 Ports 来获得的。

尽管 `cdrecord` 有很多选项，但基本用法非常简单。指定要刻录的 ISO 文件的名称，并且如果系统有多个刻录设备，还需要指定要使用的设备名称：

```sh
# cdrecord dev=device imagefile.iso
```

要确定刻录机的设备名称，可以使用 `-scanbus`，这会返回类似下面的结果：

```sh
# cdrecord -scanbus
ProDVD-ProBD-Clone 3.00 (amd64-unknown-freebsd10.0) Copyright (C) 1995-2010 Jörg Schilling
Using libscg version 'schily-0.9'
scsibus0:
        0,0,0     0) 'SEAGATE ' 'ST39236LW       ' '0004' Disk
        0,1,0     1) 'SEAGATE ' 'ST39173W        ' '5958' Disk
        0,2,0     2) *
        0,3,0     3) 'iomega  ' 'jaz 1GB         ' 'J.86' Removable Disk
        0,4,0     4) 'NEC     ' 'CD-ROM DRIVE:466' '1.26' Removable CD-ROM
        0,5,0     5) *
        0,6,0     6) *
        0,7,0     7) *
scsibus1:
        1,0,0   100) *
        1,1,0   101) *
        1,2,0   102) *
        1,3,0   103) *
        1,4,0   104) *
        1,5,0   105) 'YAMAHA  ' 'CRW4260         ' '1.0q' Removable CD-ROM
        1,6,0   106) 'ARTEC   ' 'AM12S           ' '1.06' Scanner
        1,7,0   107) *
```

找到 CD 刻录机的条目，并将三个由逗号分隔的数字作为 `dev` 的值。在此示例中，Yamaha 刻录机设备为 `1,5,0`，因此指定该设备时应该使用 `dev=1,5,0`。请参阅 `cdrecord` 的手册页，了解指定该值的其他方法，以及关于写入音频轨道和控制写入速度的更多信息。

另外，可以运行以下命令来获取刻录机的设备地址：

```sh
# camcontrol devlist
<MATSHITA CDRW/DVD UJDA740 1.00>   at scbus1 target 0 lun 0 (cd0,pass0)
```

使用 `scbus`、`target` 和 `lun` 的数字值。在此示例中，应使用 `1,0,0` 作为设备名称。

## 20.5.3. 写入数据到 ISO 文件系统

为了制作数据光盘，必须在刻录到光盘之前准备好将成为光盘轨道的数据文件。在 FreeBSD 中，安装了 [sysutils/cdrtools](https://cgit.freebsd.org/ports/tree/sysutils/cdrtools/) 包后，可以使用 `mkisofs` 来生成一个 ISO 9660 文件系统，该文件系统是 UNIX® 文件系统中目录树的镜像。最简单的用法是指定要创建的 ISO 文件的名称以及要放入 ISO 9660 文件系统中的文件路径：

```sh
# mkisofs -o imagefile.iso /path/to/tree
```

该命令将指定路径中的文件名映射到符合标准 ISO 9660 文件系统限制的名称，并排除不符合 ISO 文件系统标准的文件。

有许多选项可以克服该标准所施加的限制。特别是，`-R` 启用 UNIX® 系统常用的 Rock Ridge 扩展，`-J` 启用 Microsoft® 系统使用的 Joliet 扩展。

对于仅在 FreeBSD 系统上使用的光盘，可以使用 `-U` 来禁用所有文件名限制。当与 `-R` 一起使用时，它会生成一个与指定的 FreeBSD 目录树完全相同的文件系统镜像，即使它违反了 ISO 9660 标准。

另一个常用选项是 `-b`。此选项用于指定启动镜像的位置，用于制作 "El Torito" 启动光盘。该选项需要一个参数，即位于要写入光盘的树结构顶部的启动镜像路径。默认情况下，`mkisofs` 在“软盘仿真”模式下创建 ISO 镜像，因此期望启动镜像的大小恰好为 1200、1440 或 2880 KB。某些引导加载程序，如 FreeBSD 分发媒体所使用的引导加载程序，不使用仿真模式。在这种情况下，应使用 `-no-emul-boot`。因此，如果 **/tmp/myboot** 包含一个可引导的 FreeBSD 系统，并且引导镜像位于 **/tmp/myboot/boot/cdboot**，则此命令将生成 **/tmp/bootable.iso**：

```sh
# mkisofs -R -no-emul-boot -b boot/cdboot -o /tmp/bootable.iso /tmp/myboot
```

生成的 ISO 镜像可以通过以下方式作为内存磁盘挂载：

```sh
# mdconfig -a -t vnode -f /tmp/bootable.iso -u 0
# mount -t cd9660 /dev/md0 /mnt
```

然后可以验证 **/mnt** 和 **/tmp/myboot** 是否相同。

`mkisofs` 还有许多其他选项，可以进一步调整其行为。请参阅 [mkisofs(8)](https://man.freebsd.org/cgi/man.cgi?query=mkisofs\&sektion=8\&format=html) 获取详细信息。

> **注意**
>
> 可以将数据光盘复制为一个功能上等效于通过 `mkisofs` 创建的镜像文件。为此，可以使用 **dd**，将设备名称作为输入文件，将要创建的 ISO 文件名作为输出文件：
>
> ```sh
> # dd if=/dev/cd0 of=file.iso bs=2048
> ```
>
> 生成的镜像文件可以像在 [刻录光盘](https://docs.freebsd.org/en/books/handbook/disks/#cdrecord) 中描述的那样刻录到光盘上。

## 20.5.4. 使用数据光盘

待 ISO 被刻录到光盘，它可以通过指定文件系统类型、包含光盘的设备名称和现有挂载点来挂载：

```sh
# mount -t cd9660 /dev/cd0 /mnt
```

由于 `mount` 假定文件系统类型为 `ufs`，如果在挂载数据光盘时未包含 `-t cd9660`，则会出现 `Incorrect super block` 错误。

虽然可以通过这种方式挂载任何数据光盘，但具有某些 ISO 9660 扩展的磁盘可能会表现得不太正常。例如，Joliet 磁盘将所有文件名存储为双字节 Unicode 字符。如果某些非英文字符显示为问号，则可以使用 `-C` 指定本地字符集。有关更多信息，请参阅 [mount\_cd9660(8)](https://man.freebsd.org/cgi/man.cgi?query=mount_cd9660\&sektion=8\&format=html)。

> **注意**
>
> 为了使用 `-C` 进行字符转换，内核需要加载 **cd9660\_iconv.ko** 模块。可以通过将以下行添加到 **loader.conf** 来实现：
>
> ```sh
> cd9660_iconv_load="YES"
> ```
>
> 然后重启计算机，或者通过直接加载模块使用 `kldload`。

有时，在尝试挂载数据光盘时会显示 `Device not configured`。这通常意味着 CD 驱动器未检测到托盘中的光盘，或者驱动器在总线上不可见。光盘驱动器检测介质可能需要几秒钟的时间，所以请耐心等待。

有时，SCSI CD 驱动器可能会因为没有足够的时间响应总线重置而被忽略。为了解决这个问题，可以创建一个自定义内核，增加默认的 SCSI 延迟。在自定义内核配置文件中添加以下选项，并按照 [“构建和安装自定义内核”](https://docs.freebsd.org/en/books/handbook/kernelconfig/#kernelconfig-building) 中的说明重新构建内核：

```ini
options SCSI_DELAY=15000
```

这告诉 SCSI 总线在启动时暂停 15 秒，以便给 CD 驱动器尽可能多的时间来响应总线重置。

> **注意**
>
> 可以直接将文件刻录到光盘，而无需创建 ISO 9660 文件系统。这被称为刻录原始数据光盘，有些人会为备份目的这样做。这种类型的光盘不能像普通数据光盘那样挂载。为了检索刻录到这样的光盘上的数据，必须从原始设备节点读取数据。例如，以下命令将提取位于第二张 CD 设备上的压缩 tar 文件到当前工作目录：
>
> ```sh
> # tar xzvf /dev/cd1
> ```
>
> 为了挂载数据光盘，数据必须使用 `mkisofs` 写入。

## 20.5.5. 复制音频光盘

要复制音频光盘，需要将音频数据从光盘提取到一系列文件中，然后将这些文件刻录到空白光盘上。

[复制音频光盘](https://docs.freebsd.org/en/books/handbook/disks/#using-cdrecord) 描述了如何复制和刻录音频光盘。如果 FreeBSD 版本低于 10.0，并且设备是 ATAPI，那么必须先加载 `atapicam` 模块，加载方法可以参考 [支持的设备](https://docs.freebsd.org/en/books/handbook/disks/#atapicam)。

**操作步骤：复制音频光盘**

1. 安装 [sysutils/cdrtools](https://cgit.freebsd.org/ports/tree/sysutils/cdrtools/) 软件包和 Ports 后，提供了 `cdda2wav` 命令。此命令可以提取所有音频轨道，每个轨道都写入当前工作目录中的单独 WAV 文件：

   ```sh
   % cdda2wav -vall -B -Owav
   ```

   如果系统中只有一个光盘设备，则不需要指定设备名称。请参阅 `cdda2wav` 的手册页，了解如何指定设备及其他可用选项。
2. 使用 `cdrecord` 将 **.wav** 文件刻录到光盘：

   ```sh
   % cdrecord -v dev=2,0 -dao -useinfo  *.wav
   ```

   请确保根据 [刻录光盘](https://docs.freebsd.org/en/books/handbook/disks/#cdrecord) 中的描述正确设置 *2,0*。
