Android系统-ServiceManager1

目录

引言

概念

启动

流程图

main

binder_open

binder_become_context_manager

binder_ioctl

binder_ioctl_set_ctx_mgr

binder_new_node

binder_loop

binder_write

binder_ioctl

binder_ioctl_write_read

binder_thread_write

binder_parse

bio_init

bio_init_from_txn

svcmgr_handler

svcinfo

查询服务

do_find_service

find_svc

bio_put_ref

bio_alloc_obj

bio_alloc

do_add_service

注册服务

svc_can_register

svcinfo_death

bio_get_ref

binder_ioctl_write_read

binder_thread_write

binder_thread_read


引言

ServiceManager是Binder IPC通信中的守护进程,就是为Binder IPC通信的实现服务的。所以ServiceManager本身就是一个服务,而且是binder服务。

ServiceManager有两个特点:

1、没有采用libbinder中的多线程模型来与Binder驱动通信,而是通过自信编写的binder.c直接和Binder驱动通信,并且只有一个循环binder_loop来读取和处理事务,这样才能保持简单高效

2、ServiceManager功能主要有两个:注册服务和查询服务。

概念

ServiceManager启动流程(精简版):

1)打开binder驱动

2)注册为上下文管理者

3)进入loop循环,处理事务

ServiceManager最核心的两个功能:

注册服务:记录服务名和handler,保存到svclist列表

查询服务:根据服务名查询相应的handler信息

启动

流程图

framework/native/cmds/servicemanager/

- service_manager.c

- binder.c

kernel/drivers/ (不同Linux分支路径略有不同)

- android/binder.c

ServiceManager是由init进程创建的

service servicemanager /system/bin/servicemanager
    class core animation
    user system
    group system readproc
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart audioserver
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart inputflinger
    onrestart restart drm
    onrestart restart cameraserver
    onrestart restart keystore
    onrestart restart gatekeeperd
    onrestart restart thermalservice
    writepid /dev/cpuset/system-background/tasks
    shutdown critical

main

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";
    }

    bs = binder_open(driver, 128*1024);
    if (!bs) {
#ifdef VENDORSERVICEMANAGER
        ALOGW("failed to open binder driver %s\n", driver);
        while (true) {
            sleep(UINT_MAX);
        }
#else
        ALOGE("failed to open binder driver %s\n", driver);
#endif
        return -1;
    }

    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);
#ifdef VENDORSERVICEMANAGER
    cb.func_log = selinux_vendor_log_callback;
#else
    cb.func_log = selinux_log_callback;
#endif
    selinux_set_callback(SELINUX_CB_LOG, cb);

#ifdef VENDORSERVICEMANAGER
    sehandle = selinux_android_vendor_service_context_handle();
#else
    sehandle = selinux_android_service_context_handle();
#endif
    selinux_status_open(true);

    if (sehandle == NULL) {
        ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
        abort();
    }

    if (getcon(&service_manager_context) != 0) {
        ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
        abort();
    }


    binder_loop(bs, svcmgr_handler);

    return 0;
}

ServiceManager启动流程(普通版):

1)打开binder驱动,并调用mmap方法分配128K的内存映射空间:binder_open

2)注册成上下文管理者:binder_become_context_manager

3)验证selinux权限,判断进程是否有权限注册或查看指定服务

4)进入循环,等待client的请求:bind_loop

binder_open

struct binder_state
{
    int fd;
    void *mapped;
    size_t mapsize;
};

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;
}

void binder_close(struct binder_state *bs)
{
    munmap(bs->mapped, bs->mapsize);
    close(bs->fd);
    free(bs);
}

用户空间通过open的方法会调用到driver的open方法,创建binder_proc结构体对象,再将binder_proc对象赋值给fd->private_data,同时放入全局链表binder_procs

通过ioctl(bs->fd, BINDER_VERSION, &vers)可以获取驱动的binder版本。

调用mmap()进行内存映射,同理mmap()方法经过系统调用,对应于Binder驱动层的binder_mmap()方法,该方法会在Binder驱动层创建Binder_buffer对象,并放入当前binder_proc的proc->buffers链表。

int fd; // dev/binder的文件描述符

void *mapped; //指向mmap的内存地址

size_t mapsize; //分配的内存大小,默认为128KB

binder_become_context_manager

成为上下文的管理者,整个系统中只有一个这样的管理者。 通过ioctl()方法经过系统调用,对应于Binder驱动层的binder_ioctl()方法.

binder_ioctl

根据参数BINDER_SET_CONTEXT_MGR,最终调用binder_ioctl_set_ctx_mgr()方法,这个过程会持有binder_main_lock。

binder_ioctl_set_ctx_mgr

创建了全局的binder_node对象binder_context_mgr_node,并将binder_context_mgr_node的强弱引用各加1.

binder_new_node

在Binder驱动层创建binder_node结构体对象,并将当前binder_proc加入到binder_node的node->proc。并创建binder_node的async_todo和binder_work两个队列。

binder_loop

进入循环读写操作,由main()方法传递过来的参数func指向svcmgr_handler。

binder_write通过ioctl()将BC_ENTER_LOOPER命令发送给binder驱动,此时bwr只有write_buffer有数据,进入binder_thread_write()方法。 接下来进入for循环,执行ioctl(),此时bwr只有read_buffer有数据,那么进入binder_thread_read()方法。

binder_write

根据传递进来的参数,初始化bwr,其中write_size大小为4,write_buffer指向缓冲区的起始地址,其内容为BC_ENTER_LOOPER请求协议号。通过ioctl将bwr数据发送给binder驱动,则调用其binder_ioctl方法,如下:

binder_ioctl

binder_ioctl_write_read

binder_thread_write

从bwr.write_buffer拿出cmd数据,此处为BC_ENTER_LOOPER. 可见上层本次调用binder_write()方法,主要是完成设置当前线程的looper状态为BINDER_LOOPER_STATE_ENTERED。

binder_parse

解析binder信息,此处参数ptr指向BC_ENTER_LOOPER,func指向svcmgr_handler。故有请求到来,则调用svcmgr_handler。

bio_init

bio_init_from_txn

svcmgr_handler

该方法的功能:查询服务,注册服务,以及列举所有服务

svcinfo

每一个服务用svcinfo结构体来表示,该handle值是在注册服务的过程中,由服务所在进程那一端所确定的。

查询服务

do_find_service

查询到目标服务,并返回该服务所对应的handle

find_svc

从svclist服务列表中,根据服务名遍历查找是否已经注册。当服务已存在svclist,则返回相应的服务名,否则返回NULL。

当找到服务的handle, 则调用bio_put_ref(reply, handle),将handle封装到reply.

bio_put_ref

bio_alloc_obj

bio_alloc

do_add_service

注册服务

注册服务的分以下3部分工作:

  • svc_can_register:检查权限,检查selinux权限是否满足;
  • find_svc:服务检索,根据服务名来查询匹配的服务;
  • svcinfo_death:释放服务,当查询到已存在同名的服务,则先清理该服务信息,再将当前的服务加入到服务列表svclist;

svc_can_register

svcinfo_death

bio_get_ref

binder_write, 进入Binder driver后,直接调用后进入binder_thread_write, 处理BC_REQUEST_DEATH_NOTIFICATION命令

binder_ioctl_write_read

binder_thread_write

此方法中的proc, thread都是指当前servicemanager进程的信息. 此时TODO队列有数据,则进入binder_thread_read.

那么哪些场景会向队列增加BINDER_WORK_DEAD_BINDER事务呢? 那就是当binder所在进程死亡后,会调用binder_release方法, 然后调用binder_node_release.这个过程便会发出死亡通知的回调.

binder_thread_read

将命令BR_DEAD_BINDER写到用户空间, 此处的cookie是前面传递的svcinfo_death. 当binder_loop下一次 执行binder_parse的过程便会处理该消息。

猜你喜欢

转载自blog.csdn.net/haigand/article/details/132248247