> 文档中心 > android中binder的初始化

android中binder的初始化

binder是android独有的一种IPC机制,它是在/system/bin/servicemanager进程(可以用ps看到)中完成初始化的它的父进程是init. 

1. 代码: 

     frameworks\base\cmds\servicemanager\这个目录下,有service_manager.cbinder.c。

 
(1) 在service_manager.c中,有main函数,代码如下:
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;
}

(2) binder_open:  位于binder.c中,binder_open函数实现如下: 
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;
}

2. 说明:
   (1) 在frameworks\base\cmds\servicemanager目录下的Android.mk中,指定生成的模块为servicemanager:
         LOCAL_MODULE := servicemanager //
   (2) dev/binder会映射到一块内存虚拟空间中,通过mmap系统调用来实现。
   (3) binder.c中还提供了一系列函数,用于支持binder的访问。
   (4) binder通信机制的实现中,是用ioctl的方式与内核进行交互的。

   (5) binder的初始化一定是在jvm的初始化之前,因为jvm初始化一直到上层的system_server的过程中,会有启动很多的service,这些service都会去用到binder

    (6) servicemanager这个进程的权限是system,这个通过ps也能看出来,它是在init.rc中指定的。

3. 补充:

  mmap的使用:

    #include  
 (1)   void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)  
    描述: 把文件或者设备映射到内存。这个函数在调用进程的虚拟地址空间中创建一块映射区域
     
    参数说明:
        addr: 指定映射区域的首地址, 如果addr是NULL,那么由内核来选择一个地址来创建映射的区域,否则创建的时候会尽可能地使用addr的地址。在linux系统中,创建映射的时候应该是在下一个页面的边界创建,addr是NULL的时候,程序的可移植性最好。
        length:指定映射区域的长度
        offset:指定从文件的哪个偏移位置开始映射,offset必须是页面大小的整数倍页面的大小可以由sysconf(_SC_PAGE_SIZE)来返回
        flags指定区域在不同进程之间的共享方式,以及区域是否同步到相应的文件等等
        fd: 文件描述符.在binder中,指的就是:bs->fd = open("/dev/binder", O_RDWR)

    返回值: 这个函数返回新创建的页面的地址。成功的时候这个函数返回0。   失败的时候,返回-1


  (2)  int munmap(void *addr, size_t length); 
    作用: munmap  取消address指定地址范围的映射。以后再引用取消的映射的时候就会导致非法内存的访问。这里address应该是页面的整数倍。 成功的时候这个函数返回0。   失败的时候,返回-1.