文章目录
一、系统服务
System Server 是由 Zygote
进程 fork()
出来的 ;
Init
进程 启动 Zygote
, Zygote
启动 System Server 进程 ;
System Server 注册服务时 , 会执行 service_manager.c 中的方法 ;
二、系统服务主函数
service_manager.c 从 int main(int argc, char** argv)
方法开始执行 , 在该 main 函数中 , 执行了
3
3
3 个重要操作 :
-
① 开启 Binder : 获取 Binder 驱动 , 并且申请了 128 KB 的内存映射地址 ,
bs = binder_open(driver, 128*1024);
; -
② 注册上下文 : 将自己注册成 Binder 进程的上下文 ,
binder_become_context_manager(bs)
; -
③ 开启 Binder 循环 : 不停的轮询 , 是否有消息发送 ,
binder_loop(bs, svcmgr_handler);
;
int main(int argc, char** argv)
{
// 开启 Binder , 获取 Binder 驱动 , 并且申请了 128 KB 的内存映射地址
bs = binder_open(driver, 128*1024);
// 将自己注册成 Binder 进程的上下文
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
// 开启 Binder 循环
binder_loop(bs, svcmgr_handler);
return 0;
}
完整代码参考 /frameworks/native/cmds/servicemanager/service_manager.c ;
三、开启 Binder
通过调用 bs = binder_open(driver, 128*1024);
开启 Binder 的方法 struct binder_state *binder_open(const char* driver, size_t mapsize)
, 定义在 /frameworks/native/cmds/servicemanager/binder.c 中 ;
首先分析下 binder_state
结构体 , 其中有
3
3
3 个参数 ,
-
int fd
: Binder 驱动的文件描述 -
void *mapped
: 内存映射首地址 -
size_t mapsize
: 内存映射的大小 , 128 KB
方法最终返回一个 binder_state 结构体 ;
struct binder_state
{
int fd; // Binder 驱动的文件描述
void *mapped; // 内存映射首地址
size_t mapsize; // 内存映射的大小 , 128 KB
};
// 打开 Binder , 并获取 Binder 的状态描述
struct binder_state *binder_open(const char* driver, size_t mapsize)
{
struct binder_state *bs; // 返回的结构体
struct binder_version vers;
bs = malloc(sizeof(*bs)); // 为返回值申请内存
if (!bs) {
errno = ENOMEM;
return NULL;
}
bs->fd = open(driver, O_RDWR | O_CLOEXEC);
if (bs->fd < 0) {
fprintf(stderr,"binder: cannot open %s (%s)\n",
driver, strerror(errno));
goto fail_open;
}
if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
(vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
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;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
if (bs->mapped == MAP_FAILED) {
fprintf(stderr,"binder: cannot map device (%s)\n",
strerror(errno));
goto fail_map;
}
return bs;
fail_map:
close(bs->fd);
fail_open:
free(bs);
return NULL;
}
完整代码参考 /frameworks/native/cmds/servicemanager/binder.c#97;
四、注册上下文
通过调用 binder_become_context_manager(bs)
, 将自己注册成 Binder 进程的上下文 ; 其中调用的 ioctl
方法是内核中的方法 , 这是 IO Control 的简称 ; 这个代码得去内核中查找 ;
int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
完整代码参考 /frameworks/native/cmds/servicemanager/binder.c#147
在 【Binder 机制】分析 Android 内核源码中的 Binder 驱动源码 binder.c ( googlesource 中的 Android 内核源码 | 内核源码下载 ) 博客中分析了该 ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0)
方法对应的源码 ;
五、开启 Binder 循环
在 service_manager.c 的 main
函数中 , 调用 binder_loop(bs, svcmgr_handler)
开启 Binder 循环 ;
binder_loop
方法定义在 /frameworks/native/cmds/servicemanager/binder.c 中 ;
在 binder_loop
方法中 , 先调用了 binder_write
方法 , 然后开启了死循环 ;
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;
//
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;
}
// 如果收到 Binder 读写消息信息 , 调用 binder_parse 方法处理 ;
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;
}
}
}
完整代码参考 /frameworks/native/cmds/servicemanager/binder.c ;
六、binder_write 方法
在 binder_write
方法中 , 调用了内核中的 ioctl(bs->fd, BINDER_WRITE_READ, &bwr)
方法 ; 具体方法参考 【Binder 机制】分析 Android 内核源码中的 Binder 驱动源码 binder.c ( googlesource 中的 Android 内核源码 | 内核源码下载 ) 博客进行分析 ;
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;
}
完整代码参考 /frameworks/native/cmds/servicemanager/binder.c ;
七、binder_ioctl 内核方法
分析调用内核方法 ioctl(bs->fd, BINDER_WRITE_READ, &bwr)
, 传入 BINDER_WRITE_READ
常量 , 走如下分支代码 ; 主要调用了 binder_ioctl_write_read
方法 ;
case BINDER_WRITE_READ:
ret = binder_ioctl_write_read(filp, cmd, arg, thread);
if (ret)
goto err;
break;
android-mainline/drivers/android/binder.c 部分内核 Binder 驱动代码 :
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;
/*pr_info("binder_ioctl: %d:%d %x %lx\n",
proc->pid, current->pid, cmd, arg);*/
binder_selftest_alloc(&proc->alloc);
trace_binder_ioctl(cmd, arg);
ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
if (ret)
goto err_unlocked;
thread = binder_get_thread(proc);
if (thread == NULL) {
ret = -ENOMEM;
goto err;
}
switch (cmd) {
case BINDER_WRITE_READ:
ret = binder_ioctl_write_read(filp, cmd, arg, thread);
if (ret)
goto err;
break;
default:
ret = -EINVAL;
goto err;
}
ret = 0;
err:
if (thread)
thread->looper_need_return = false;
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
if (ret && ret != -EINTR)
pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
err_unlocked:
trace_binder_ioctl_done(ret);
return ret;
}
八、binder_ioctl_write_read 内核方法
在 方法中 , 调用了
2
2
2 个重要的方法 , copy_from_user(&bwr, ubuf, sizeof(bwr))
从用户空间的进程缓冲区中读取到内核空间缓冲区 , copy_to_user(ubuf, &bwr, sizeof(bwr))
从内核空间写出到用户空间进程中 ;
如果写出的数据大于 0 , 则调用 binder_thread_write
方法 ;
如果读取的数据大于 0 , 则调用 binder_thread_read
方法 ;
static int binder_ioctl_write_read(struct file *filp,
unsigned int cmd, unsigned long arg,
struct binder_thread *thread)
{
int ret = 0;
struct binder_proc *proc = filp->private_data;
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg;
struct binder_write_read bwr;
if (size != sizeof(struct binder_write_read)) {
ret = -EINVAL;
goto out;
}
// 从用户空间的进程缓冲区中读取到内核空间缓冲区
if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
ret = -EFAULT;
goto out;
}
binder_debug(BINDER_DEBUG_READ_WRITE,
"%d:%d write %lld at %016llx, read %lld at %016llx\n",
proc->pid, thread->pid,
(u64)bwr.write_size, (u64)bwr.write_buffer,
(u64)bwr.read_size, (u64)bwr.read_buffer);
// 如果写出的数据大于 0
if (bwr.write_size > 0) {
ret = binder_thread_write(proc, thread,
bwr.write_buffer,
bwr.write_size,
&bwr.write_consumed);
trace_binder_write_done(ret);
if (ret < 0) {
bwr.read_consumed = 0;
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto out;
}
}
// 如果读取的数据大于 0
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);
binder_inner_proc_lock(proc);
if (!binder_worklist_empty_ilocked(&proc->todo))
binder_wakeup_proc_ilocked(proc);
binder_inner_proc_unlock(proc);
if (ret < 0) {
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto out;
}
}
binder_debug(BINDER_DEBUG_READ_WRITE,
"%d:%d wrote %lld of %lld, read return %lld of %lld\n",
proc->pid, thread->pid,
(u64)bwr.write_consumed, (u64)bwr.write_size,
(u64)bwr.read_consumed, (u64)bwr.read_size);
// 从内核空间写出到用户空间进程中
if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
ret = -EFAULT;
goto out;
}
out:
return ret;
}