Android tinyalsa深度解析之pcm_close调用流程与实战(一百零四)

简介: CSDN博客专家、《Android系统多媒体进阶实战》作者

博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列【原创干货持续更新中...... 】🚀
Android多媒体专栏地址:多媒体系统工程师系列【原创干货持续更新中...... 】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课 🚀
专题四:Android15快速自定义与集成音效实战课 🚀
专题五:Android15音频策略实战课 🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例) 🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
更多原创,欢迎关注:Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

      • [🌻1. 前言](#🌻1. 前言)
      • [🌻2. 用法与应用场景](#🌻2. 用法与应用场景)
      • [🌻3. 调用流程剖析](#🌻3. 调用流程剖析)
        • [3.1 核心步骤](#3.1 核心步骤)
        • [3.2 涉及核心时序图](#3.2 涉及核心时序图)
      • [🌻4. 实战应用案例](#🌻4. 实战应用案例)
      • [🌻5. 用法总结](#🌻5. 用法总结)

🌻1. 前言

本篇目的:Android tinyalsa深度解析之 pcm_close 调用流程与实战。

🌻2. 用法与应用场景

pcm_close 是 tinyalsa 库中用于关闭 PCM 设备并释放所有相关资源的终点函数。它不仅负责用户态内存的回收,更重要的是触发内核驱动释放物理硬件资源。

  • 用法 :int pcm_close(struct pcm *pcm);
  • 返回值 :成功返回 0。若传入指针无效,函数会安全返回。
  • 应用场景:
  1. 结束音频会话:在播放或录音任务完成后,正常关闭设备节点。
  2. 错误处理路径 :当 pcm_open 成功但后续的 pcm_prepare 或数据读写发生严重错误时,必须调用此函数进行资源清理。
  3. 动态路由切换:在 Android 系统切换音频路径(如 Speaker 切换至有线耳机)时,HAL 层通常需要关闭当前的 PCM 实例并重新配置。

🌻3. 调用流程剖析

3.1 核心步骤
  1. 指针合法性校验 :检查传入的 pcm 是否为 NULL 或指向 bad_pcm。tinyalsa 的设计确保了对非法句柄调用 close 也不会导致系统崩溃。
  2. 停止流传输 :如果设备仍处于 RUNNING 状态,底层驱动会在关闭文件描述符前尝试停止 DMA 传输。
  3. 解映射 MMAP 缓冲区 :检查 pcm->mmap_buffer。如果用户以 PCM_MMAP 模式打开设备,pcm_close 会自动调用 munmap 释放映射的内存块。
  4. 触发内核 Release :执行系统调用 close(pcm->fd)。这会进入内核 ALSA 核心层,调用驱动的 release 回调函数,进而关闭硬件功放或重置硬件寄存器。
  5. 内存释放 :调用 free(pcm) 销毁用户态的结构体实例,完成最后的清理工作。

关键技术:坏句柄安全回收
tinyalsa 在 pcm_open 失败时也会返回一个结构体(fd 为 -1)。pcm_close 能够识别这种"坏句柄"并仅释放内存而不尝试执行内核关闭操作,这简化了 HAL 层的异常处理逻辑。

3.2 涉及核心时序图

Audio Codec/DMA Kernel ALSA Core VFS (close syscall) tinyalsa (pcm_close) Audio HAL Audio Codec/DMA Kernel ALSA Core VFS (close syscall) tinyalsa (pcm_close) Audio HAL alt MMAP 模式已启用 调用 pcm_close(pcm) 1. 验证 pcm 指针及状态 2. munmap(pcm->>mmap_buffer) 3. close(pcm->>fd) 触发 snd_pcm_release 停止 DMA, 降低功耗 硬件已重置 返回 4. free(pcm) 释放结构体 返回 0


🌻4. 实战应用案例

此 Demo 展示了在 Android HAL 开发中,如何规范地使用 pcm_close 并通过指针置空防止野指针异常。

c 复制代码
#include <tinyalsa/asoundlib.h>
#include <stdio.h>
#include <stdlib.h>

/**
 * 模拟 HAL 层安全释放音频流的逻辑
 */
void hal_pcm_release(struct pcm **pp_pcm) {
    if (pp_pcm == NULL || *pp_pcm == NULL) {
        return;
    }

    /* 1. 执行 tinyalsa 关闭操作 */
    printf("HAL: Closing pcm device...\n");
    int ret = pcm_close(*pp_pcm);

    if (ret != 0) {
        printf("HAL: Warning - pcm_close returned error code %d\n", ret);
    }

    /* 2. 极其重要:手动将原指针置为 NULL
     * 防止 HAL 层其他线程误用已释放的内存 (Use-After-Free)
     */
    *pp_pcm = NULL;
    printf("HAL: Resource cleanup complete.\n");
}

int main() {
    struct pcm_config config = {
        .channels = 2,
        .rate = 44100,
        .period_size = 1024,
        .period_count = 4,
        .format = PCM_FORMAT_S16_LE
    };

    // 打开设备 (声卡 0, 设备 0, 播放模式)
    struct pcm *out_stream = pcm_open(0, 0, PCM_OUT, &config);

    if (out_stream && pcm_is_ready(out_stream)) {
        printf("HAL: Audio session started.\n");
        // ... 此处执行音频数据写入 pcm_write ...
    }

    // 无论打开成功还是失败,最终都要调用清理函数
    hal_pcm_release(&out_stream);

    return 0;
}

🌻5. 用法总结

特性 详情描述
内存管理 完全清理 。内部集成了对 mmap 缓冲区和 pcm 结构体本身的 free。
调用配对 必须与 pcm_open 配对。漏掉 close 会导致声卡被占用(Device Busy)以及系统 fd 泄露。
线程安全 非线程安全 。严禁在主线程 close 的同时在另一线程执行 pcm_write,需在 HAL 层加锁。
硬件状态 重置硬件。该函数执行后,内核通常会关闭相关的 DAC/ADC 电源以节省功耗。
容错性 高容忍度。可以安全处理未成功 ready 的 pcm 指针,不会造成内核异常。
相关推荐
千里马学框架4 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台4 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone4 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc4 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo4 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077004 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼4 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone4 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen4 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone4 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui