Android 系统服务管家servicemanager启动过程详解

时间:2022-07-29 16:08:16

Android考虑到移动设备耗电以及跨进程通信效率等因素,基于OpenBinder专门为进程通信开发了一套框架:binder。例如,客户端程序需要获取WindowManager,TelephonyManager等系统服务时,就需要通过binder这个中介来负责数据与指令的传输。那么,Android提供了如此多的系统服务(可达上百个,可通过 adb shell service list查看),又是谁在负责管理这些服务了?Android为此专门提供了一个系统管家servicemanagerservicemanager主要负责添加服务,获取服务,查找服务以及当某个服务意外终止时,对该服务的资源进行回收。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启动过程详解

参考文献