background
近期项目反馈开机log里有binder报错如下,开机后,就正常了。
[ 264.315743@1] binder: 5591: binder_alloc_buf size 87696 failed, no address space
[ 264.325729@1] binder: 5591: binder_alloc_buf size 87696 failed, no address space
[ 264.337669@2] binder: 5591: binder_alloc_buf size 87696 failed, no address space
[ 264.339720@3] binder: 5591: binder_alloc_buf size 87696 failed, no address space
no address space表明进程的binder buffer用完了。默认情况下每个进程的binder buffer是1MB,如果binder buffer耗尽,首先要怀疑binder buffer存在泄露。
frameworks/native/libs/binder/ProcessState.cpp
#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
但是开机后,就没有这样的log了。而且进程pid 5591的binder debugfs 节点也没有发现异常。所以这个case并不是binder buffer泄露。
root@MagicProjector_A1S:/ # cat d/binder/proc/5591
binder proc state:
proc 5591
thread 5591: l 00
thread 5619: l 12
thread 5620: l 11
thread 5675: l 00
thread 5679: l 00
thread 5684: l 00
thread 6699: l 00
thread 6702: l 00
thread 6703: l 00
thread 6707: l 00
thread 6709: l 00
thread 6710: l 00
thread 6711: l 00
thread 6712: l 00
node 20090: u00000000ab058e38 c00000000ab058400 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4097
node 9884: u00000000ab06aa18 c00000000ab06a9f8 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4097
node 9903: u00000000ab06bc80 c00000000ab06bc60 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4097
node 10124: u00000000ab074850 c00000000ab07a0f0 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4097
node 20184: u00000000ab09a898 c00000000ab0ba730 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4097
node 20461: u00000000ab09b9a0 c00000000ab071b48 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4097
node 20753: u00000000ab0db840 c00000000ab0db820 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4097
node 22531: u00000000ab112368 c00000000ab106b70 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4097
ref 9879: desc 0 node 1 s 1 w 1 d (null)
ref 9882: desc 1 node 632 s 1 w 1 d (null)
ref 9887: desc 2 node 622 s 1 w 1 d (null)
ref 9888: desc 3 node 750 s 1 w 1 d (null)
ref 9889: desc 4 node 797 s 1 w 1 d (null)
ref 9897: desc 5 node 206 s 1 w 1 d (null)
ref 9910: desc 6 node 1037 s 1 w 1 d (null)
ref 9939: desc 7 node 993 s 1 w 1 d (null)
ref 10048: desc 8 node 1734 s 1 w 1 d (null)
ref 20096: desc 9 node 20095 s 1 w 1 d (null)
ref 10176: desc 10 node 1972 s 1 w 1 d ffffffc016dec9c0
ref 10221: desc 11 node 1796 s 1 w 1 d (null)
ref 10223: desc 12 node 10222 s 1 w 1 d (null)
ref 10236: desc 13 node 700 s 1 w 0 d (null)
ref 20697: desc 14 node 200 s 1 w 1 d (null)
ref 20742: desc 15 node 951 s 1 w 1 d (null)
ref 20745: desc 16 node 5169 s 1 w 1 d ffffffc018c6b840
ref 20931: desc 17 node 180 s 1 w 1 d ffffffc0198acbc0
ref 20938: desc 18 node 1025 s 1 w 1 d (null)
ref 22529: desc 19 node 732 s 1 w 1 d (null)
ref 22534: desc 20 node 4956 s 1 w 1 d (null)
buffer 10235: ffffff8013f00050 size 24:8 delivered
buffer 21121: ffffff8013f00708 size 216:0 delivered
buffer 21268: ffffff8013f00830 size 8036:0 delivered
buffer 21894: ffffff8013f027e8 size 216:0 delivered
buffer 23215: ffffff8013f02910 size 7880:0 delivered
buffer 23358: ffffff8013f04828 size 7880:0 delivered
buffer 24206: ffffff8013f06740 size 7732:0 delivered
debug
每个进程binder buffer默认是1M大小,synchronous transactions和asynchronous transactions各一半512KB。如果是asynchronous transaction buffer不足,那么报错的log是:
[ 264.315743@1] binder: 5591: binder_alloc_buf size 87696 failed, no async space left
所以这个应该是synchronous transaction buffer耗尽导致的。在binder driver里,当分配binder buffer失败时,将binder proc的状态信息打印出来如下:
<3>[ 48.810014@2] binder: 5560: binder_alloc_buf size 91144 failed, no address space
<3>[ 48.811766@2] binder: binder proc state pid : 5560
<4>[ 48.817656@2] Buffer address: ffffff8012400000, size 1040384 Allocated buffers:
<4>[ 48.817670@2] buffer debugid 9282: ffffff8012400198 size 24:8 delivered
<4>[ 48.817678@2] called 9281: ffffff8012400108 from 5560:5715 to 3736:3736 code 1 flags 10 pri 0 r1 buffer free
<4>[ 48.817684@2] buffer debugid 13385: ffffff8012400280 size 1016:0 delivered
<4>[ 48.817690@2] called 13382: ffffff80124001f0 from 5560:5664 to 4104:4274 code 2 flags 10 pri 0 r1 size 1048832:2097664 data ffffff800c900b20
<4>[ 48.817697@2] buffer debugid 20467: ffffff8012400740 size 216:0 delivered
<4>[ 48.817703@2] called 20466: ffffff80124006b0 from 5560:6838 to 4104:4579 code 11 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817710@2] buffer debugid 18858: ffffff8012400a00 size 144:0 delivered
<4>[ 48.817717@2] called 18856: ffffff8012400970 from 5560:6795 to 4104:4396 code 1 flags 10 pri 19 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817724@2] buffer debugid 30628: ffffff8012400cb0 size 216:0 delivered
<4>[ 48.817729@2] called 30627: ffffff8012400c20 from 5560:6837 to 4104:4579 code 11 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817736@2] buffer debugid 20793: ffffff8012400e50 size 8028:0 delivered
<4>[ 48.817742@2] called 20774: ffffff8012400dc0 from 5560:6794 to 4104:4574 code 53 flags 10 pri 19 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817749@2] buffer debugid 34272: ffffff8012402e78 size 216:0 delivered
<4>[ 48.817756@2] called 34270: ffffff8012402de8 from 5560:6786 to 4104:4526 code 11 flags 10 pri 19 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817763@2] buffer debugid 37862: ffffff801240a750 size 2208:0 delivered
<4>[ 48.817769@2] called 37861: ffffff801240a6c0 from 5560:7132 to 4104:4526 code 2 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817775@2] buffer debugid 37440: ffffff801240f7f8 size 91140:0 delivered
<4>[ 48.817781@2] called 37439: ffffff801240f768 from 5560:7109 to 4104:4526 code 28 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817789@2] buffer debugid 37521: ffffff8012425cc8 size 91140:0 delivered
<4>[ 48.817794@2] called 37512: ffffff8012425c38 from 5560:7113 to 4104:4120 code 28 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817801@2] buffer debugid 37771: ffffff801243c198 size 2208:0 delivered
<4>[ 48.817807@2] called 37769: ffffff801243c108 from 5560:7129 to 4104:4527 code 2 flags 10 pri 0 r1 size 28:0 data ffffff800c900d88
<4>[ 48.817813@2] buffer debugid 37823: ffffff801243cb00 size 2208:0 delivered
<4>[ 48.817819@2] called 37822: ffffff801243ca70 from 5560:7124 to 4104:4121 code 2 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817826@2] buffer debugid 37843: ffffff801243d468 size 2208:0 delivered
<4>[ 48.817832@2] called 37842: ffffff801243d3d8 from 5560:7131 to 4104:4583 code 2 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817839@2] buffer debugid 37614: ffffff801243e280 size 91140:0 delivered
<4>[ 48.817844@2] called 37603: ffffff801243e1f0 from 5560:7105 to 4104:4581 code 28 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817851@2] buffer debugid 37602: ffffff8012468b38 size 91140:0 delivered
<4>[ 48.817857@2] called 37591: ffffff8012468aa8 from 5560:7106 to 4104:4120 code 28 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817864@2] buffer debugid 37665: ffffff801247f008 size 91140:0 delivered
<4>[ 48.817870@2] called 37664: ffffff801247ef78 from 5560:7110 to 4104:4577 code 28 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817877@2] buffer debugid 37712: ffffff80124954d8 size 91140:0 delivered
<4>[ 48.817883@2] called 37709: ffffff8012495448 from 5560:7119 to 4104:4583 code 28 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817890@2] buffer debugid 37829: ffffff80124ab9a8 size 91140:0 delivered
<4>[ 48.817896@2] called 37828: ffffff80124ab918 from 5560:7120 to 4104:4576 code 28 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817903@2] buffer debugid 37866: ffffff80124c1e78 size 91140:0 delivered
<4>[ 48.817908@2] called 37865: ffffff80124c1de8 from 5560:7114 to 4104:4577 code 28 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817915@2] buffer debugid 37872: ffffff80124d8348 size 91140:0 delivered
<4>[ 48.817921@2] called 37871: ffffff80124d82b8 from 5560:7126 to 4104:4574 code 28 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.817930@2]
<4>[ 48.817930@2] Free buffers:
<4>[ 48.817936@2] free buffer debugid 37847: ffffff8012400000 size 8
<4>[ 48.817940@2] free buffer debugid 37859: ffffff8012400818 size 88
<4>[ 48.817944@2] free buffer debugid 37841: ffffff8012400a90 size 144
<4>[ 48.817948@2] free buffer debugid 37853: ffffff801243dd08 size 1000
<4>[ 48.817952@2] free buffer debugid 0: ffffff801240aff0 size 18040
<4>[ 48.817956@2] free buffer debugid 37827: ffffff8012402f50 size 30320
<4>[ 48.817960@2] free buffer debugid 0: ffffff80124ee750 size 63464
<4>[ 48.817963@2] free buffer debugid 0: ffffff8012454688 size 82720
<4>[ 48.817967@2] thread 5560: l 20
<4>[ 48.817971@2] thread 5593: l 12
<4>[ 48.817974@2] thread 5594: l 11
<4>[ 48.817977@2] thread 5664: l 20
<4>[ 48.817980@2] thread 5681: l 20
<4>[ 48.817984@2] thread 5710: l 00
<4>[ 48.817987@2] thread 5715: l 20
<4>[ 48.817990@2] thread 6786: l 00
<4>[ 48.817993@2] thread 6794: l 20
<4>[ 48.817996@2] thread 6795: l 20
<4>[ 48.817999@2] thread 6805: l 00
<4>[ 48.818002@2] thread 6807: l 20
<4>[ 48.818005@2] thread 6837: l 00
<4>[ 48.818008@2] thread 6838: l 20
<4>[ 48.818011@2] thread 6999: l 11
<4>[ 48.818014@2] thread 7105: l 00
<4>[ 48.818017@2] thread 7106: l 00
<4>[ 48.818020@2] thread 7109: l 00
<4>[ 48.818023@2] thread 7110: l 00
<4>[ 48.818027@2] thread 7113: l 00
<4>[ 48.818030@2] thread 7114: l 00
<4>[ 48.818033@2] thread 7119: l 00
<4>[ 48.818036@2] thread 7120: l 00
<4>[ 48.818039@2] thread 7124: l 00
<4>[ 48.818042@2] thread 7126: l 00
<4>[ 48.818045@2] thread 7127: l 10
<4>[ 48.818051@2] outgoing transaction 37873: ffffffc021ea4d00 from 5560:7127 to 4104:4120 code 28 flags 10 pri 0 r1 node 569 size 88:0 data ffffff800c9000c8
<4>[ 48.818057@2] thread 7129: l 00
<4>[ 48.818060@2] thread 7131: l 00
<4>[ 48.818063@2] thread 7132: l 00
<4>[ 48.818069@2] node 8609: u00000000ab1e2768 c00000000ab1e2748 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4104
<4>[ 48.818077@2] node 8649: u00000000ab1e2fa8 c00000000ab1e2f88 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4104
<4>[ 48.818084@2] node 18517: u00000000ab1e93c8 c00000000ab03d198 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4104
<4>[ 48.818091@2] node 8939: u00000000ab1f14b8 c00000000ab1f1498 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4104
<4>[ 48.818099@2] node 18826: u00000000ab209638 c00000000ab209618 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4104
<4>[ 48.818107@2] node 18594: u00000000ab219008 c00000000ab219498 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4104
<4>[ 48.818114@2] node 19111: u00000000ab251fe0 c00000000ab251fc0 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4104
<4>[ 48.818121@2] node 20983: u00000000ab261028 c00000000ab2618b8 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 proc 4104
<4>[ 48.818129@2] ref 8604: desc 0 node 1 s 1 w 1 d (null)
<4>[ 48.818134@2] ref 8607: desc 1 node 579 s 1 w 1 d (null)
<4>[ 48.818139@2] ref 8614: desc 2 node 569 s 1 w 1 d (null)
<4>[ 48.818143@2] ref 8615: desc 3 node 685 s 1 w 1 d (null)
<4>[ 48.818148@2] ref 8616: desc 4 node 742 s 1 w 1 d (null)
<4>[ 48.818153@2] ref 8635: desc 5 node 196 s 1 w 1 d (null)
<4>[ 48.818158@2] ref 8662: desc 6 node 980 s 1 w 1 d (null)
<4>[ 48.818163@2] ref 8679: desc 7 node 934 s 1 w 1 d (null)
<4>[ 48.818168@2] ref 8883: desc 8 node 1743 s 1 w 1 d (null)
<4>[ 48.818173@2] ref 18528: desc 9 node 18527 s 1 w 1 d (null)
<4>[ 48.818178@2] ref 9276: desc 10 node 1802 s 1 w 1 d (null)
<4>[ 48.818182@2] ref 9278: desc 11 node 9277 s 1 w 1 d (null)
<4>[ 48.818187@2] ref 9283: desc 12 node 647 s 1 w 0 d (null)
<4>[ 48.818192@2] ref 9290: desc 13 node 2270 s 1 w 1 d ffffffc00e433180
<4>[ 48.818197@2] ref 19078: desc 14 node 188 s 1 w 1 d (null)
<4>[ 48.818202@2] ref 19097: desc 15 node 894 s 1 w 1 d (null)
<4>[ 48.818207@2] ref 19101: desc 16 node 5363 s 1 w 1 d ffffffc0029b1540
<4>[ 48.818212@2] ref 20279: desc 17 node 170 s 1 w 1 d ffffffc0177e8100
<4>[ 48.818217@2] ref 20288: desc 18 node 968 s 1 w 1 d (null)
<4>[ 48.818222@2] ref 20977: desc 19 node 669 s 1 w 1 d (null)
<4>[ 48.818227@2] ref 20988: desc 20 node 4338 s 1 w 1 d (null)
<6>[ 48.818234@2] binder: 4104:4120 transaction failed 29201, size 91140-0
从上面的log中可以看到,需要分配91KB的buffer,但是free buffer里空间最大的是82KB。已经分配的buffer的transaction都是delivered状态,说明transaction已经完成了,但是binder buffer却被hold住了,没有释放。
why delivered binder buffer not release
binder buffer transaction 是delivered的状态,但是binder buffer并没有释放,是什么原因造成的呢?
要搞明白这个问题,需要理清楚一个完整的binder transaction 过程。从binder client到binder server的 transaction过程如下图所示,其中蓝色字体标的是binder server端的调用。
先看从binder client端到binder server端,第7步binder_alloc_buf会在binder server进程的vm空间里分配一块buffer。通过binder传递的数据是封装在parcel 对象里的,binder server在第9步ipcSetDataReference将release_func赋值给parcel的mOwner。在binderServer执行transact后,会调parcel的recyle,进而调到第17步的freeBuffer。
frameworks/native/libs/binder/IPCThreadState.cpp
void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data,
size_t /*dataSize*/,
const binder_size_t* /*objects*/,
size_t /*objectsSize*/, void* /*cookie*/)
{
//ALOGI("Freeing parcel %p", &parcel);
IF_LOG_COMMANDS() {
alog << "Writing BC_FREE_BUFFER for " << data << endl;
}
ALOG_ASSERT(data != NULL, "Called with NULL data");
if (parcel != NULL) parcel->closeFileDescriptors();
IPCThreadState* state = self();
state->mOut.writeInt32(BC_FREE_BUFFER);
state->mOut.writePointer((uintptr_t)data);
}
在freeBuffer函数中,会将BC_FREE_BUFFER cmd写到mOut中。然后第18步sendReply发送到binder driver里。
在binder driver中,会处理BC_FREE_BUFFER将分配的binder buffer释放掉。
static int binder_thread_write(struct binder_proc *proc,
struct binder_thread *thread,
binder_uintptr_t binder_buffer, size_t size,
binder_size_t *consumed)
{
uint32_t cmd;
struct binder_context *context = proc->context;
void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size;
while (ptr < end && thread->return_error.cmd == BR_OK) {
int ret;
if (get_user(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
trace_binder_command(cmd);
if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
atomic_inc(&binder_stats.bc[_IOC_NR(cmd)]);
atomic_inc(&proc->stats.bc[_IOC_NR(cmd)]);
atomic_inc(&thread->stats.bc[_IOC_NR(cmd)]);
}
switch (cmd) {
....
case BC_FREE_BUFFER: {
binder_uintptr_t data_ptr;
struct binder_buffer *buffer;
if (get_user(data_ptr, (binder_uintptr_t __user *)ptr))
return -EFAULT;
ptr += sizeof(binder_uintptr_t);
buffer = binder_alloc_prepare_to_free(&proc->alloc,
data_ptr);
if (buffer == NULL) {
binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n",
proc->pid, thread->pid, (u64)data_ptr);
break;
}
if (!buffer->allow_user_free) {
binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n",
proc->pid, thread->pid, (u64)data_ptr);
break;
}
binder_debug(BINDER_DEBUG_FREE_BUFFER,
"%d:%d BC_FREE_BUFFER u%016llx found buffer %d for %s transaction\n",
proc->pid, thread->pid, (u64)data_ptr,
buffer->debug_id,
buffer->transaction ? "active" : "finished");
if (buffer->transaction) {
buffer->transaction->buffer = NULL;
buffer->transaction = NULL;
}
if (buffer->async_transaction && buffer->target_node) {
struct binder_node *buf_node;
struct binder_work *w;
buf_node = buffer->target_node;
binder_node_inner_lock(buf_node);
BUG_ON(!buf_node->has_async_transaction);
BUG_ON(buf_node->proc != proc);
w = binder_dequeue_work_head_ilocked(
&buf_node->async_todo);
if (!w) {
buf_node->has_async_transaction = 0;
} else {
binder_enqueue_work_ilocked(
w, &proc->todo);
binder_wakeup_proc_ilocked(proc);
}
binder_node_inner_unlock(buf_node);
}
trace_binder_transaction_buffer_release(buffer);
binder_transaction_buffer_release(proc, buffer, NULL);
binder_alloc_free_buf(&proc->alloc, buffer);
break;
}
...
default:
pr_err("%d:%d unknown command %d\n",
proc->pid, thread->pid, cmd);
return -EINVAL;
}
*consumed = ptr - buffer;
}
return 0;
}
所以binder server进程分配的binder buffer在binder transaction中会被 release掉。
再看binder client这端,第23步binder_transaction后在binder client进程的vm空间里分配binder buffer,用来存放reply返回的数据。binder client在第27步会调用freeBuffer将BC_FREE_BUFFER写到mOut中。
frameworks/native/libs/binder/IPCThreadState.cpp
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = (uint32_t)mIn.readInt32();
...
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");
if (err != NO_ERROR) goto finish;
if (reply) {
if ((tr.flags & TF_STATUS_CODE) == 0) {
reply->ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t),
freeBuffer, this);
} else {
err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
}
} else {
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
continue;
}
}
goto finish;
default:
err = executeCommand(cmd);
if (err != NO_ERROR) goto finish;
break;
}
}
finish:
if (err != NO_ERROR) {
if (acquireResult) *acquireResult = err;
if (reply) reply->setError(err);
mLastError = err;
}
return err;
}
但binder client的这个BC_FREE_BUFFER cmd是在什么时间传递到binder driver呢?
答案是下次binder call。如果一个binder thread完成了一次binder transaction,短时间内没有活干。就不会将BC_FREE_BUFFER cmd传递到binder driver。就会造成binder buffer是delivered状态,但是binder buffer却被hold住了,没有释放。
上面的问题中,我们看到binder thread有29个,只有一个在干活。每个binder thread上会hold一个binder buffer。另外,binder buffer的size有些非常大91KB。
这个问题有两个解决方法:
1. 进程不要设置binder thread 的个数,使用默认值15。这样的活,最多会hold住14个binder buffer
2. 将BINDER VM SIZE设大一些
Summary
binder no address space 通常有三个情况:
1. 上层有parcel对像没有调用recycle
2. 本文分析的case
3. 异步transaction调用过多,server端来不及处理。导致阻塞过多的binder asynchronous transaction,每个都会消耗一块binder buffer。这个实际上是一个资源竞争问题。