简介:CSDN博客专家、《Android系统多媒体进阶实战》作者
博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列【原创干货持续更新中……】🚀
Android多媒体专栏地址:多媒体系统工程师系列【原创干货持续更新中……】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课🚀
专题四:Android15快速自定义与集成音效实战课🚀
专题五:Android15音频策略实战课🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例)🚀
人生格言:人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
🍉🍉🍉文章目录🍉🍉🍉
- 🌻1. 前言
- 🌻2. 用法与应用场景
- 🌻3. 调用流程剖析
- 3.1 核心步骤
- 3.2 涉及核心时序图
- 🌻4. 实战应用案例
- 🌻5. 用法总结
🌻1. 前言
本篇目的:Android tinyalsa之pcm_close调用流程与实战。
🌻2. 用法与应用场景
pcm_close是tinyalsa库中用于关闭 PCM 设备并释放所有相关资源的终点函数。它不仅负责用户态内存的回收,更重要的是触发内核驱动释放物理硬件资源。
- 用法:
int pcm_close(struct pcm *pcm); - 返回值:成功返回0。若传入指针无效,函数会安全返回。
- 应用场景:
- 结束音频会话:在播放或录音任务完成后,正常关闭设备节点。
- 错误处理路径:当
pcm_open成功但后续的pcm_prepare或数据读写发生严重错误时,必须调用此函数进行资源清理。 - 动态路由切换:在 Android 系统切换音频路径(如 Speaker 切换至有线耳机)时,HAL 层通常需要关闭当前的 PCM 实例并重新配置。
🌻3. 调用流程剖析
3.1 核心步骤
- 指针合法性校验:检查传入的
pcm是否为NULL或指向bad_pcm。tinyalsa的设计确保了对非法句柄调用 close 也不会导致系统崩溃。 - 停止流传输:如果设备仍处于
RUNNING状态,底层驱动会在关闭文件描述符前尝试停止 DMA 传输。 - 解映射 MMAP 缓冲区:检查
pcm->mmap_buffer。如果用户以PCM_MMAP模式打开设备,pcm_close会自动调用munmap释放映射的内存块。 - 触发内核 Release:执行系统调用
close(pcm->fd)。这会进入内核 ALSA 核心层,调用驱动的release回调函数,进而关闭硬件功放或重置硬件寄存器。 - 内存释放:调用
free(pcm)销毁用户态的结构体实例,完成最后的清理工作。
关键技术:坏句柄安全回收tinyalsa在pcm_open失败时也会返回一个结构体(fd 为 -1)。pcm_close能够识别这种“坏句柄”并仅释放内存而不尝试执行内核关闭操作,这简化了 HAL 层的异常处理逻辑。
3.2 涉及核心时序图
🌻4. 实战应用案例
此 Demo 展示了在 Android HAL 开发中,如何规范地使用pcm_close并通过指针置空防止野指针异常。
#include<tinyalsa/asoundlib.h>#include<stdio.h>#include<stdlib.h>/** * 模拟 HAL 层安全释放音频流的逻辑 */voidhal_pcm_release(structpcm**pp_pcm){if(pp_pcm==NULL||*pp_pcm==NULL){return;}/* 1. 执行 tinyalsa 关闭操作 */printf("HAL: Closing pcm device...\n");intret=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");}intmain(){structpcm_configconfig={.channels=2,.rate=44100,.period_size=1024,.period_count=4,.format=PCM_FORMAT_S16_LE};// 打开设备 (声卡 0, 设备 0, 播放模式)structpcm*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);return0;}🌻5. 用法总结
| 特性 | 详情描述 |
|---|---|
| 内存管理 | 完全清理。内部集成了对mmap缓冲区和pcm结构体本身的free。 |
| 调用配对 | 必须与 pcm_open 配对。漏掉 close 会导致声卡被占用(Device Busy)以及系统 fd 泄露。 |
| 线程安全 | 非线程安全。严禁在主线程 close 的同时在另一线程执行pcm_write,需在 HAL 层加锁。 |
| 硬件状态 | 重置硬件。该函数执行后,内核通常会关闭相关的 DAC/ADC 电源以节省功耗。 |
| 容错性 | 高容忍度。可以安全处理未成功 ready 的 pcm 指针,不会造成内核异常。 |