Binder Driver 初始化

1. Binder 简介

Binder是Android引入的一种进程间通信(IPC)机制,其底层驱动和其它Linux驱动类似,以misc设备来注册的。主要包括以下几个部分:

(1)调用binder_init函数创建/dev/binder设备节点;

(2)调用binder_open函数获取binder驱动文件描述符;

(3)调用binder_mmap函数分配内存存放数据;

(4)调用binder_ioctl函数进行IPC数据操作。

Client,Service以及Service Manager是运行在用户空间的,而binder驱动是运行在内核空间的,需要通过系统调用(syscall)来内核态和用户态切换,如下图所示:

2. kernel init 简述

涉及的代码:

1
2
3
kernel/include/uapi/linux/android/binder.h
kernel/drivers/android/binder.c
kernel/include/linux/init.h

在kernel启动时会将initcall分为不同阶段,每个阶段顺序由链接顺序决定。如有兴趣可以自行查阅vmlinux.lds.h和vmlinux.lds.S代码了解initcall的实现。下面只列出init.h文件中不同initcall的优先级:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// kernel/include/linux/init.h
#define pure_initcall(fn) __define_initcall(fn, 0)
#define core_initcall(fn) __define_initcall(fn, 1)
#define core_initcall_sync(fn) __define_initcall(fn, 1s)
#define postcore_initcall(fn) __define_initcall(fn, 2)
#define postcore_initcall_sync(fn) __define_initcall(fn, 2s)
#define arch_initcall(fn) __define_initcall(fn, 3)
#define arch_initcall_sync(fn) __define_initcall(fn, 3s)
#define subsys_initcall(fn) __define_initcall(fn, 4)
#define subsys_initcall_sync(fn) __define_initcall(fn, 4s)
#define fs_initcall(fn) __define_initcall(fn, 5)
#define fs_initcall_sync(fn) __define_initcall(fn, 5s)
#define device_initcall(fn) __define_initcall(fn, 6)
#define device_initcall_sync(fn) __define_initcall(fn, 6s)
#define late_initcall(fn) __define_initcall(fn, 7)
#define late_initcall_sync(fn) __define_initcall(fn, 7s)

从binder.c中能明显看到,binder驱动就是在device_initcall阶段开始初始化的。

3. binder init 代码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// kernel/drivers/android/binder.c
static int __init binder_init(void)
{
int ret;
char *device_name, *device_names;
struct binder_device *device;
struct hlist_node *tmp;
// 初始化为binder分配内存缓冲区。
binder_alloc_shrinker_init();
// ~0U:无符号整型,对0取反。
atomic_set(&binder_transaction_log.cur, ~0U);
atomic_set(&binder_transaction_log_failed.cur, ~0U);
// 创建/sys/kernel/debug/binder目录。
binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL);
if (binder_debugfs_dir_entry_root)
// 创建/sys/kernel/debug/binder/proc目录用于记录每个进程基本信息。
binder_debugfs_dir_entry_proc = debugfs_create_dir("proc",
binder_debugfs_dir_entry_root);
if (binder_debugfs_dir_entry_root) {
// S_IRUGO=S_IRUSR-00400|S_IRGRP-00040|S_IROTH-00004=00444
// 创建/sys/kernel/debug/binder/state文件用于记录状态信息,并注册操作函数binder_state_fops。
debugfs_create_file("state",
S_IRUGO,
binder_debugfs_dir_entry_root,
NULL,
&binder_state_fops);
// 创建/sys/kernel/debug/binder/stats文件用于记录统计信息,并注册操作函数binder_stats_fops。
debugfs_create_file("stats",
S_IRUGO,
binder_debugfs_dir_entry_root,
NULL,
&binder_stats_fops);
// 创建/sys/kernel/debug/binder/transactions文件用于记录transaction相关信息,并注册操作函数binder_transactions_fops。
debugfs_create_file("transactions",
S_IRUGO,
binder_debugfs_dir_entry_root,
NULL,
&binder_transactions_fops);
// 创建/sys/kernel/debug/binder/transaction_log文件用于记录transaction日志相关信息,并注册操作函数binder_transaction_log_fops。
debugfs_create_file("transaction_log",
S_IRUGO,
binder_debugfs_dir_entry_root,
&binder_transaction_log,
&binder_transaction_log_fops);
// 创建/sys/kernel/debug/binder/failed_transaction_log文件用于记录transaction失败日志相关信息,并注册操作函数binder_transaction_log_fops。
debugfs_create_file("failed_transaction_log",
S_IRUGO,
binder_debugfs_dir_entry_root,
&binder_transaction_log_failed,
&binder_transaction_log_fops);
}
// kzalloc:分配不超过128KB的连续的物理内存映射区域。
// GFP_KERNEL:内存分配器flags,无内存可用时可引起休眠,允许启动磁盘IO和文件系统IO。
// binder_devices_param:binder,hwbinder,vndbinder。
device_names = kzalloc(strlen(binder_devices_param) + 1, GFP_KERNEL);
if (!device_names) {
// ENOMEM:12,内存溢出。
ret = -ENOMEM;
goto err_alloc_device_names_failed;
}
strcpy(device_names, binder_devices_param);
// 创建binder设备
while ((device_name = strsep(&device_names, ","))) {
ret = init_binder_device(device_name);
if (ret)
goto err_init_binder_device_failed;
}
return ret;
err_init_binder_device_failed:
hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) {
// 注册misc设备:/dev/binder
misc_deregister(&device->miscdev);
// 从hash表中删除。
hlist_del(&device->hlist);
kfree(device);
}
err_alloc_device_names_failed:
// 删除/sys/kernel/debug/binder目录。
debugfs_remove_recursive(binder_debugfs_dir_entry_root);
return ret;
}

device_initcall(binder_init);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// kernel/drivers/android/binder.c
struct binder_device {
// 加入binder_devices全局链表。
struct hlist_node hlist;
// misc设备。
struct miscdevice miscdev;
// 获取service manager对应的binder_node。
struct binder_context context;
};

static const struct file_operations binder_fops = {
.owner = THIS_MODULE,
.poll = binder_poll,
.unlocked_ioctl = binder_ioctl,
.compat_ioctl = binder_ioctl,
.mmap = binder_mmap,
.open = binder_open,
.flush = binder_flush,
.release = binder_release,
};

static int __init init_binder_device(const char *name)
{
int ret;
struct binder_device *binder_device;
binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL);
if (!binder_device)
return -ENOMEM;
// 定义binder相关操作fops。
binder_device->miscdev.fops = &binder_fops;
// MISC_DYNAMIC_MINOR:由miscdevice动态分配次设备号。
binder_device->miscdev.minor = MISC_DYNAMIC_MINOR;
binder_device->miscdev.name = name;
binder_device->context.binder_context_mgr_uid = INVALID_UID;
binder_device->context.name = name;
mutex_init(&binder_device->context.context_mgr_node_lock);
// 注册misc混杂设备,其主设备号为10,在/sys/devices/virtual/misc目录下创建设备节点。
ret = misc_register(&binder_device->miscdev);
if (ret < 0) {
// 释放分配的内存,否则会引起oops异常。
kfree(binder_device);
return ret;
}
// 通过全局链表binder_devices管理binder_device。
hlist_add_head(&binder_device->hlist, &binder_devices);
return ret;
}

4. binder 相关日志介绍

(1)执行cat /sys/kernel/debug/binder/proc/<pid>指令所对应的函数是binder_proc_show,包含ref/node/thread等信息:

1
2
3
4
5
6
7
8
9
10
11
android:/sys/kernel/debug/binder/proc # cat 539

binder proc state:
proc 539
context binder
thread 539: l 12 need_return 0 tr 0 // 线程号是539;l 12表明线程状态是BINDER_LOOPER_STATE_ENTERED,BINDER_LOOPER_STATE_WAITINGtr 0表明线程tmp_ref不在使用。
thread 565: l 12 need_return 0 tr 0
node 712: u0000007116e2d140 c0000007116e53008 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 369
ref 710: desc 0 node 1 s 1 w 1 d 0000000000000000

// node debug_id: binder_address weakref_impl_address pri policy:priority hs has_strong_ref hw has_weak_ref ls local_strong_ref lw local_weak_ref is internal_strong_ref iw internal_weak_ref tr tmp_ref proc pid

(2)执行cat /sys/kernel/debug/binder/state指令所对应的函数是binder_state_show,其结构主要包括以下几部分:

a.整体信息:所有dead npdes信息。

1
2
3
4
5
6
7
8
android:/sys/kernel/debug/binder cat state

binder state:
dead nodes:
node 1851: u00000071a5c2d460 c00000071a5c44140 pri 0:120 hs 1 hw 1 ls 0 lw 0 is 0 iw 1 tr 1 proc 913
node 42820: u0000007c8b80db00 c0000007c8b80e3c0 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 541
node 10135: u0000007c89f80980 c0000007c89f5c3c0 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 1147
node 10112: u0000007c89f808c0 c0000007c920fce00 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 913

b.各个进程信息:每个进程thread,node,ref,buffer等信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
android:/sys/kernel/debug/binder cat state

proc 559
context hwbinder
thread 559: l 02 need_return 0 tr 0
incoming transaction 5224: 0000000000000000 from 913:1058 to 559:559 code 4 flags 10 pri 1:89 r1 node 921 size 44:0 data 0000000000000000
thread 1055: l 11 need_return 0 tr 0
node 921: u0000007dc7e2d380 c0000007dc7e441e0 pri 0:120 hs 1 hw 1 ls 1 lw 0 is 2 iw 2 tr 1 proc 913 370
ref 786: desc 0 node 3 s 1 w 1 d 0000000000000000
buffer 5224: 0000000000000000 size 44:0:0 active

// pending transaction:当前所有procthread todo队列的transaction
// incoming transaction:当前thread transaction_stack,由该thread接收的transaction
// outgoint transaction:当前thread transaction_stack,由该thread发出的transaction
// pending transactions:当前proc总的pending transcation

(3)执行cat /sys/kernel/debug/binder/stats指令所对应的函数是binder_stats_show,其结果主要包含两部分:

a.整体统计信息:所有BC_XXX、BR_XXX命令的次数,系统存活的binder数、开机后所创建的binder数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
android:/sys/kernel/debug/binder cat stats

binder stats:
BC_TRANSACTION: 261976
BC_REPLY: 27152
BC_FREE_BUFFER: 309211
BC_INCREFS: 3754
BC_ACQUIRE: 3924
BC_RELEASE: 1132
BC_DECREFS: 1106
BC_INCREFS_DONE: 2111
BC_ACQUIRE_DONE: 2111
BC_REGISTER_LOOPER: 197
BC_ENTER_LOOPER: 171
BC_REQUEST_DEATH_NOTIFICATION: 1219
BC_CLEAR_DEATH_NOTIFICATION: 577
BC_DEAD_BINDER_DONE: 88
BC_TRANSACTION_SG: 10950
BC_REPLY_SG: 9304
BR_TRANSACTION: 272925
BR_REPLY: 36456
BR_TRANSACTION_COMPLETE: 309380
BR_INCREFS: 2122
BR_ACQUIRE: 2122
BR_RELEASE: 770
BR_DECREFS: 766
BR_SPAWN_LOOPER: 199
BR_DEAD_BINDER: 89
BR_CLEAR_DEATH_NOTIFICATION_DONE: 577

proc: active 124 total 205
thread: active 531 total 1154
node: active 1159 total 2128
ref: active 1916 total 3941
death: active 620 total 1219
transaction: active 3 total 309382
transaction_complete: active 0 total 309382

// 有124个binder_proc,531个binder_thread,1159个binder_node,1916个binder_refd等等。
// 从开机到现在创建了205个binder_proc,1154个binder_thread等等。
// 3个正在执行的binder_transaction,完成了0个transaction
// BC_TRANSACTION+BC_REPLY=BR_TRANSACTION_COMPLETE+BR_DEAD_REPLY+BR_FAILED_REPLY

b.遍历进程信息:每个进程基本信息(如refs/node/thread等),所有BC_XXX、BR_XXX命令的次数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
android:/sys/kernel/debug/binder cat stats

proc 539 // pid号是539
context binder // context类型是binder(主要分binderhwbindervndbinder三类)。
threads: 2 //2个binder_thread
requested threads: 0+0/15 //0个requested_threads(请求线程数)+0个requested_threads_started(已启动线程数)/15个max_threads(最大线程数)
ready threads 2 // 2个ready_threads(准备就绪的线程数)
free async space 520192 // 520kb可用的异步空间
nodes: 1 // 1个binder_node
refs: 1 s 1 w 1 // 1次引用次数,1次强引用次数,1次弱引用次数
buffers: 0 // 0个allocated_buffers(已分配的buffer个数)
pages: 0:1:253
pages high watermark: 1
pending transactions: 0 // todo队列中有0个transaction
//该进程中BC_XXXBR_XXX命令执行次数
BC_TRANSACTION: 2
BC_FREE_BUFFER: 2
BC_INCREFS: 1
BC_ACQUIRE: 1
BC_INCREFS_DONE: 1
BC_ACQUIRE_DONE: 1
BC_ENTER_LOOPER: 2
BR_REPLY: 2
BR_TRANSACTION_COMPLETE: 2
BR_INCREFS: 1
BR_ACQUIRE: 1

// 当binder内存吃紧时,可查看free async spacebuffers字段。
// 当系统空间时,一般ready_threads=requested_threads_started+BC_ENTER_LOOPERready_threads个数越少,说明系统越繁忙。
// 绝大多数进程的最大线程数是15个,而surfaceflinger只有4个,但servicemanagerhwbindervndbinder却是0个(因为只有主线程)。

(4)执行cat /sys/kernel/debug/binder/transactions指令可以查看各进程基本信息;

1
2
3
4
5
6
7
8
9
10
11
12
13
android:/sys/kernel/debug/binder # cat transactions

binder transactions:
proc 469
context hwbinder
thread 469: l 02 need_return 0 tr 0
incoming transaction 45841: 0000000000000000 from 0:0 to 469:469 code 6 flags 10 pri 0:120 r1 node 400 size 48:0 data 0000000000000000
node 400: u0000007edd02d380 c0000007edd0530a0 pri 0:120 hs 1 hw 1 ls 3 lw 0 is 1 iw 1 tr 1 proc 370
buffer 45841: 0000000000000000 size 48:0:0 delivered // data_size是48,offset_size是0,delivered表明该内存块已被分发。
buffer 138360: 0000000000000000 size 32:0:0 active
buffer 368562: 0000000000000000 size 32:0:0 active
pending transaction 138360: 0000000000000000 from 0:0 to 469:0 code f43484e flags 10 pri 0:120 r1 node 400 size 32:0 data 0000000000000000
pending transaction 368562: 0000000000000000 from 0:0 to 469:0 code f43484e flags 10 pri 0:120 r1 node 400 size 32:0 data 0000000000000000

(5)执行cat /sys/kernel/debug/binder/transaction_log指令可查看最近32次transaction对应的调用节点信息。

1
2
3
4
5
6
7
8
9
android:/sys/kernel/debug/binder # cat transaction_log

742412: async from 1699:1699 to 479:0 context binder node 30674 handle 25 size 80:0 ret 0/0 l=0
742413: call from 1789:1789 to 479:0 context binder node 34965 handle 34 size 80:0 ret 0/0 l=0
742414: reply from 1699:1699 to 479:0 context binder node 30674 handle 25 size 80:0 ret 0/0 l=0

// debug_id: call_type from from_proc:from_thread to to_proc:to_thread node to_nodehandle target_handle size data_size:offsets_size
// call_type有三种,分别是call,reply,async
// 相较于transaction_logfailed_transaction_log的差异在于其to_proc字段为0,即远程proc挂掉了。

5. binder 相关常量说明

(1)binder_stat_types中定义的类型及其创建、删除函数整理如下表:

类型 备注 创建函数 删除函数
BINDER_STAT_PROC binder进程 binder_open binder_deferred_release
BINDER_STAT_THREAD binder线程 binder_get_thread binder_free_thread
BINDER_STAT_NODE binder节点 binder_new_node binder_thread_read/binder_node_release/binder_dec_node
BINDER_STAT_REF binder引用 binder_get_ref_for_node binder_delete_ref
BINDER_STAT_DEATH binder死亡 binder_thread_write binder_thread_read/binder_release_work/binder_delete_ref
BINDER_STAT_TRANSACTION binder事务 binder_transactionbinder_thread_read/binder_transaction/binder_release_work/binder_pop_transaction
BINDER_STAT_TRANSACTION_COMPLETE binder已完成事务 binder_transaction binder_thread_read/binder_transaction/binder_release_work

(2)binder_driver_command_protocol中包含19条BC_XXX命令,其类型整理如下表:

Call命令 类型 备注
BC_TRANSACTION binder_transaction_data binder事务(client对server的请求)
BC_REPLY binder_transaction_data 事务答复(server对client的答复)
BC_ACQUIRE_RESULT __s32 获取结果
BC_FREE_BUFFER binder_uintptr_t 释放缓冲
BC_INCREFS __u32 -
BC_ACQUIRE __u32 -
BC_RELEASE __u32 -
BC_DECREFS __u32 -
BC_INCREFS_DONE binder_ptr_cookie -
BC_ACQUIRE_DONE binder_ptr_cookie -
BC_ATTEMPT_ACQUIRE binder_pri_desc -
BC_REGISTER_LOOPER void 通知子线程准备
BC_ENTER_LOOPER void 通知主线程准备
BC_EXIT_LOOPER void 通知线程退出
BC_REQUEST_DEATH_NOTIFICATION binder_handle_cookie 请求接收死亡通知
BC_CLEAR_DEATH_NOTIFICATION binder_handle_cookie 请求清除死亡通知
BC_DEAD_BINDER_DONE binder_uintptr_t 已处理完死亡通知
BC_TRANSACTION_SG binder_transaction_data_sg -
BC_REPLY_SG binder_transaction_data_sg -

(3)binder_driver_return_protocol中包含18条BR_XXX命令,其类型整理如下表:

Return命令 类型 备注
BR_ERROR __s32 操作发生错误
BR_OK void 操作完成
BR_TRANSACTION binder_transaction_data 通知进程收到1次binder请求(server端)
BR_REPLY binder_transaction_data 通知进程收到binder请求的回复(client端)
BR_ACQUIRE_RESULT __s32 -
BR_DEAD_REPLY void -
BR_TRANSACTION_COMPLETE void 对于接受请求的确认回复
BR_INCREFS binder_ptr_cookie -
BR_ACQUIRE binder_ptr_cookie -
BR_RELEASE binder_ptr_cookie -
BR_DECREFS binder_ptr_cookie -
BR_ATTEMPT_ACQUIRE binder_pri_ptr_cookie -
BR_NOOP void -
BR_SPAWN_LOOPER void 通知binder进程创建一个新线程
BR_FINISHED void -
BR_DEAD_BINDER binder_uintptr_t 发送死亡通知
BR_CLEAR_DEATH_NOTIFICATION_DONE binder_uintptr_t 完成清除死亡通知
BR_FAILED_REPLY void -

(4)looper相关状态整理如下表:

Looper状态 备注
BINDER_LOOPER_STATE_REGISTERED 0x01
BINDER_LOOPER_STATE_ENTERED 0x02
BINDER_LOOPER_STATE_EXITED 0x04
BINDER_LOOPER_STATE_INVALID 0x08
BINDER_LOOPER_STATE_WAITING 0x10
BINDER_LOOPER_STATE_POLL 0x20