2. ALSA 体系架构概览
ALSA(Advanced Linux Sound Architecture)是 Linux 内核中用于音频设备驱动的标准框架,也是用户空间音频应用编程的主要接口。理解 ALSA 在 Linux 音频栈中的位置、内核空间与用户空间的分界,以及 Card、Device、Subdevice 这三个核心组件,是后续进行 ALSA 用户空间编程的基础。
2.1 ALSA 在 Linux 音频栈中的位置
在 Linux 系统中,音频数据从应用程序到物理硬件(如 Codec、DAC/ADC)需要经过多个软件层。ALSA 位于中间层,向上提供统一的用户空间 API,向下管理具体的硬件驱动。
- 用户空间应用:播放器(aplay、mpg123)、录音工具(arecord)、VoIP 软件、游戏引擎等。
- ALSA 用户空间库(libasound):提供
snd_pcm_*、snd_ctl_*、snd_mixer_*等 API,简化对内核设备的操作。 - ALSA 内核核心(snd):管理 PCM 设备、控制接口、定时器、MIDI 等子系统。
- ALSA 硬件驱动(snd-xxx):直接与 I2S、AC97、HDMI、USB Audio Class 等硬件控制器交互。
- 物理硬件:SoC 内置 I2S 控制器、外部 Codec 芯片、USB 音频设备等。
2.2 内核空间与用户空间的分界
ALSA 严格遵循 Linux 内核空间与用户空间的分离原则。用户空间的应用程序不能直接访问硬件寄存器,必须通过系统调用进入内核,由内核驱动完成实际操作。
| 维度 | 用户空间 | 内核空间 |
|---|---|---|
| 运行权限 | 非特权(Ring 3) | 特权(Ring 0) |
| 主要组件 | libasound、应用进程 | snd 核心、硬件驱动 |
| 接口方式 | 调用 snd_pcm_* 等 API |
通过 ioctl、mmap、read/write 系统调用 |
| 数据路径 | 应用缓冲区 → libasound 缓冲区 | 内核环形缓冲区(DMA)→ 硬件 FIFO |
| 错误处理 | 返回负的 errno 值(如 -EINVAL) |
内核日志(dmesg) |
/dev/snd/ 下设备文件的 ioctl 或 mmap 系统调用。libasound 封装了这些底层细节,开发者只需关注 API 语义。
2.3 ALSA 核心组件:Card、Device、Subdevice
ALSA 使用三级层次结构来组织音频硬件资源:Card(声卡) → Device(设备) → Subdevice(子设备)。理解这一模型是正确操作 ALSA 设备的前提。
2.3.1 Card(声卡)
Card 代表一个物理或逻辑的音频接口单元。每个 Card 有一个唯一的编号(从 0 开始),以及一个名称(如 hw:0、hw:1)。在嵌入式系统中,一个 SoC 通常只有一个 Card;如果外接 USB 音频设备,则会注册为新的 Card。
- 标识符:
hw:0、hw:1、default(指向系统默认声卡)。 - 查看方式:
cat /proc/asound/cards或aplay -l。 - 典型场景:嵌入式开发板上,Card 0 通常是 SoC 内置音频接口,Card 1 可能是 HDMI 或 USB 音频。
2.3.2 Device(设备)
每个 Card 下可以包含多个 Device,每个 Device 代表一种功能接口。最常见的 Device 类型是 PCM(Pulse Code Modulation)设备,用于播放和录音。此外还有 Control 设备(用于音量、开关控制)、MIDI 设备、Timer 设备等。
- PCM 设备编号:通常 device 0 为播放,device 1 为录音,但并非绝对。
- 标识符:
hw:0,0(Card 0 的 Device 0)、hw:0,1(Card 0 的 Device 1)。 - 查看方式:
cat /proc/asound/card0/pcm0p/info(p 表示 playback,c 表示 capture)。
2.3.3 Subdevice(子设备)
Subdevice 是 Device 下的更细粒度单元,用于支持多路复用。例如,一个支持多通道独立播放的硬件,可以将每个通道映射为一个 Subdevice。大多数嵌入式音频设备每个 Device 只有一个 Subdevice(编号 0)。
- 标识符:
hw:0,0,0(Card 0, Device 0, Subdevice 0)。 - 典型用途:多声道声卡、支持多个独立音频流的专业音频接口。
- 默认值:如果硬件不支持多子设备,Subdevice 编号固定为 0。
2.4 设备文件与用户空间访问入口
ALSA 在 /dev/snd/ 目录下暴露一组设备文件,用户空间通过它们与内核交互。常见的设备文件类型如下:
| 设备文件 | 类型 | 说明 |
|---|---|---|
/dev/snd/controlC0 |
Control | Card 0 的控制接口(音量、开关、混音器) |
/dev/snd/pcmC0D0p |
PCM 播放 | Card 0 Device 0 播放(playback) |
/dev/snd/pcmC0D0c |
PCM 录音 | Card 0 Device 0 录音(capture) |
/dev/snd/timer |
Timer | 全局音频定时器 |
/dev/snd/seq |
Sequencer | MIDI 序列器 |
- 嵌入式系统中,如果内核未编译
CONFIG_SND或相关驱动,/dev/snd/目录可能为空或不存在。 - 用户空间程序需要
rw权限访问这些设备文件。通常将用户加入audio组可解决权限问题。 - 不要直接
open和ioctl操作/dev/snd/pcmC*文件,除非你正在编写极底层的测试代码。生产代码应使用 libasound 提供的 API。
2.5 本章小结
- ALSA 是 Linux 音频栈的核心,位于用户空间应用与硬件驱动之间。
- 用户空间通过 libasound 库和
/dev/snd/设备文件与内核 ALSA 子系统通信。 - ALSA 使用 Card → Device → Subdevice 三级模型管理音频硬件,标识符格式为
hw:Card,Device,Subdevice。 - 嵌入式开发中,最常操作的是 PCM 设备(
hw:0,0)和 Control 设备(hw:0)。