binder是android独有的一种IPC机制,它是在/system/bin/servicemanager进程(可以用ps看到)中完成初始化的,它的父进程是init.
1. 代码:
frameworks\base\cmds\servicemanager\,这个目录下,有service_manager.c,binder.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 <sys/mman.h>(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。
作用: munmap 取消address指定地址范围的映射。以后再引用取消的映射的时候就会导致非法内存的访问。这里address应该是页面的整数倍。 成功的时候这个函数返回0。 失败的时候,返回-1.。