Android 系统服务管家servicemanager启动过程详解
Posted Jason_Wang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 系统服务管家servicemanager启动过程详解相关的知识,希望对你有一定的参考价值。
android考虑到移动设备耗电以及跨进程通信效率等因素,基于OpenBinder专门为进程通信开发了一套框架:binder。例如,客户端程序需要获取WindowManager,TelephonyManager等系统服务时,就需要通过binder这个中介来负责数据与指令的传输。那么,Android提供了如此多的系统服务(可达上百个,可通过 adb shell service list
查看),又是谁在负责管理这些服务了?Android为此专门提供了一个系统管家servicemanager
。servicemanager
主要负责添加服务,获取服务,查找服务以及当某个服务意外终止时,对该服务的资源进行回收。ServiceManager跨越了两个框架层:Java层、C++层。这篇文章先看一看native(C)层的具体实现原理。
源码路径:
- C++: /android/frameworks/native/cmds/servicemanager/
- Java: /android/frameworks/base/core/java/android/os/
servicemanager的启动
Android在init进程启动以后,通过脚本init.rc
,启动ServiceManager:
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart keystore
在service_manager.c
中找到对应的main()
函数,这是servicemanager启动的入口:
int main()
struct binder_state *bs;
// 打开binder
bs = binder_open(128*1024);
if (!bs)
ALOGE("failed to open binder driver\\n");
return -1;
// 成为系统服务的管家
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;
main函数里主要做了三件事:一是打开binder文件节点,并分配IPC所需的内存;二让ServiceManager成为系统服务的管家(context manager);三开启相应的工作线程,并循环处理IPC请求。
binder_open
函数binder_open()
主要作用:(1)打开binder设备文件,获取到对应的文件描述符,(2)从Binder驱动获取binder版本号,(3)接着创建一个binder内存区域,用于跨进程数据的交换(这里大小为128K)。
struct binder_state *binder_open(size_t mapsize)
struct binder_state *bs;
struct binder_version vers;
// 为binder_state分配内存空间
bs = malloc(sizeof(*bs));
if (!bs)
errno = ENOMEM;
return NULL;
// 打开Binder驱动对应的文件节点,最终调用驱动函数binder_open
bs->fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
// 获取当前Binder版本号
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;
//分配一块只读内存区域,用于IPC交换数据,最终调用binder驱动接口binder_mmap
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;
binder相关的
ioctl
指令定义在/android/kernel/drivers/staging/android/uapi/binder.h
#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64)
#define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32)
#define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, __s32)
#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, __s32)
#define BINDER_THREAD_EXIT _IOW('b', 8, __s32)
#define BINDER_VERSION _IOWR('b', 9, struct binder_version)
binder驱动提供了诸如ioctl,mmap,open,flush等操作,在驱动初始化时会将其注册到系统中
static const struct file_operations binder_fops =
.owner = THIS_MODULE,
.poll = binder_poll,
.unlocked_ioctl = binder_ioctl,
.compat_ioctl = binder_ioctl,
.mmap = binder_mmap,
.open = binder_open,
.flush = binder_flush,
.release = binder_release,
;
static struct miscdevice binder_miscdev =
.minor = MISC_DYNAMIC_MINOR,
.name = "binder",
.fops = &binder_fops
;
binder_become_context_manager
int binder_become_context_manager(struct binder_state *bs)
// 系统调用,告知binder驱动,ServiceManager将成为系统服务管家,对应的handle为0
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
系统调用ioctl
最终会调用binder驱动对应的操作函数。查看binder驱动的代码,在/android/kernel/drivers/staging/android/binder.c
中有一个函数binder_ioctl
,这就是用于处理kernel系统调用ioctl
对应的指令,找到请求BINDER_SET_CONTEXT_MGR
对应的代码,在设置系统服务管家完成后,返回对应的结果。
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;
ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
// 加锁
binder_lock(__func__);
thread = binder_get_thread(proc);
switch (cmd)
....
// 设置服务管家
case BINDER_SET_CONTEXT_MGR:
ret = binder_ioctl_set_ctx_mgr(filp);
if (ret)
goto err;
break;
....
// 查询Binder版本
case BINDER_VERSION:
struct binder_version __user *ver = ubuf;
if (put_user_preempt_disabled(BINDER_CURRENT_PROTOCOL_VERSION, &ver->protocol_version))
ret = -EINVAL;
goto err;
break;
default:
ret = -EINVAL;
goto err;
ret = 0;
....
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;
// 让ServiceManager线程进入循环
binder_write(bs, readbuf, sizeof(uint32_t));
for (;;)
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (uintptr_t) readbuf;
// 读取 driver中的数据
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
// 解析读取到的数据,并通过svcmgr_handler进行处理
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
....
读取到binder驱动缓冲区域里的数据后,解析之:
int binder_parse(struct binder_state *bs, struct binder_io *bio,
uintptr_t ptr, size_t size, binder_handler func)
int r = 1;
uintptr_t end = ptr + (uintptr_t) size;
while (ptr < end)
uint32_t cmd = *(uint32_t *) ptr;
ptr += sizeof(uint32_t);
switch(cmd)
case BR_NOOP:
break;
case BR_TRANSACTION_COMPLETE:
break;
case BR_INCREFS:
case BR_ACQUIRE:
case BR_RELEASE:
case BR_DECREFS:
ptr += sizeof(struct binder_ptr_cookie);
break;
case BR_TRANSACTION:
struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
....
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);
// 处理客户端请求,func就是函数svcmgr_handler
res = func(bs, txn, &msg, &reply);
if (txn->flags & TF_ONE_WAY)
binder_free_buffer(bs, txn->data.ptr.buffer);
else
// 发送回复给客户端
binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
ptr += sizeof(*txn);
break;
case BR_REPLY:
struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
if ((end - ptr) < sizeof(*txn))
ALOGE("parse: reply too small!\\n");
return -1;
binder_dump_txn(txn);
if (bio)
bio_init_from_txn(bio, txn);
bio = 0;
else
/* todo FREE BUFFER */
ptr += sizeof(*txn);
r = 0;
break;
case BR_DEAD_BINDER:
struct binder_death *death = (struct binder_death *)(uintptr_t) *(binder_uintptr_t *)ptr;
ptr += sizeof(binder_uintptr_t);
death->func(bs, death->ptr);
break;
case BR_FAILED_REPLY:
r = -1;
break;
....
default:
ALOGE("parse: OOPS %d\\n", cmd);
return -1;
return r;
svcmgr_handler处理客户端的请求,如添加服务,查找服务以及获取服务等。
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
int allow_isolated;
if (txn->target.ptr != BINDER_SERVICE_MANAGER)
return -1;
if (txn->code == PING_TRANSACTION)
return 0;
....
switch(txn->code)
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL)
return -1;
handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
if (!handle)
break;
bio_put_ref(reply, handle);
return 0;
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL)
return -1;
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
case SVC_MGR_LIST_SERVICES:
uint32_t n = bio_get_uint32(msg);
if (!svc_can_list(txn->sender_pid, txn->sender_euid))
ALOGE("list_service() uid=%d - PERMISSION DENIED\\n",
txn->sender_euid);
return -1;
si = svclist;
while ((n-- > 0) && si)
si = si->next;
if (si)
bio_put_string16(reply, si->name);
return 0;
return -1;
default:
ALOGE("unknown code %d\\n", txn->code);
return -1;
bio_put_uint32(reply, 0);
return 0;
这里总结下ServiceManager进程启动的过程,其流程简图如下:
- binder_open(): 打开驱动设备节点,并为进程分配一个128K大小的内存区域用于IPC数据交换;
- binder_become_context_manager(): 使servicemanager称为系统服务的管家;
- binder_loop(): 进入线程执行状态,等待客户端程序的请求
参考文献
以上是关于Android 系统服务管家servicemanager启动过程详解的主要内容,如果未能解决你的问题,请参考以下文章