Android 8.0 启动ServiceManager
来源:互联网 发布:微屏软件 编辑:程序博客网 时间:2024/05/18 22:17
一、简述
framework/native/cmds/servicemanager/ - service_manager.c - binder.c kernel/drivers/ (不同Linux分支路径略有不同) - staging/android/binder.c - android/binder.c
ServiceManager是Binder IPC通信过程中的守护进程,本身也是一个Binder服务,但并没有采用libbinder中的多线程模型来与Binder驱动通信,而是自行编写了binder.c直接和Binder驱动来通信,并且只有一个循环binder_loop来进行读取和处理事务,这样的好处是简单而高效。
ServiceManager本身工作相对简单,其功能:查询和注册服务。 对于Binder IPC通信过程中,其实更多的情形是BpBinder和BBinder之间的通信,比如ActivityManagerProxy和ActivityManagerService之间的通信等。
流程
启动过程
ServiceManager是由init进程通过解析init.rc文件而创建的,其所对应的可执行程序/system/bin/servicemanager,所对应的源文件是service_manager.c,进程名为/system/bin/servicemanager。
service servicemanager /system/bin/servicemanager class core user system group system critical onrestart restart healthd onrestart restart zygote onrestart restart media onrestart restart surfaceflinger onrestart restart drm
启动Service Manager的入口函数是service_manager.c中的main()方法,代码如下:
main
[ -> service_manager.c]
int main(int argc, char **argv){ struct binder_state *bs; //打开binder驱动,申请128k字节大小的内存空间 bs = binder_open(128*1024); ... //成为上下文管理者 【见小节2.3】 if (binder_become_context_manager(bs)) { 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;}
二、核心工作
servicemanager的核心工作就是注册服务和查询服务
2.1 do_find_service
[-> service_manager.c]
uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid){ //查询相应的服务 struct svcinfo *si = find_svc(s, len); if (!si || !si->handle) { return 0; } if (!si->allow_isolated) { uid_t appid = uid % AID_USER; //检查该服务是否允许孤立于进程而单独存在 if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) { return 0; } } //服务是否满足查询条件 if (!svc_can_find(s, len, spid)) { return 0; } return si->handle;}
查询到目标服务,并返回该服务所对应的handle
2.1.1 find_svc
struct svcinfo *find_svc(const uint16_t *s16, size_t len){ struct svcinfo *si; for (si = svclist; si; si = si->next) { //当名字完全一致,则返回查询到的结果 if ((len == si->len) && !memcmp(s16, si->name, len * sizeof(uint16_t))) { return si; } } return NULL;}
从svclist服务列表中,根据服务名遍历查找是否已经注册。当服务已存在svclist
,则返回相应的服务名,否则返回NULL。
当找到服务的handle, 则调用bio_put_ref(reply, handle),将handle封装到reply.
2.2 do_add_service
[-> service_manager.c]
int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle, uid_t uid, int allow_isolated, pid_t spid){ struct svcinfo *si; if (!handle || (len == 0) || (len > 127)) return -1; //权限检查,>=AID_APP if (!svc_can_register(s, len, spid)) { return -1; } //服务检索 si = find_svc(s, len); if (si) { if (si->handle) { svcinfo_death(bs, si); //服务已注册时,释放相应的服务 } si->handle = handle; } else { si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t)); if (!si) { //内存不足,无法分配足够内存 return -1; } si->handle = handle; si->len = len; memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); //内存拷贝服务信息 si->name[len] = '\0'; si->death.func = (void*) svcinfo_death; si->death.ptr = si; si->allow_isolated = allow_isolated; si->next = svclist; // svclist保存所有已注册的服务 svclist = si; } //以BC_ACQUIRE命令,handle为目标的信息,通过ioctl发送给binder驱动 binder_acquire(bs, handle); //以BC_REQUEST_DEATH_NOTIFICATION命令的信息,通过ioctl发送给binder驱动,主要用于清理内存等收尾工作 binder_link_to_death(bs, handle, &si->death); return 0;}static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid){ const char *perm = "add"; if (multiuser_get_app_id(uid) >= AID_APP) { return 0; /* Don't allow apps to register services */ } return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;}
注册服务的分以下3部分工作:
- svc_can_register:检查权限,检查selinux权限是否满足;
- find_svc:服务检索,根据服务名来查询匹配的服务;
- svcinfo_death:释放服务,当查询到已存在同名的服务,则先清理该服务信息,再将当前的服务加入到服务列表svclist;
三. 总结
ServiceManger集中管理系统内的所有服务,通过权限控制进程是否有权注册服务,通过字符串名称来查找对应的Service;由于ServiceManger进程建立跟所有向其注册服务的死亡通知, 那么当服务所在进程死亡后, 会只需告知ServiceManager.每个Client通过查询ServiceManager可获取Server进程的情况,降低所有Client进程直接检测会导致负载过重。
ServiceManager启动流程:
- 打开binder驱动,并调用mmap()方法分配128k的内存映射空间:binder_open();
- 通知binder驱动使其成为守护进程:binder_become_context_manager();
- 验证selinux权限,判断进程是否有权注册或查看指定服务;
- 进入循环状态,等待Client端的请求:binder_loop()。
- 注册服务的过程,根据服务名称,但同一个服务已注册,重新注册前会先移除之前的注册信息;
- 死亡通知: 当binder所在进程死亡后,会调用binder_release方法,然后调用binder_node_release.这个过程便会发出死亡通知的回调.
ServiceManager最核心的两个功能为查询和注册服务:
- 注册服务:记录服务名和handle信息,保存到svclist列表;
- 查询服务:根据服务名查询相应的的handle信息。
四. 源码目录
从上之下, 整个Binder架构所涉及的总共有以下5个目录:
/framework/base/core/java/ (Java)/framework/base/core/jni/ (JNI)/framework/native/libs/binder (Native)/framework/native/cmds/servicemanager/ (Native)/kernel/drivers/staging/android (Driver)
4.1 Java framework
/framework/base/core/java/android/os/ - IInterface.java - IBinder.java - Parcel.java - IServiceManager.java - ServiceManager.java - ServiceManagerNative.java - Binder.java /framework/base/core/jni/ - android_os_Parcel.cpp - AndroidRuntime.cpp - android_util_Binder.cpp (核心类)
4.2 Native framework
/framework/native/libs/binder - IServiceManager.cpp - BpBinder.cpp - Binder.cpp - IPCThreadState.cpp (核心类) - ProcessState.cpp (核心类)/framework/native/include/binder/ - IServiceManager.h - IInterface.h/framework/native/cmds/servicemanager/ - service_manager.c - binder.c
4.3 Kernel
/kernel/drivers/staging/android/ - binder.c - uapi/binder.h
参考网址:
http://gityuan.com/2015/11/07/binder-start-sm/
- Android 8.0 启动ServiceManager
- Android ServiceManager启动
- android启动之ServiceManager启动
- android binder --- ServiceManager启动分析
- Android Framework学习(十三)之启动ServiceManager
- android binder机制---servicemanager进程启动
- Android源码(10) --- Binder(4) ServiceManager 启动
- android----ServiceManager
- Android 系统服务管家servicemanager启动过程详解
- Android Binder机制——ServiceManager的启动
- ServiceManager启动流程
- 【android】binder机制-servicemanager
- Android - Binder机制 - ServiceManager
- Android binder -serviceManager
- android binder 机制 (ServiceManager)
- 3.Android内核 ServiceManager
- android serviceManager使用
- android binder 机制 (ServiceManager)
- 微图App中如何切换在线地图
- SSL证书申请
- 恨铁不成钢 苹果Siri为何敌不过其它智能助理?
- 同时使用@IdClass @ManyToOne碰到的一个问题
- jdk--ClassLoader
- Android 8.0 启动ServiceManager
- 算法——递归算法
- resteasy 数据校验之Hibernate validation 国际化问题
- java.net.BindException: Address already in use: bind异常处理方法
- php作业01
- opencart 2.3全面伪静态
- 这里简单介绍一个自己写的检测某个进程是否存在的bash小脚本
- 深度学习和自然语言处理的应用和脉络1-基础
- mysql 导入数据库