binder call fail caused by no address space

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。这个实际上是一个资源竞争问题。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值