You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
android-notes/blogs/Android/Framework/Interview/系统服务相关/ServiceManager 的启动和工作原理.md

5.6 KiB

ServiceManager 的启动和工作原理
  1. ServiceManager 启动流程是怎样的?
  2. 怎么获取 ServiceManager 的 binder 对象?
  3. 怎么向 ServiceManager 添加服务?
  4. 怎么从 ServiceManager 获取服务?

ServiceManager 的启动

  1. 启动进程
  2. 启用 binder 机制
  3. 发布自己的服务
  4. 等待并响应请求
启动进程
service servicemanager /system/bin/servicemanager
clas core
user system
group system
critical
//...
int main(int argc, char **argv) {
	struct binder_status *bs;
    // 1.打开 binder 驱动
	bs = binder_open(128*1024);
    // 2.把自己注册为上下文管理者
	binder_become_context_manager(bs);
    // 3.进入 loop 循环,不断等待请求、处理请求
	binder_loop(bs, svcmgr_handler);
	return 0;
}
struct binder_status *binder_open(size_t, mapsize) {
	struct binder_state *bs;
	bs = malloc(sizeof(*bs));
    // 1.打开 binder 驱动,返回一个 fd
	bs->fd = open("/dev/binder", O_RDWR);
	bs->mapsize = mapsize;
    // 2.给 fd 映射一块内存,128 kb
	bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
	return bs;
}
// 注册成上下文,其实就是告诉 binder 驱动,ServiceManager 已经就绪了
int binder_become_context_manager(struct binder_state *bs) {
	return ioctl(bs->fd, BINDER_SET_CONTEXT_MSR, 0);
}

binder_loop 分为两个阶段,第一阶段主要是注册为 binder 线程:

void binder_loop(struct binder_state *bs, binder_handler func) {
	uint32_t readbuf[32];
    // 把当前线程注册为 binder 线程,也就是告诉 binder 驱动,当前线程可以处理 binder 请求的
    readbuf[0] = BC_ENTER_LOOPER;
    binder_write(bs, readbuf, sizeof(uint32_t));
    //...
}
int binder_write(struct binder_state *bs, void *data, size_t len) {
    // BINDER_WRITE_READ 表示可读可写
    // write_size > 0 执行写
    // read_size > 0 执行读
    // write_size > 0 && read_size > 0,先写再读
	struct binder_write_read bwr;
	bwr.write_size = len;
    bwr.write_consumed = 0;
    bwr.write_buffer = (uintptr_t) data;
    bwr.read_size = 0;
    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    return res;
}

第二阶段,就是读请求处理请求了:

void binder_loop(struct binder_state *bs, binder_handler func) {
    struct binder_write_read bwr;
    //...
    bwr.write_size = 0;
    for(;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_buffer = (unitptr_t) readbuf;
        ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
        // 解析请求,并在回掉函数 func 处理请求
        binder_parse(bs, 0, (uintptr_t)readbuf, bwr.read_consumed, func);
    }
}

如何获取 ServiceManager?

以 SurfaceFlinger 为例:

sp<IServiceManager> defaultServiceManager() {
	if(gDefaultServiceManager != null) {
		return gDefaultServiceManager;
	}
	while(gDefaultServiceManager == null) {
		gDefaultServiceManager = getContextObject();
		if(gDefaultServiceManager==null) sleep(1);
	}
}
sp<IBinder> ProcessState::getContextObject(...) {
    // 返回 ServiceManager 的 Proxy 对象,注意 handler 值为 0
	return getStrongProxyForHandle(0);
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) {
	// 以 binder handle 值作为索引,获取数组里面对应的 handle_entry
    handle_entry* e = loopupHandleLocked(handle);
	IBinder* b = e->binder;
	if(b == NULL) {
        // ServiceManager 的 Proxy 对象就是 BpBinder(0);
		b = new BpBinder(handle);
		e->binder = b;
	}
	return b;
}

怎么向 ServiceManager 添加服务?

// 添加服务,Service 名称和 Service Binder 对象
status_t addService(const String16& name, const sp<IBinder>& service, ...) {
	//...
    // 通过 remote 函数获取 BpBinder 对象,然后调用 BpBinder 的 transact 函数
	remote() -> transact(ADD_SERVICE_TRANSACTION, data, &reply);
}
status_t BpBinder::transact(unit32_t code, const Parcel& data, Parcel* reply, ...) {
    // IPCThreadState 线程单例,直接跟 binder 驱动交互
	IPCThreadState::self()->transact(mHandle, code, data, ...);
}

在 ServiceManager 收到请求之后,如何处理?

int svcmgr_handler(..., struct binder_transaction_data *txn, ...) {
	switch(txn->code) {
		//...
		case SVC_MSR_ADD_SERVICE:
            // 注册到 ServiceManage 的虽然传递的是 binder 实体对象
            // 但是真正 ServiceManager 收到的只是一个 handle 值
            // ServiceManager 会根据 handle 值还有 binder 相关信息封装成一个数据结构插入到单链表里
            do_add_service(bs, s, len, handle, ...);
            break;
	}
}

怎么从 ServiceManager 获取服务?

关于怎么获取服务呢,和注册服务差不多,都需要向 ServiceManager 发起一个 binder 调用。

public static IBinder getService(String name) {
	IBinder service = sCache.get(name);
	if(service != null) {
		return service;
	}else {
        // 获取 ServiceManager 的 binder 对象,然后调用它的 getService 函数
		return getIServiceManager().getService(name);
	}
	return null;
}

ServiceManager 在收到请求之后,是如何处理的呢?

int svcmgr_handler(..., struct binder_transaction_data *txn, ...) {
	uint32_t handle;
	switch(txn->code) {
		case SVC_MGR_GET_SERVICE:
            // 拿到服务的名称
			s = bio_get_string16(msg, &len);
            // 找到对应服务的 handle 值
			handle = do_find_service(bs, s, len, ...);
            // 返回 handle 值,Client 端再根据 handle 值封装一个 BpBinder 就行了
			bio_put_ref(reply, handle);
			return 0;
	}
}