android binder机制,注册系统服务--服务端servicemanager binder驱动
来源:互联网 发布:网络平台开发预算 编辑:程序博客网 时间:2024/06/10 11:08
3 服务端servicemanager binder驱动
前面分析过Servicemanager进程中的main方法步骤,
1,调用binder_open方法打开binder驱动。
2,调用binder_become_context_manager方法注册成为binder服务的大管家。
3,调用binder_loop方法进入无限循环, 处理binder驱动发来的请求。
其中binder_loop调用流程图如下,
3.1 读取驱动信息
binder.c的binder_loop方法如下,
void binder_loop(struct binder_state *bs, binder_handler func){ int res; struct binder_write_read bwr; uint32_t readbuf[32]; bwr.write_size = 0; bwr.write_consumed = 0; bwr.write_buffer = 0;readbuf[0] = BC_ENTER_LOOPER;//将BC_ENTER_LOOPER命令发送给binder驱动 binder_write(bs, readbuf, sizeof(uint32_t)); for (;;) { bwr.read_size = sizeof(readbuf); bwr.read_consumed = 0; bwr.read_buffer = (uintptr_t) readbuf; // 读取驱动的命令 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); if (res < 0) { ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno)); break; } // 解析命令 res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func); if (res == 0) { ALOGE("binder_loop: unexpected reply?!\n"); break; } if (res < 0) { ALOGE("binder_loop: io error %d %s\n", res, strerror(errno)); break; } }}
binder_loop方法主要分为3个阶段,
1,首先调用binder_write方法向binder驱动发送BC_ENTER_LOOPER命令, 告诉binder驱动“本线程要进入循环
状态了”。
2,然后调用ioctl方法读取binder驱动信息。
3,读取驱动信息之后,调用binder_parse方法进行解析。
其中第二步在Servicemanager进程那一章节中也详细论述了,已经在binder驱动的binder_thread_read方法中处
于等待状态了,上一章唤醒就是指唤醒该线程, 继续执行binder_thread_read方法,这个地方比较难懂,有点晦涩,
但是是关键点。
通俗的讲,逻辑原理如下,
1,首先一个厨师将所有菜都买好了,但是没有炒菜,然后就去睡觉了。
2,客人来了点一个菜之后,将厨师叫醒,厨师就去炒客人需要的菜。
这其中涉及到应用进程和Servicemanager进程,用户态和内核态,通过在内核态中的内存共享的方式进行跨进程
通信。流程图如下,
应用进程传入数据时的命令是BINDER_WORK_TRANSACTION, binder_thread_read对该命令的处理如下,
1,首先获取客户进程发送过来的事务,然后复制到结构体binder_transaction_data Tr中。
case BINDER_WORK_TRANSACTION: {t = container_of(w, struct binder_transaction, work);} break;•••if (t->buffer->target_node) {struct binder_node *target_node = t->buffer->target_node;tr.target.ptr = target_node->ptr;tr.cookie = target_node->cookie;t->saved_priority = task_nice(current);if (t->priority < target_node->min_priority && !(t->flags & TF_ONE_WAY))binder_set_nice(t->priority);else if (!(t->flags & TF_ONE_WAY) || t->saved_priority > target_node->min_priority)binder_set_nice(target_node->min_priority);cmd = BR_TRANSACTION;} else {tr.target.ptr = 0;tr.cookie = 0;cmd = BR_REPLY;}tr.code = t->code;tr.flags = t->flags;tr.sender_euid = from_kuid(current_user_ns(), t->sender_euid);
2,将内核态的数据复制到用户态中,此时命令是BR_TRANSACTION
tr.data_size = t->buffer->data_size;tr.offsets_size = t->buffer->offsets_size;tr.data.ptr.buffer = (binder_uintptr_t)((uintptr_t)t->buffer->data +proc->user_buffer_offset);tr.data.ptr.offsets = tr.data.ptr.buffer +ALIGN(t->buffer->data_size, sizeof(void *));if (put_user(cmd, (uint32_t __user *)ptr))return -EFAULT;ptr += sizeof(uint32_t);if (copy_to_user(ptr, &tr, sizeof(tr)))return -EFAULT;ptr += sizeof(tr);
把tr的内容拷贝到用户传进来的缓冲区去了,指针ptr指向这个用户缓冲区的地址。
这样ServiceManager进程在用户空间就真正得到了客户进程发送过来的服务注册信息。接着将客户进程
发送过来的事务项添加到当前线程的事务堆栈中,交给当前线程处理。
if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {t->to_parent = thread->transaction_stack;t->to_thread = thread;thread->transaction_stack = t;} else {t->buffer->transaction = NULL;kfree(t);binder_stats_deleted(BINDER_STAT_TRANSACTION);}
binder_thread_read方法执行完成之后,回到binder_ioctl方法中,
if (bwr.read_size > 0) {ret = binder_thread_read(proc, thread, bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);trace_binder_read_done(ret);if (!list_empty(&proc->todo))wake_up_interruptible(&proc->wait);if (ret < 0) {if (copy_to_user(ubuf, &bwr, sizeof(bwr)))ret = -EFAULT;goto err;}}if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {ret = -EFAULT;goto err;}break;
把本地变量struct binder_write_read bwr的内容拷贝回到用户传进来的缓冲区中,就返回到用户态的binder_loop方法中,
for (;;) { bwr.read_size = sizeof(readbuf); bwr.read_consumed = 0; bwr.read_buffer = (uintptr_t) readbuf; // 读取驱动的命令 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); if (res < 0) { ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno)); break; } // 解析命令 res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func); if (res == 0) { ALOGE("binder_loop: unexpected reply?!\n"); break; }
返回来的数据都放在readbuf中,接着调用binder_parse进行解析。
这一系列实质都是binder_loop方法由用户态到内核态的逆过程。有点难懂,所以要反复折腾。
3.2 解析信息
binder_parse方法中会处理各种类型的消息,现在主要看BR_TRANSACTION类型消息的处理,主要包含服务的注册和获取。
相关代码如下,
case BR_TRANSACTION: { struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr; if ((end - ptr) < sizeof(*txn)) { ALOGE("parse: txn too small!\n"); return -1; } binder_dump_txn(txn); if (func) { unsigned rdata[256/4]; struct binder_io msg; struct binder_io reply; int res; bio_init(&reply, rdata, sizeof(rdata), 4); bio_init_from_txn(&msg, txn); //从txn解析出binder_io信息 res = func(bs, txn, &msg, &reply); binder_send_reply(bs, &reply, txn->data.ptr.buffer, res); } ptr += sizeof(*txn); break; }
1,首先从txn解析出binder_io信息。
2,回调svcmgr_handler方法进行处理,func指向的是service_manager.c中的svcmgr_handler方法,binder驱动的
请求会回调该方法。
3,处理完成之后通知处理结果。
- android binder机制,注册系统服务--服务端servicemanager binder驱动
- android binder机制,注册系统服务---服务端servicemanager
- android binder机制,注册系统服务---客户端Binder驱动
- 【android】binder机制-servicemanager
- Android - Binder机制 - ServiceManager
- android binder 机制 (ServiceManager)
- android binder 机制 (ServiceManager)
- Binder-系统服务和ServiceManager
- 【Android进阶】Android Binder之ServiceManager注册服务解析1
- android binder机制,注册系统服务---native客户端
- android binder机制,注册系统服务---结果返回
- android binder机制---Binder驱动
- android binder机制,注册系统服务---Java层注册系统服务
- Android Binder机制浅析之ServiceManager
- Android Binder机制浅析之ServiceManager
- Android Binder机制(三) ServiceManager守护进程
- Android Binder机制(三) ServiceManager守护进程
- 五、Android Binder机制浅析之ServiceManager
- 动态规划 数字三角形
- hibernate 和java类 往 mysql 传 数据乱码
- 专题二 符号的技巧---- 14.优先级和类型转换分析
- VS运行程序
- 3.字符设备驱动
- android binder机制,注册系统服务--服务端servicemanager binder驱动
- LOG4J配置详解及样例一个
- 关于C++ const 的全面总结
- 修改jenkins的默认端口---tt
- 关于cookie(实训)
- 生成android端BKS类型的证书库
- TensorFlow实战——RNN
- android中用AsyncTask解决UI线程阻塞
- spring boot 部署、启动