<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[【FAQ】全志R329如何解决蓝牙播放无声（snd_pcm_open error: Out of memory）？]]></title><description><![CDATA[<p dir="auto"><strong>问题背景</strong><br />
客户使用蓝牙a2dp source功能，连接蓝牙耳机播放音乐高概率出现播放无声的现象。<br />
但在客户使用相同btmanager版本的其他机型上并没有遇到这个问题。</p>
<p dir="auto"><strong>问题描述</strong><br />
在出现播放无声问题时，btmanager会一直出现如下的打印：</p>
<pre><code>BTMG[aw_pcm_open:400]:  ---&gt;Couldn't open PCM:bluealsa:DEV=28:37:13:3B:DA:78
BTMG[_a2dp_src_pcm_write:150]:  a2dp source open pcm error: Out of memory；
</code></pre>
<p dir="auto">从log来看，播放时没有成功打开蓝牙虚拟声卡，所以播放没有声音是必然的。其中打开蓝牙声卡是使用标准函数snd_pcm_open，<br />
而错误信息是 Out of memory。显然从日志来看，此问题与系统内存有关系。客户机器是512M内存。</p>
<p dir="auto"><strong>问题分析</strong></p>
<p dir="auto">既然与内存有关系，便从内存方向去分析此问题：</p>
<p dir="auto">1）查看当前内存信息<br />
cat /proc/meminfo</p>
<p dir="auto"><img src="/assets/uploads/files/1637905022902-3b1f6a9b0776482496a80e6fa06090e5.jfif" alt="3b1f6a9b0776482496a80e6fa06090e5.jfif" class=" img-responsive img-markdown" width="undefined" height="undefined" /><br />
但是看内存信息，在声卡一直打不开的时候，MemFree也有 10M左右，所以就觉得有点奇怪了，为什么内存这么多，还是申请不到内存打开声卡呢？<br />
难道是脏内存太多了？</p>
<p dir="auto">2）尝试线程的栈调大</p>
<ul>
<li>把btmanager里面相关的线程栈调高至20K，还是无效。</li>
<li>修改C库把默认线程的栈修改为1M，依然无效。</li>
</ul>
<p dir="auto">3）清理缓存</p>
<p dir="auto">是不是脏内存太多，内存不连续？<br />
使用echo 3 &gt; /proc/sys/vm/drop_caches 清理一下，发现就可以正常申请了。<br />
但是让内存的同事看了下连续内存还是足够的，所以这还不是根本原因。</p>
<p dir="auto">4）跟踪代码<br />
通过在alsa-lib 里面增加打印，最终发现是在snd_user_file函数里面调用wordexp(file, &amp;we, WRDE_NOCMD);<br />
返回了WRDE_NOSPACE，而打开的file /usr/share/alsa/alsa.conf也只有10K左右。再继续跟踪C库里面的wordexp函数，发现是在fork的时候有问题。<br />
接着又做了个实验，同时在出问题的时候，我们在非打开声卡的地方调用fork函数，也是会申请不到内存。<br />
所以本质上是fork函数导致的，打开声卡的过程刚好触发了这个问题。</p>
<p dir="auto"><strong>解决办法</strong></p>
<p dir="auto">对于fork函数，有如下的行为：</p>
<p dir="auto">fork函数会创建带有独立虚拟地址空间的新进程，内核会把当前进程的虚拟内存中数据结构复制一份给新进程。</p>
<p dir="auto">看了下客户应用的出问题时的内存情况：<br />
<img src="/assets/uploads/files/1637905015468-c258bb1c9e9849a2a5c991468981f992.jpg" alt="c258bb1c9e9849a2a5c991468981f992.jpg" class=" img-responsive img-markdown" width="562" height="772" /></p>
<p dir="auto">异常时，应用的VmPeak和VmSize偏高，这个说明此时应用申请的虚拟内存是非常高了。<br />
此时如果有打开声卡，触发fork的操作，子进程也需要申请那么大的虚拟内存。<br />
问题就在此，突然申请那么大的虚拟内存，被内核限制了。</p>
<p dir="auto">解决方案：</p>
<p dir="auto">1、客户出问题的方案，由于跑特殊的算法导致使用了比较大的虚拟内存。<br />
可以通过优化应用内存解决。</p>
<p dir="auto">2、取消内核的限制<br />
在系统启动脚本加上 echo &gt; 1 /proc/sys/vm/overcommit_memory 这个命令操作。<br />
内核就不会限制应用申请比较大的虚拟内存了。</p>
]]></description><link>https://bbs.aw-ol.com/topic/657/faq-全志r329如何解决蓝牙播放无声-snd_pcm_open-error-out-of-memory</link><generator>RSS for Node</generator><lastBuildDate>Sat, 16 May 2026 20:36:23 GMT</lastBuildDate><atom:link href="https://bbs.aw-ol.com/topic/657.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 26 Nov 2021 05:39:24 GMT</pubDate><ttl>60</ttl></channel></rss>