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

211 lines
5.6 KiB

---
ServiceManager 的启动和工作原理
---
1. ServiceManager 启动流程是怎样的?
2. 怎么获取 ServiceManager 的 binder 对象?
3. 怎么向 ServiceManager 添加服务?
4. 怎么从 ServiceManager 获取服务?
#### ServiceManager 的启动
1. 启动进程
2. 启用 binder 机制
3. 发布自己的服务
4. 等待并响应请求
##### 启动进程
```ini
service servicemanager /system/bin/servicemanager
clas core
user system
group system
critical
//...
```
```c
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;
}
```
```c
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;
}
```
```c
// 注册成上下文,其实就是告诉 binder 驱动,ServiceManager 已经就绪了
int binder_become_context_manager(struct binder_state *bs) {
return ioctl(bs->fd, BINDER_SET_CONTEXT_MSR, 0);
}
```
binder_loop 分为两个阶段,第一阶段主要是注册为 binder 线程:
```c
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));
//...
}
```
```c
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;
}
```
第二阶段,就是读请求处理请求了:
```c
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 为例:
```c
sp<IServiceManager> defaultServiceManager() {
if(gDefaultServiceManager != null) {
return gDefaultServiceManager;
}
while(gDefaultServiceManager == null) {
gDefaultServiceManager = getContextObject();
if(gDefaultServiceManager==null) sleep(1);
}
}
```
```c
sp<IBinder> ProcessState::getContextObject(...) {
// 返回 ServiceManager 的 Proxy 对象,注意 handler 值为 0
return getStrongProxyForHandle(0);
}
```
```c
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 添加服务?
```c
// 添加服务,Service 名称和 Service Binder 对象
status_t addService(const String16& name, const sp<IBinder>& service, ...) {
//...
// 通过 remote 函数获取 BpBinder 对象,然后调用 BpBinder 的 transact 函数
remote() -> transact(ADD_SERVICE_TRANSACTION, data, &reply);
}
```
```c
status_t BpBinder::transact(unit32_t code, const Parcel& data, Parcel* reply, ...) {
// IPCThreadState 线程单例,直接跟 binder 驱动交互
IPCThreadState::self()->transact(mHandle, code, data, ...);
}
```
在 ServiceManager 收到请求之后,如何处理?
```c
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 调用。
```java
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 在收到请求之后,是如何处理的呢?
```c
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;
}
}
```