文章目录
ServiceManager负责binder的查询和注册,由init进程通过解析init.rc文件而创建的
- do_add_service()函数:注册服务
- do_find_service()函数:查找服务
- binder_link_to_death()函数:结束服务
- binder_send_reply()函数:将注册结果返回给Binder驱动
ServiceManger 的初始化
// frameworks/native/cmds/servicemanager/service_manager.c
int main(int argc, char** argv)
{
struct binder_state *bs;
union selinux_callback cb;
char *driver;
if (argc > 1) {
driver = argv[1];
} else {
driver = "/dev/binder";
}
// 打开binder驱动,申请分配内存
bs = binder_open(driver, 128*1024);
// 注册ServiceManager服务
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
cb.func_log = selinux_log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);
binder_loop(bs, svcmgr_handler);
return 0;
}
binder_open
这里的binder_open 不是内核binder驱动的binder_open,而是在用户进程下。
// frameworks/native/cmds/servicemanager/binder.c
struct binder_state *binder_open(const char* driver, size_t mapsize)
{
struct binder_state *bs;
struct binder_version vers;
bs = malloc(sizeof(*bs));
// 打开内核驱动,会调用到驱动的binder_open,返回一个文件句柄
bs->fd = open(driver, O_RDWR | O_CLOEXEC);
// 查询binder版本,会调用到驱动的binder_ioctl,类型是BINDER_VERSION
if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
(vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
// 比较当前binder版本与预期的是否一致
fprintf(stderr,
"binder: kernel driver version (%d) differs from user space version (%d)\n",
vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
goto fail_open;
}
bs->mapsize = mapsize;
// 向内核申请mapSize大小的内存,并映射到内核空间,会调用到驱动的binder_mmap
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
return bs;
流程:
- ServiceManager进程打开binder驱动,驱动调用了binder_open(),binder内核会创建一个对应的binder_proc,初始化之后加入全局的红黑树。
- ServiceManager进程查询binder版本,驱动调用了binder_ioctl(),type是BINDER_VERSION
- ServiceManager进程mmap申请内核内存,驱动调用了binder_mmap(),binder驱动只为进程分配了一个buffer,但还没将内核虚拟空间和进程虚拟空间、物理内存映射
struct binder_state {
int fd; // binder文件描述符
void *mapped; //指向mmap的内存地址
size_t mapsize; //分配的内存大小,默认为128KB
};
binder驱动的BINDER_VERSION命令
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int ret;
struct binder_proc *proc = filp->private_data;
struct binder_thread *thread;
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg;
binder_selftest_alloc(&proc->alloc);
ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
thread = binder_get_thread(proc);
switch (cmd) {
…...
case BINDER_VERSION: {
struct binder_version __user *ver = ubuf;
// 将BINDER_CURRENT_PROTOCOL_VERSION拷贝到用户空间
if (put_user(BINDER_CURRENT_PROTOCOL_VERSION,&ver->protocol_version)) {
ret = -EINVAL;
goto err;
}
break;
…...
}
return ret;
}
ioctl(bs->fd, BINDER_VERSION, &vers) 的第三个