return -1;
}
selinux_enabled = is_selinux_enabled(); //selinux权限是否使能
sehandle = selinux_android_service_context_handle();
selinux_status_open(true);
if (selinux_enabled > 0) {
if (sehandle == NULL) {
abort(); //无法获取sehandle
}
if (getcon(&service_manager_context) != 0) {
abort(); //无法获取service_manager上下文
}
}
…
//进入无限循环,处理client端发来的请求
binder_loop(bs, svcmgr_handler);
return 0;
}
简单来说就是做了三件事:
- 打开binder驱动:binder_open;
- 注册成为binder服务的大管家:binder_become_context_manager;
- 进入无限循环,处理client端发来的请求:binder_loop;
首先看看binder_open方法:
打开驱动:binder_open
//frameworks/native/cmds/servicemanager/binder.c
struct binder_state *binder_open(size_t mapsize)
{
//定义一个binder_state结构体
struct binder_state *bs;
struct binder_version vers;
bs = malloc(sizeof(*bs));
if (!bs) {
errno = ENOMEM;
return NULL;
}
//通过系统调用陷入内核,打开Binder设备驱动
bs->fd = open(“/dev/binder”, O_RDWR);
if (bs->fd < 0) {
goto fail_open; // 无法打开binder设备
}
//通过系统调用,ioctl获取binder版本信息
if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
(vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
goto fail_open; //内核空间与用户空间的binder不是同一版本
}
bs->mapsize = mapsize;
//通过系统调用,mmap内存映射,mmap必须是page的整数倍
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
if (bs->mapped == MAP_FAILED) {
goto fail_map; // binder设备内存无法映射
}
return bs;
fail_map:
close(bs->fd);
fail_open:
free(bs);
return NULL;
}
首先是定义一个binder_state结构体,这个结构体用来存放binder驱动的文件描述符fd,指向mmap的内存地址和内存的大小:
struct binder_state
{
int fd; // dev/binder的文件描述符
void *mapped; //指向mmap的内存地址
size_t mapsize; //分配的内存大小,默认为128KB
};
j接着调用open()打开binder设备,open()方法经过系统调用,进入Binder驱动,然后调用方法binder_open(),该方法会在Binder驱动层创建一个binder_proc
对象,再将binder_