ServiceManager启动流程大致分以下三步:
- binder_open(打开binder驱动,进行mmap空间映射)
- binder_become_context_manager(注册自己为服务管家)
- binder_loop(循环等待处理Client的请求)
源码阅读地址参考:
main()
ServiceManager是init进程解析init.rc文件时启动的
/system/core/rootdir/init.rc
start servicemanager //319行 ,启动servicemanager.rc脚本
/frameworks/native/cmds/servicemanager/servicemanager.rc
service servicemanager /system/bin/servicemanager
……
servicemanager是以服务形式启动的,启动路径/system/bin/servicemanager,对应源文件service_manager.c,找到main函数:
/frameworks/native/cmds/servicemanager/service_manager.c
int main(int argc, char** argv){
……
struct binder_state *bs;
driver = "/dev/binder";
bs = binder_open(driver, 128*1024);
……
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
……
binder_loop(bs, svcmgr_handler);
}
我们可以看到三个主要函数:
- binder_open打开binder设备文件/dev/binder,函数会返回映射的地址和空间,保存在binder_state类型的bs对象中
- binder_become_context_manager将自己注册为servicemanager, handle为0,其他Client可以通过这个0号引用获取到Service Manager
- binder_loop循环等待+处理 Client 请求(Service注册请求+代理对象获取请求)
binder_open
/frameworks/native/cmds/servicemanager/binder.c
struct binder_state{
int fd;//文件描述符
void *mapped;//起始地址
size_t mapsize;//空间大小
};
struct binder_state *binder_open(const char* driver, size_t mapsize{
……
bs = malloc(sizeof(*bs));
……
//其中bs的类型为binder_state
bs->fd = open(driver, O_RDWR | O_CLOEXEC);
……
bs->mapsize = mapsize;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
……
}
- 调用binder.c的binder_open,函数内部调用open打开设备文件,为当前进程创建binder_state结构体
- 接着调用mmap函数,请求binder驱动申请128K大小的内核缓冲区,映射到servicemanager的进程空间,映射后的起始地址和空间大小,均保存在binder_state结构体中
- 最后bs返回servicemanager
open()、mmap()最后都是调用kernel层Binder驱动的binder_open()、binder_mmap(),具体细节自行查看吧
binder_become_context_manager
/frameworks/native/cmds/servicemanager/binder.c
int binder_become_context_manager(struct binder_state *bs){
……
result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
return result;
}
调用kernel层binder.c的ioctl方法
/kernel/3.4/xref/drivers/staging/android/binder.c
static struct binder_node *binder_context_mgr_node;
……
static struct binder_node *binder_new_node(……)
……
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){
……
case BINDER_SET_CONTEXT_MGR:
……
binder_context_mgr_node = binder_new_node(proc, NULL, NULL);
……
}
使用binder_new_node创建了servicemanager对应的binder_node结点,保存在了binder_context_mgr_node变量中
也就是说其他所有Client均可以通过binder.c的binder_context_mgr_node变量拿到servicemanager对应的binder_node结点
binder_loop
/frameworks/native/cmds/servicemanager/binder.c
void binder_loop(struct binder_state *bs, binder_handler func){
……
//数据置空
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
readbuf[0] = BC_ENTER_LOOPER;
//通过binder_write,即ioctl向binder驱动层写入数据
//通知binder驱动,servicemanager开启loop循环了
//第一次写入数据
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) {
fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
goto fail;
}
res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0);
if (res == 0) return 0;
if (res < 0) goto fail;
}
……
}
int binder_write(struct binder_state *bs, void *data, size_t len) {
struct binder_write_read bwr;
int res;
bwr.write_size = len;
bwr.write_consumed = 0;
bwr.write_buffer = (uintptr_t) data;
bwr.read_size = 0;
bwr.read_consumed = 0;
bwr.read_buffer = 0;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
if (res < 0) {
fprintf(stderr,"binder_write: ioctl failed (%s)\n",
strerror(errno));
}
return res;
}
可以看出:
第一次写入write_buffer = BC_ENTER_LOOPER
第二次写入read_buffer = BC_ENTER_LOOPER
/kernel/3.4/xref/drivers/staging/android/binder.c
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){
……
case BINDER_WRITE_READ: {
……
//将用户空间的数据拷贝到内核空间
if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
ret = -EFAULT; goto out;
}
//第一次进入到这里
if (bwr.write_size > 0) {
ret = binder_thread_write(proc, thread,bwr.write_buffer,bwr.write_size,&bwr.write_consumed);
……
}
//第二次进入到这里
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);
……
}
……
}
}
第一次binder_thread_write()主要是设置一个START标志
static int binder_thread_write(……){
……
//循环获取buffer中的数据
while (……) {
……
case BC_ENTER_LOOPER:
//设置线程的looper = BINDER_LOOPER_STATE_ENTERED
thread->looper |= BINDER_LOOPER_STATE_ENTERED;
break;
……
}
}
第二次已经开启死循环了,不断调用binder_thread_read()
static int binder_thread_read(……){
……
//如果没有请求,则阻塞在此次,直到有请求,再次唤醒
ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
……
}
只是贴了主要代码,具体细节还请自行查看源码
结尾:
失眠必读系列未完待续,有任何错误,虚心讨教,欢迎指正...
参考资料: