一个关于binder的debug技巧
這里介紹一個通過kernel的sys文件系統去debug binder的方法,我遇到的兩類問題:1、binder leak 2、binder開啟的線程已達上限造成后面的從上往下的call flow block住產生anr
1、binder leak就是binder內存泄漏,用于binder通信的buffer大概有4M左右(據同事描述,還沒拷證具體數值),在binder通信中如果傳輸中使用的parcel沒有有效release,會造成buffer空間越來越少,然后積累到一定程度,就會出現binder傳輸的消息在另外一端無法接收。
/***更正***/
在進程使用binder driver的時候,最大在kernel空間中開啟的虛擬內存空間是4M。一般如果使用IPCThread的API去操作binder的時候是會自動往driver發送FREE_BUFFER的指令做釋放操作,所以一般很難出現Binder leak的現象。除非是自己對binder去做IOctl。
2、binder線程到達上限。這個的情景就是app向service發起請求的頻率過高,service端如果對所有的業務執行都加了鎖的話,則會導致service端用于接收處理binder事件的線程全部卡住,當線程池(default 16個線程)耗盡之后,就無法再處理請求。如果這個時候app的主線程如果再調用該serivce提供的方法,就很容易出現anr
我要提的debug方法就是cat /sys/kernel/debug/binder這個目錄下的文件來查看所有進程的使用binder的狀況來確定是上述兩種狀況的哪一種,我主要是cat transactions這個文件來查看運行狀況的,一般的打印如下:
proc代表進程號;一行buffer代表有一個binder通信在占用buffer的空間(具體其他打印的意義需要參考binder driver)
如果針對第一種binder leak的情況,在程序運行過程中該proc下的buffer的行數會越來越多,不停地增長,這樣基本上你就能判斷是binder leak的情況
另外一種狀況的打印,其中有新增一類以thread開頭的打印,這個代表的是進程具有的接收binder的線程,如果這類行數超多,16個,基本就可以確定是binder線程池已經滿了
proc 1663 thread 1663: l 02incoming transaction 73304: ffffffc07735c580 from 2364:3836 to 1663:1663 code 9 flags 10 pri 0 r1 node 9227 size 44:0 data ffffff8005580880thread 2158: l 10outgoing transaction 73630: ffffffc097d93c00 from 1663:2158 to 2364:0 code 1 flags 10 pri 0 r1 node 23731 size 92:0 data ffffff8005c81018thread 2179: l 02incoming transaction 73390: ffffffc09a2bdf80 from 2364:3879 to 1663:2179 code 9 flags 10 pri 0 r1 node 9227 size 44:0 data ffffff8005580370thread 2968: l 01incoming transaction 73402: ffffffc0b1df1600 from 2364:3859 to 1663:2968 code 20 flags 10 pri 0 r1 node 9227 size 60:0 data ffffff8005580900thread 3328: l 01incoming transaction 73340: ffffffc0b1df1c80 from 2364:3864 to 1663:3328 code 20 flags 10 pri 0 r1 node 9227 size 60:0 data ffffff8005580160thread 3505: l 01incoming transaction 73344: ffffffc0b1acd780 from 2364:3572 to 1663:3505 code 9 flags 10 pri 0 r1 node 9227 size 44:0 data ffffff8005580270thread 3506: l 01incoming transaction 73338: ffffffc0b1df1c00 from 2364:3320 to 1663:3506 code 9 flags 10 pri 0 r1 node 9227 size 44:0 data ffffff80055800e0thread 3528: l 01incoming transaction 73642: ffffffc0b0354500 from 2364:2377 to 1663:3528 code 3 flags 10 pri 0 r1 node 23734 size 72:0 data ffffff8005580a20thread 3529: l 01incoming transaction 73343: ffffffc09b223a00 from 2364:3321 to 1663:3529 code 9 flags 10 pri 0 r1 node 9227 size 44:0 data ffffff80055801f0thread 3582: l 01incoming transaction 73644: ffffffc077b0fc00 from 2364:3516 to 1663:3582 code 3 flags 10 pri 0 r1 node 23734 size 72:0 data ffffff8005580508thread 3583: l 01incoming transaction 73307: ffffffc098e91780 from 2364:3322 to 1663:3583 code 20 flags 10 pri 0 r1 node 9227 size 60:0 data ffffff8005580628thread 3835: l 01incoming transaction 73309: ffffffc0a3c8ae80 from 2364:3566 to 1663:3835 code 20 flags 10 pri 0 r1 node 9227 size 60:0 data ffffff8005580050thread 3852: l 01incoming transaction 73411: ffffffc0b0357200 from 2364:2379 to 1663:3852 code 9 flags 10 pri 0 r1 node 9227 size 44:0 data ffffff80055803f0thread 3853: l 01incoming transaction 73629: ffffffc0779a5500 from 2364:2942 to 1663:3853 code 9 flags 10 pri 0 r1 node 9227 size 44:0 data ffffff8005580470thread 3874: l 01incoming transaction 73400: ffffffc094b5e900 from 2364:3005 to 1663:3874 code 20 flags 10 pri 0 r1 node 9227 size 60:0 data ffffff80055807f0thread 3875: l 01incoming transaction 73308: ffffffc094b19a80 from 2364:3860 to 1663:3875 code 20 flags 10 pri 0 r1 node 9227 size 60:0 data ffffff80055806d0thread 3889: l 01incoming transaction 73384: ffffffc09907ea80 from 2364:3571 to 1663:3889 code 9 flags 10 pri 0 r1 node 9227 size 44:0 data ffffff80055802f0thread 3892: l 01incoming transaction 74866: ffffffc09919be00 from 1650:1816 to 1663:3892 code 4 flags 10 pri -8 r1 node 26532 size 44:0 data ffffff80055805a0buffer 73309: ffffff8005580050 size 60:0 activebuffer 73338: ffffff80055800e0 size 44:0 activebuffer 73340: ffffff8005580160 size 60:0 activebuffer 73343: ffffff80055801f0 size 44:0 activebuffer 73344: ffffff8005580270 size 44:0 activebuffer 73384: ffffff80055802f0 size 44:0 activebuffer 73390: ffffff8005580370 size 44:0 activebuffer 73411: ffffff80055803f0 size 44:0 activebuffer 73629: ffffff8005580470 size 44:0 activebuffer 73644: ffffff8005580508 size 72:0 activebuffer 74866: ffffff80055805a0 size 44:0 activebuffer 73307: ffffff8005580628 size 60:0 activebuffer 73308: ffffff80055806d0 size 60:0 activebuffer 73400: ffffff80055807f0 size 60:0 activebuffer 73304: ffffff8005580880 size 44:0 activebuffer 73402: ffffff8005580900 size 60:0 activebuffer 43572: ffffff80055809a8 size 0:0 deliveredbuffer 73642: ffffff8005580a20 size 72:0 active為了進一步確認是否已經占滿,用debuggerd去dump該進程獲得其墓碑文件,就基本能看出來線程的情況,java的binder線程名大多是binder_1~binder_A ....之類的如果滿16個就能確定了;native的bin檔的話,線程名沒有那么明確,但這些binder線程的名字都相同,也是如果滿了16也能說明是該問題。
為解決這種線程池耗盡的問題,應該從app端去限制請求的頻率,設定一定的時間間隔才能保證功能正常。
原文地址:?https://zhuanlan.zhihu.com/p/22645229
總結
以上是生活随笔為你收集整理的一个关于binder的debug技巧的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android O限制系统全屏进一步遏制
- 下一篇: Binder实用指南(一) - 理解篇