1. ALSA 音频架构概述

ALSA(Advanced Linux Sound Architecture)是 Linux 内核中负责音频设备管理的核心子系统。它向上提供统一的系统调用接口,向下抽象各类音频硬件,是用户空间应用程序与音频硬件之间的桥梁。理解 ALSA 在 Linux 内核中的位置、用户空间与内核空间的交互方式以及核心数据结构的关系,是掌握声卡注册与设备树配置的基础。

1.1 ALSA 在 Linux 内核中的位置

ALSA 位于 Linux 内核的 drivers/sound/ 目录下,属于字符设备驱动框架的一部分。它通过 VFS(虚拟文件系统)暴露设备节点,并依赖内核其他子系统完成 DMA 传输、中断处理、电源管理等任务。

关键路径: 用户空间 → 系统调用 → VFS → ALSA 核心层 → 硬件驱动层 → 音频控制器

ALSA 在内核中的层次关系如下表所示:

层次 组件 职责
用户空间 应用程序(aplay、arecord、PulseAudio、PipeWire) 通过 ALSA lib 调用 ioctl、mmap、read/write
系统调用层 VFS + 字符设备接口 将文件操作映射到 ALSA 核心层的回调函数
ALSA 核心层 snd core、pcm、control、midi、timer 管理声卡对象、PCM 流、控制接口、DMA 缓冲区
硬件抽象层 soc-core、ac97、hdmi、i2s 控制器驱动 封装硬件寄存器操作,提供平台无关接口
硬件层 音频控制器(I2S、AC97、HDA)、Codec、DMA 引擎 物理音频信号的采集与播放
ALSA 在 Linux 内核中的层次架构 用户空间:应用程序(aplay / arecord / PulseAudio / PipeWire) 系统调用层:VFS + 字符设备接口(ioctl / mmap / read / write) ALSA 核心层 snd core / pcm / control / midi / timer / dma buffer 硬件抽象层:soc-core / ac97 / hdmi / i2s 控制器驱动 硬件层:音频控制器 / Codec / DMA 引擎

1.2 用户空间与内核空间接口

ALSA 在用户空间与内核空间之间定义了清晰的接口边界。用户空间通过 ALSA lib 库调用内核暴露的字符设备接口,内核则通过 file_operations 结构体注册回调函数处理请求。

1.2.1 设备节点

ALSA 在 /dev/snd/ 目录下创建以下设备节点:

  • controlC0:控制接口,用于音量调节、混音器设置、枚举控件
  • pcmC0D0p:PCM 播放设备(p = playback)
  • pcmC0D0c:PCM 录音设备(c = capture)
  • timer:定时器接口,用于音频时钟同步
  • midiC0D0:MIDI 设备接口

1.2.2 核心接口调用流程

用户空间操作 系统调用 内核回调 说明
snd_pcm_open() open() snd_pcm_playback_open() 打开 PCM 设备,分配运行时结构
snd_pcm_hw_params() ioctl(SNDRV_PCM_IOCTL_HW_PARAMS) snd_pcm_hw_params() 设置采样率、格式、通道数、缓冲区大小
snd_pcm_sw_params() ioctl(SNDRV_PCM_IOCTL_SW_PARAMS) snd_pcm_sw_params() 设置触发阈值、中断周期等软件参数
snd_pcm_prepare() ioctl(SNDRV_PCM_IOCTL_PREPARE) snd_pcm_prepare() 准备 DMA 缓冲区,重置指针
snd_pcm_writei() write() / ioctl snd_pcm_playback_trigger() 启动 DMA 传输,将数据写入环形缓冲区
snd_pcm_readi() read() / ioctl snd_pcm_capture_trigger() 从环形缓冲区读取采集到的音频数据
提示: 内核空间与用户空间之间的数据传递主要通过 DMA 环形缓冲区 完成,避免每次读写都产生中断。用户空间通过 mmap 可以直接映射 DMA 缓冲区,实现零拷贝音频传输。
用户空间与内核空间接口交互 用户空间 ALSA lib (libasound) 应用程序:aplay / arecord PulseAudio / PipeWire 内核空间 VFS 字符设备驱动 ALSA 核心层 (snd) PCM / Control / MIDI 子系统 open / ioctl / read / write / mmap 设备节点:/dev/snd/controlC0 / pcmC0D0p / pcmC0D0c DMA 环形缓冲区(硬件与内核共享)

1.3 核心数据结构关系图

ALSA 内核驱动的核心数据结构围绕 struct snd_card 展开,它代表一个物理或逻辑声卡。理解这些结构体之间的关联是编写音频驱动的关键。

1.3.1 核心结构体一览

结构体 头文件 作用
struct snd_card include/sound/core.h 声卡顶层对象,管理所有子设备
struct snd_pcm include/sound/pcm.h PCM 设备,包含 playback 和 capture 子流
struct snd_pcm_substream include/sound/pcm.h 单个 PCM 数据流,管理运行时参数和 DMA 缓冲区
struct snd_pcm_runtime include/sound/pcm.h 运行时状态,记录 hw/sw 参数、DMA 地址、指针位置
struct snd_control include/sound/control.h 控制接口,用于音量、混音器、开关等控件
struct snd_soc_card include/sound/soc.h ASoC 框架中的声卡对象,关联平台、Codec、DAI 链路
struct snd_soc_dai include/sound/soc.h 数字音频接口,描述 I2S、TDM、AC97 等总线配置
struct snd_soc_codec include/sound/soc.h 音频编解码器驱动,负责 DAC/ADC 转换

1.3.2 结构体关系

核心结构体之间的包含与引用关系如下:

  • snd_card 是根对象,通过 devices 链表挂载 snd_pcm、snd_control 等子设备。
  • snd_pcm 包含两个 snd_pcm_substream(playback 和 capture),每个 substream 拥有独立的 snd_pcm_runtime。
  • snd_pcm_runtime 记录 snd_pcm_hw_params(硬件参数)和 snd_pcm_sw_params(软件参数),并指向 DMA 缓冲区描述符。
  • 在 ASoC 框架中,snd_soc_card 通过 dai_link 数组连接 snd_soc_dai 和 snd_soc_codec,形成完整的音频路径。
注意: 在设备树配置中,snd_soc_card 的实例化通常由 simple-card 或 audio-graph-card 驱动完成,开发者只需在设备树中描述 DAI 连接关系,无需手动编写结构体初始化代码。
ALSA 核心数据结构关系图 struct snd_card(声卡对象) struct snd_pcm(PCM 设备) snd_pcm_substream (playback) snd_pcm_substream (capture) snd_pcm_runtime snd_pcm_runtime hw_params / sw_params / dma_addr hw_params / sw_params / dma_addr struct snd_control(音量/混音器控件) 说明:snd_card 通过 devices 链表管理 snd_pcm 和 snd_control;每个 snd_pcm 包含 playback 和 capture 两个 substream

1.4 本章小结

  • ALSA 是 Linux 内核音频子系统的核心,位于 drivers/sound/,通过 VFS 字符设备接口与用户空间交互。
  • 用户空间通过 /dev/snd/ 设备节点和 ALSA lib 库访问内核音频功能,核心操作包括 open、ioctl、mmap、read/write。
  • 核心数据结构以 snd_card 为根,向下包含 snd_pcm、snd_pcm_substream、snd_pcm_runtime,以及 snd_control 控制接口。
  • 在 ASoC 框架中,snd_soc_card 通过 DAI link 连接 Codec 和 CPU DAI,设备树配置直接描述这些连接关系。