Android Binder - Service Manager

Service Manager是所有服务的管理器,因此,所有Server(System Server)都要向它注册,应用程序则向Service Manager查询相应的服务。其实现位于"frameworks/base/cmds/servicemanager\service_manager.c"文件中。

int main(int argc, char **argv)
{
    struct binder_state *bs;
    void *svcmgr = BINDER_SERVICE_MANAGER;

    bs = binder_open(128*1024);

    if (binder_become_context_manager(bs)) {
        LOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

    svcmgr_handle = svcmgr;
    binder_loop(bs, svcmgr_handler);
    return 0;
}

首先调用binder_open打开binder设备/dev/binder,参数mapsize指定了需要映射的内存大小,为什么要进行映射呢,什么地方会用到映射地址bs->mapped呢?

struct binder_state *binder_open(unsigned mapsize)
{       
    struct binder_state *bs;

    bs = malloc(sizeof(*bs));
    if (!bs) {
        errno = ENOMEM;
        return 0;
    }

    bs->fd = open("/dev/binder", O_RDWR);
    if (bs->fd < 0) {
        fprintf(stderr,"binder: cannot open device (%s)\n",
                strerror(errno));
        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;
    }

        /* TODO: check version */

    return bs;

fail_map:
    close(bs->fd);
fail_open:
    free(bs);
    return 0;
}

然后调用binder_become_context_manager使得它称为context manager,也就是Service manager,这个特殊的服务用来管理其他的所有服务。

int binder_become_context_manager(struct binder_state *bs)
{       
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}

Service Manager监听请求

Service Manager通过ioctl BINDER_SET_CONTEXT_MGR向Binder驱动声明自己是服务管理器,作为服务管理器有两个最重要的工作,接收其他server的服务注册; 为客户端提供查询和获取服务。因此Service最后会进入一个监听循环,等待用户的请求,并使用srcmgr_handler回调函数处理用户请求。

void binder_loop(struct binder_state *bs, binder_handler func)
{       
    int res;
    struct binder_write_read bwr;
    unsigned readbuf[32]; 
    
    bwr.write_size = 0;
    bwr.write_consumed = 0;
    bwr.write_buffer = 0;
 
    readbuf[0] = BC_ENTER_LOOPER;
    binder_write(bs, readbuf, sizeof(unsigned));

    for (;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (unsigned) readbuf;
        
        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);

        if (res < 0) {
            LOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
            break;
        }

        res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
        if (res == 0) {
            LOGE("binder_loop: unexpected reply?!\n");
            break;
        }
        if (res < 0) {
            LOGE("binder_loop: io error %d %s\n", res, strerror(errno));
            break;
        }
    }
}

在Service Manager能够服务Server和client的请求之前,要设置bind proc为 LOOPER_ENTER状态,然后调用ioctl BINDER_WRITE_READ等待来自Server和Client的请求,这个ioctl是个阻塞的操作,直到有请求进入,才会返回

binder_parse分析@readbuf中的请求,bwr.read_consumed是请求的长度,@func是请求处理函数


ServiceManager数据结构

 90 struct svcinfo
 91 {
 92     struct svcinfo *next;
 93     void *ptr;
 94     struct binder_death death;
 95     unsigned len;
 96     uint16_t name[0];
 97 };

每一个svcinfo代表一个注册的service

@next,所有的service通过next链接到全局变量svclist

@ptr,虽然从命名上是一个pointer,但是存储的是一个handle,一般来说从0x01开始,0x00保留给service manager自身。

@len,name的长度

@name,是service名字,client端要通过这个名字找到匹配的服务。


struct binder_io
{
    char *data;            /* pointer to read/write from */
    uint32_t *offs;        /* array of offsets */
    uint32_t data_avail;   /* bytes available in data buffer */
    uint32_t offs_avail;   /* entries available in offsets array */

    char *data0;           /* start of data buffer */
    uint32_t *offs0;       /* start of offsets buffer */
    uint32_t flags;
    uint32_t unused;
};

binder_io是用来生成binder message的辅助结构

@data 是当前可用buffer位置,这个地址随着加入数据,而改变

@offs 是当前可用的offset buffer位置,可以用来存放obj相对于@data0的偏移地址,4bytes

@data_avail 当前可用的data空间大小

@offs_avail 当前空用的offsets大小

@data0 data buffer的起始位置,data0记录着binder_io数据buffer的起始位置

@offs0 offset buffer的起始位置,offs0记录着binder_io offset buffer的起始位置

从@data0 ~ @data保存着对象,@offs0 ~ @offs保存着obj的偏移位置,这个偏移位置是obj地址相对于@data0的偏移位置




你可能感兴趣的:(Android Binder - Service Manager)