其他
Binder这么弱还赶来面头条?
1service servicemanager /system/bin/servicemanager
2 class core animation
3 user system //1
4 group system readproc
5 critical //2
6 onrestart restart healthd
7 onrestart restart zygote
8 onrestart restart audioserver
9 onrestart restart media
10 onrestart restart surfaceflinger
11 onrestart restart inputflinger
12 onrestart restart drm
13 onrestart restart cameraserver
14 onrestart restart keystore
15 onrestart restart gatekeeperd
16 writepid /dev/cpuset/system-background/tasks
17 shutdown critical
18}
1int main(int argc, char** argv)
2{
3 struct binder_state *bs;//1
4 union selinux_callback cb;
5 char *driver;
6
7 if (argc > 1) {
8 driver = argv[1];
9 } else {
10 driver = "/dev/binder";
11 }
12 bs = binder_open(driver, 128*1024);//2
13 ...
14 if (binder_become_context_manager(bs)) {//3
15 ALOGE("cannot become context manager (%s)\n", strerror(errno));
16 return -1;
17 }
18 ...
19 if (getcon(&service_manager_context) != 0) {
20 ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
21 abort();
22 }
23 binder_loop(bs, svcmgr_handler);//4
24
25 return 0;
26}
1struct binder_state
2{
3 int fd; //binder设备的文件描述符
4 void *mapped; //binder设备文件映射到进程的地址空间
5 size_t mapsize; //内存映射后,系统分配的地址空间的大小,默认为128KB
6}
注释2处调用了binderopen函数,用于打开binder设备文件,并申请了128KB大小的内存空间。 注释3处调用了binder_become_context_manager函数,将servicemanager注册成为Binder机制的上下文管理者。 注释4处调用了binder_loop函数,循环等待和处理客户端发来的请求。
1. 打开binder设备文件
1struct binder_state *binder_open(const char* driver, size_t mapsize)
2{
3 struct binder_state *bs;
4 struct binder_version vers;
5
6 bs = malloc(sizeof(*bs));
7 if (!bs) {
8 errno = ENOMEM;
9 return NULL;
10 }
11
12 bs->fd = open(driver, O_RDWR | O_CLOEXEC);//1
13 if (bs->fd < 0) {
14 fprintf(stderr,"binder: cannot open %s (%s)\n",
15 driver, strerror(errno));
16 goto fail_open;
17 }
18 //获取Binder的version
19 if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
20 (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {//2
21 fprintf(stderr,
22 "binder: kernel driver version (%d) differs from user space version (%d)\n",
23 vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
24 goto fail_open;
25 }
26
27 bs->mapsize = mapsize;
28 bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);//3
29 if (bs->mapped == MAP_FAILED) {
30 fprintf(stderr,"binder: cannot map device (%s)\n",
31 strerror(errno));
32 goto fail_map;
33 }
34 return bs;
35
36fail_map:
37 close(bs->fd);
38fail_open:
39 free(bs);
40 return NULL;
41}
1static int binder_open(struct inode *nodp, struct file *filp)
2{//代表Binder进程
3 struct binder_proc *proc;//1
4 binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n",
5 current->group_leader->pid, current->pid);
6//分配内存空间
7 proc = kzalloc(sizeof(*proc), GFP_KERNEL);//2
8 if (proc == NULL)
9 return -ENOMEM;
10 get_task_struct(current);
11 proc->tsk = current;
12 INIT_LIST_HEAD(&proc->todo);
13 init_waitqueue_head(&proc->wait);
14 proc->default_priority = task_nice(current);
15//binder同步锁
16 binder_lock(__func__);
17
18 binder_stats_created(BINDER_STAT_PROC);
19 hlist_add_head(&proc->proc_node, &binder_procs);
20 proc->pid = current->group_leader->pid;
21 INIT_LIST_HEAD(&proc->delivered_death);
22 filp->private_data = proc;//3
23//binder同步锁释放
24 binder_unlock(__func__);
25 ...
26 return 0;
27}
1int binder_become_context_manager(struct binder_state *bs)
2{
3 return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
4}
1static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
2{
3 int ret;
4 struct binder_proc *proc = filp->private_data; //1
5 struct binder_thread *thread;
6 unsigned int size = _IOC_SIZE(cmd);
7 void __user *ubuf = (void __user *)arg;
8 trace_binder_ioctl(cmd, arg);
9
10 ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
11 if (ret)
12 goto err_unlocked;
13
14 binder_lock(__func__);
15 thread = binder_get_thread(proc);//2
16 if (thread == NULL) {
17 ret = -ENOMEM;
18 goto err;
19 }
20
21 switch (cmd) {
22 ...
23 case BINDER_SET_CONTEXT_MGR:
24 if (binder_context_mgr_node != NULL) {//3
25 printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already set\n");
26 ret = -EBUSY;
27 goto err;
28 }
29 ret = security_binder_set_context_mgr(proc->tsk);
30 if (ret < 0)
31 goto err;
32 if (binder_context_mgr_uid != -1) {//4
33 if (binder_context_mgr_uid != current->cred->euid) {//5
34 printk(KERN_ERR "binder: BINDER_SET_"
35 "CONTEXT_MGR bad uid %d != %d\n",
36 current->cred->euid,
37 binder_context_mgr_uid);
38 ret = -EPERM;
39 goto err;
40 }
41 } else
42 binder_context_mgr_uid = current->cred->euid;//6
43 binder_context_mgr_node = binder_new_node(proc, NULL, NULL);//7
44 if (binder_context_mgr_node == NULL) {
45 ret = -ENOMEM;
46 goto err;
47 }
48 binder_context_mgr_node->local_weak_refs++;
49 binder_context_mgr_node->local_strong_refs++;
50 binder_context_mgr_node->has_strong_ref = 1;
51 binder_context_mgr_node->has_weak_ref = 1;
52 break;
53 ...
54err_unlocked:
55 trace_binder_ioctl_done(ret);
56 return ret;
57}
3. 循环等待和处理客户端发来的请求
1void binder_loop(struct binder_state *bs, binder_handler func)
2{
3 int res;
4 struct binder_write_read bwr;
5 uint32_t readbuf[32];
6
7 bwr.write_size = 0;
8 bwr.write_consumed = 0;
9 bwr.write_buffer = 0;
10
11 readbuf[0] = BC_ENTER_LOOPER;
12 binder_write(bs, readbuf, sizeof(uint32_t));//1
13
14 for (;;) {
15 bwr.read_size = sizeof(readbuf);
16 bwr.read_consumed = 0;
17 bwr.read_buffer = (uintptr_t) readbuf;
18
19 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);//2
20
21 if (res < 0) {
22 ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
23 break;
24 }
25
26 res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);//3
27 if (res == 0) {
28 ALOGE("binder_loop: unexpected reply?!\n");
29 break;
30 }
31 if (res < 0) {
32 ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
33 break;
34 }
35 }
36}
1int binder_write(struct binder_state *bs, void *data, size_t len)
2{
3 struct binder_write_read bwr;//1
4 int res;
5
6 bwr.write_size = len;
7 bwr.write_consumed = 0;
8 bwr.write_buffer = (uintptr_t) data;//2
9 bwr.read_size = 0;
10 bwr.read_consumed = 0;
11 bwr.read_buffer = 0;
12 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);//3
13 if (res < 0) {
14 fprintf(stderr,"binder_write: ioctl failed (%s)\n",
15 strerror(errno));
16 }
17 return res;
18}
1static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
2{
3 ...
4 void __user *ubuf = (void __user *)arg;
5 ...
6 switch (cmd) {
7 case BINDER_WRITE_READ: {
8 struct binder_write_read bwr;
9 if (size != sizeof(struct binder_write_read)) {
10 ret = -EINVAL;
11 goto err;
12 }
13 if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {//1
14 ret = -EFAULT;
15 goto err;
16 }
17 binder_debug(BINDER_DEBUG_READ_WRITE,
18 "binder: %d:%d write %ld at %08lx, read %ld at %08lx\n",
19 proc->pid, thread->pid, bwr.write_size, bwr.write_buffer,
20 bwr.read_size, bwr.read_buffer);
21
22 if (bwr.write_size > 0) {//2
23 ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);//3
24 trace_binder_write_done(ret);
25 if (ret < 0) {
26 bwr.read_consumed = 0;
27 if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
28 ret = -EFAULT;
29 goto err;
30 }
31 }
32 ...
33 binder_debug(BINDER_DEBUG_READ_WRITE,
34 "binder: %d:%d wrote %ld of %ld, read return %ld of %ld\n",
35 proc->pid, thread->pid, bwr.write_consumed, bwr.write_size,
36 bwr.read_consumed, bwr.read_size);
37 if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {//4
38 ret = -EFAULT;
39 goto err;
40 }
41 break;
42 }
43 ...
44 return ret;
45}