news 2026/4/3 1:49:15

Android Binder详解【5】 ServiceManager

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Android Binder详解【5】 ServiceManager

Android 系统的 Binder 通信体系中,ServiceManager(简称 SM)是无可替代的核心枢纽 —— 它是所有 Binder 服务的 “注册表”,负责系统 / 应用服务的注册(addService)、查询(getService)、删除等核心操作。与普通 Android 服务不同,SM 的设计极度精简且特殊:摒弃了常规的 Binder 线程池,仅通过单线程 + Looper 的方式完成与 Binder 驱动的交互。本文将基于 Android 原生源码,深度解析 SM 的核心实现逻辑,并通过 SurfaceFlinger(SF)注册到 SM 的完整链路,直观展示 Binder 通信的全过程。

一、SM 的核心定位与设计特点

1. 核心定位

SM 是 Android 系统级的 “服务注册表”,所有想要通过 Binder 提供服务的组件(如 ActivityManagerService、WindowManagerService、SurfaceFlinger)都必须先向 SM 注册;而想要使用服务的客户端,也必须先通过 SM 查询到对应的服务 Binder 对象,才能发起跨进程调用。

2. 关键设计特点

  • 功能单一性:仅聚焦服务注册 / 查询 / 删除核心逻辑,无多余业务逻辑;
  • 无 Binder 线程池:普通 Android 服务通过 Binder 线程池处理多客户端请求,而 SM 仅用 1 个主线程;
  • Looper 驱动交互:直接监听 Binder 驱动的文件描述符(FD),通过 Looper 事件循环处理驱动命令;
  • Binder 上下文管理器:向 Binder 驱动声明自己是 “上下文管理器”,成为 Binder 通信的根节点。

二、SM 的启动流程(main.cpp 核心逻辑)

SM 的入口位于native\cmds\servicemanager\main.cpp,其启动流程是理解 SM 的关键,核心步骤如下:

int main(int argc, char** argv) { // 1. 初始化Binder驱动关联,禁用线程池 const char* driver = "/dev/binder"; sp<ProcessState> ps = ProcessState::initWithDriver(driver); ps->setThreadPoolMaxThreadCount(0); // 核心:禁用Binder线程池 ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY); // 2. 创建SM实例并自注册(将自己注册为"manager"服务) sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>()); if (!manager->addService("manager", manager, false, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) { LOG(ERROR) << "Could not self register servicemanager"; } // 3. 设置为Binder上下文管理器(SM专属标识) IPCThreadState::self()->setTheContextObject(manager); ps->becomeContextManager(); // 4. 初始化Looper,注册Binder驱动FD和定时器FD sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/); BinderCallback::setupTo(looper); // 注册Binder驱动FD ClientCallbackCallback::setupTo(looper, manager); // 注册定时器FD // 5. 进入Looper无限循环,监听并处理事件 while(true) { looper->pollAll(-1); } return EXIT_FAILURE; }

关键步骤解析

  1. 禁用 Binder 线程池setThreadPoolMaxThreadCount(0)通过ioctl告知 Binder 驱动,SM 不需要线程池,所有请求由主线程处理;
  2. 自注册:SM 将自身注册为名为 “manager” 的服务,确保其他组件能查询到 SM 本身;
  3. 成为上下文管理器becomeContextManager()通过ioctl(BINDER_SET_CONTEXT_MGR_EXT)向驱动声明身份,SM 的 Binder 句柄固定为 0,是 Binder 通信的根;
  4. Looper 事件循环:SM 的主线程通过looper->pollAll(-1)进入无限循环,等待 Binder 驱动或定时器的事件触发。

三、Binder 驱动事件处理:BinderCallback

SM 通过BinderCallback将 Binder 驱动的 FD 注册到 Looper,实现 “驱动有命令时主动回调” 的机制,核心代码如下:

class BinderCallback : public LooperCallback { public: static sp<BinderCallback> setupTo(const sp<Looper>& looper) { sp<BinderCallback> cb = sp<BinderCallback>::make(); // 1. 获取Binder驱动FD,并设置为轮询模式 int binder_fd = -1; IPCThreadState::self()->setupPolling(&binder_fd); // 2. 将FD注册到Looper,监听EVENT_INPUT(驱动有数据/命令时触发) int ret = looper->addFd(binder_fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb, nullptr); LOG_ALWAYS_FATAL_IF(ret != 1, "Failed to add binder FD to Looper"); return cb; } // 3. 驱动事件回调:处理Binder命令 int handleEvent(int /* fd */, int /* events */, void* /* data */) override { IPCThreadState::self()->handlePolledCommands(); // 核心:处理驱动命令 return 1; // 持续监听 } };
特殊逻辑:SM 的 Binder 调用路由

普通服务的 Binder 调用会通过tr.target.ptr找到对应的 BBinder,但 SM 作为上下文管理器,tr.target.ptr为 0,直接调用预先设置的the_context_object(即 SM 自身):

// IPCThreadState::executeCommand 中 BR_TRANSACTION 分支 if (tr.target.ptr) { // 普通服务:通过ptr找到BBinder error = reinterpret_cast<BBinder*>(tr.cookie)->transact(...); } else { // SM专属:直接调用上下文对象(SM)的transact error = the_context_object->transact(tr.code, buffer, &reply, tr.flags); }

四、客户端连接状态检测:ClientCallbackCallback

SM 通过 5 秒定时器周期性检测服务的客户端连接状态,核心功能由ClientCallbackCallback实现:

class ClientCallbackCallback : public LooperCallback { public: static sp<ClientCallbackCallback> setupTo(const sp<Looper>& looper, const sp<ServiceManager>& manager) { sp<ClientCallbackCallback> cb = sp<ClientCallbackCallback>::make(manager); // 1. 创建定时器FD(5秒周期) int fdTimer = timerfd_create(CLOCK_MONOTONIC, 0); itimerspec timespec { .it_interval = {5, 0}, // 周期:5秒 .it_value = {5, 0}, // 首次触发:5秒后 }; timerfd_settime(fdTimer, 0, &timespec, nullptr); // 2. 将定时器FD注册到Looper looper->addFd(fdTimer, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb, nullptr); return cb; } // 3. 定时器回调:检测客户端连接状态 int handleEvent(int fd, int /*events*/, void* /*data*/) override { uint64_t expirations; read(fd, &expirations, sizeof(expirations)); // 读取定时器事件 mManager->handleClientCallbacks(); // 核心:检测客户端连接状态 return 1; } };

核心作用

handleClientCallbacks()会遍历 SM 中注册的所有服务,检测每个服务的客户端连接是否活跃,若状态发生变化(如客户端断开),会主动通知服务端,保证服务能及时清理无效连接。

五、SM 的核心功能实现:AIDL 与 ServiceManager 类

SM 的核心功能(addService/getService 等)通过 AIDL 定义,并由ServiceManager类实现具体逻辑。

1. AIDL 生成的 BnServiceManager

IServiceManager.aidl经编译后生成BnServiceManager(服务端)和BpServiceManager(客户端),其中BnServiceManager负责将 Binder 命令转换为具体方法调用:

// BnServiceManager::onTransact 核心逻辑 status_t BnServiceManager::onTransact(uint32_t _aidl_code, const Parcel& _aidl_data, Parcel* _aidl_reply, uint32_t _aidl_flags) { switch (_aidl_code) { case TRANSACTION_getService: // getService命令 ::std::string in_name; _aidl_data.readUtf8FromUtf16(&in_name); // 调用SM的getService方法 binder::Status _aidl_status(getService(in_name, &_aidl_return)); _aidl_reply->writeStrongBinder(_aidl_return); // 返回服务Binder对象 break; case TRANSACTION_addService: // addService命令 // 同理:解析参数,调用addService方法 break; } return OK; }

2. 具体功能实现:ServiceManager 类

ServiceManager类是 SM 核心功能的真正执行者,继承自IServiceManager,实现了所有服务管理逻辑:

// ServiceManager::getService 核心实现 Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) { *outBinder = tryGetService(name, true); // 查询服务注册表,返回Binder对象 return Status::ok(); }

六、完整 Binder 链路实例:SurfaceFlinger 注册到 SM 的过程

为了更直观理解 SM 的工作机制,我们以SurfaceFlinger(SF)注册到 SM的完整流程为例,梳理从客户端发起请求到 SM 完成服务注册的全 Binder 链路,保留关键代码和文件路径:

步骤 1:SF 发起注册请求(客户端入口)

SurfaceFlinger 在启动时,会调用 SM 的addService方法将自身注册到 SM,

// main_surfaceflinger.cpp sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false, IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);

步骤 2:ServiceManagerShim 层封装(适配层)

请求先经过ServiceManagerShim做参数适配

// native\libs\binder\IServiceManager.cpp status_t ServiceManagerShim::addService(const String16& name, const sp<IBinder>& service, bool allowIsolated, int dumpsysPriority) { Status status = mTheRealServiceManager->addService( String8(name).c_str(), service, allowIsolated, dumpsysPriority); return status.exceptionCode(); }

步骤 3:BpServiceManager 发起 Binder 跨进程调用

AIDL 工具生成的BpServiceManager(客户端代理)会通过remote()->transact发起跨进程调用

BnServiceManager 和BpServiceManager 不是在framework 源码里的, 是aidl工具编译的时候生成的
frameworks\native\libs\binder\aidl\android\os\IServiceManager.aidl

// android/os/IServiceManager.cpp (AIDL工具生成) ::android::binder::Status BpServiceManager::addService(const ::std::string& name, const ::android::sp<::android::IBinder>& service, bool allowIsolated, int32_t dumpPriority) { _aidl_ret_status = remote()->transact(BnServiceManager::TRANSACTION_addService, _aidl_data, &_aidl_reply, 0); }

步骤 4:BpBinder 封装 Binder 调用参数

BpBinder作为客户端 Binder 代理的核心,会将调用参数封装并交给IPCThreadState处理,代码位于native\libs\binder\BpBinder.cpp

// native\libs\binder\BpBinder.cpp status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { // SM的Binder句柄固定为0,驱动会根据handle转发数据到SM进程 status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags); }

步骤 5:IPCThreadState 与 Binder 驱动交互

IPCThreadState负责将调用数据写入 Binder 驱动,并等待响应,代码位于native\libs\binder\IPCThreadState.cpp

// native\libs\binder\IPCThreadState.cpp status_t IPCThreadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr); waitForResponse(reply); } status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) { while (1) { if ((err=talkWithDriver()) < NO_ERROR) break; if (mIn.dataAvail() == 0) continue; cmd = (uint32_t)mIn.readInt32(); switch (cmd) { case BR_REPLY: // 接收SM的响应 { binder_transaction_data tr; err = mIn.read(&tr, sizeof(tr)); if (reply) { if ((tr.flags & TF_STATUS_CODE) == 0) { reply->ipcSetDataReference( reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(binder_size_t), freeBuffer); } } } } } status_t IPCThreadState::talkWithDriver(bool doReceive) { binder_write_read bwr; bwr.write_size = outAvail; bwr.write_buffer = (uintptr_t)mOut.data(); do { // 通过ioctl将数据写入Binder驱动 ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr); } while (err == -EINTR); }

步骤 6:Binder 驱动转发请求到 SM 进程

Binder 驱动接收到 SF 进程的BC_TRANSACTION命令后,根据 handle=0 识别出目标是 SM 进程,唤醒 SM 的主线程,并将请求数据转发给 SM。

步骤 7:SM 主线程处理 Binder 请求(Looper 回调)

SM 的主线程通过 Looper 监听 Binder 驱动 FD 的EVENT_INPUT事件,触发回调处理请求,代码位于native\cmds\servicemanager\main.cpp

// native\cmds\servicemanager\main.cpp int handleEvent(int /* fd */, int /* events */, void* /* data */) override { IPCThreadState::self()->handlePolledCommands(); // 处理驱动转发的请求 return 1; // 持续监听 }

步骤 8:SM 解析并执行 Binder 命令

SM 的IPCThreadState读取驱动数据并执行命令,最终调用 SM 自身的transact方法,代码位于native\libs\binder\IPCThreadState.cpp

// native\libs\binder\IPCThreadState.cpp status_t IPCThreadState::handlePolledCommands() { do { result = getAndExecuteCommand(); } while (mIn.dataPosition() < mIn.dataSize()); return result; } status_t IPCThreadState::getAndExecuteCommand() { talkWithDriver(); // 从Binder驱动读取SF的注册请求 cmd = mIn.readInt32(); result = executeCommand(cmd); // 执行ADD_SERVICE命令 } status_t IPCThreadState::executeCommand(int32_t cmd) { // 调用SM的BBinder处理ADD_SERVICE请求 the_context_object->transact(tr.code, buffer, &reply, tr.flags); }

步骤 9:BBinder 转发到 onTransact 方法

SM 的BBinder基类将请求转发到onTransact方法,代码位于native\libs\binder\Binder.cpp

// native\libs\binder\Binder.cpp status_t BBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { onTransact(code, data, reply, flags); // 转发到AIDL生成的onTransact }

步骤 10:AIDL 生成的 onTransact 解析参数

AIDL 工具生成的BnServiceManager::onTransact解析请求参数,并调用 SM 的addService方法,代码位于android/os/IServiceManager.cpp(AIDL 生成):

// android/os/IServiceManager.cpp (AIDL工具生成) BnServiceManager::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) { switch (_aidl_code) { case BnServiceManager::TRANSACTION_addService: android::binder::Status _aidl_status(addService(in_name, in_service, in_allowIsolated, in_dumpPriority)); _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply); break; } }

步骤 11:SM 完成 SF 服务注册(最终落地)

SM 的addService方法将 SurfaceFlinger 写入服务注册表(mNameToService),完成注册,代码位于native\cmds\servicemanager\ServiceManager.cpp

// native\cmds\servicemanager\ServiceManager.cpp Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) { // 覆盖已有服务(如果存在),将SF写入SM的服务注册表 mNameToService[name] = Service { .binder = binder, .allowIsolated = allowIsolated, .dumpPriority = dumpPriority, .debugPid = ctx.debugPid, }; return Status::ok(); }

七、总结

Android ServiceManager 作为 Binder 通信的核心枢纽,其设计和实现有以下关键特点:

  1. 极简的线程模型:摒弃 Binder 线程池,仅通过单线程 + Looper 监听 FD 事件,保证轻量和高效;
  2. Binder 上下文管理器:作为 Binder 通信的根节点,句柄固定为 0,所有服务查询 / 注册都从 SM 开始;
  3. 双 FD 监听机制:通过 Binder 驱动 FD 处理服务注册 / 查询命令,通过定时器 FD 检测客户端连接状态;
  4. AIDL 驱动的功能映射:基于 AIDL 生成的 Bn/BpServiceManager,将 Binder 命令转换为具体的服务管理操作;
  5. 完整的 Binder 链路:以 SurfaceFlinger 注册为例,客户端请求经 Binder 驱动转发到 SM,最终落地到服务注册表,形成闭环。

SM 的设计充分体现了 Android 系统 “核心组件极简、高效” 的原则,作为系统服务的 “注册表”,它的稳定性和高效性直接决定了整个 Android 系统 Binder 通信的正常运行。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/24 2:09:42

SAM分割实战:预装环境快速体验‘分割一切‘

SAM分割实战&#xff1a;预装环境快速体验分割一切 如果你是一名医疗影像研究员&#xff0c;想要测试SAM模型在CT图像分割中的应用&#xff0c;却苦于PyTorch版本兼容性问题&#xff0c;那么这篇文章正是为你准备的。本文将带你快速体验一个预装好所有依赖的Jupyter环境&#…

作者头像 李华
网站建设 2026/3/27 8:05:07

msvcp100.dll文件丢失 打不开应用软件 免费下载方法分享

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/4/1 1:55:02

AI如何帮你轻松实现CSS position: sticky效果

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个演示position: sticky效果的网页。要求&#xff1a;1) 顶部导航栏在滚动时固定在顶部&#xff1b;2) 侧边栏在滚动到特定位置时固定&#xff1b;3) 页脚在滚动到底部时固定…

作者头像 李华
网站建设 2026/4/1 0:21:21

msvcr100.dll文件缺失找不到 打不开程序问题 免费下载方法分享

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/4/2 18:25:48

告别复杂配置!Hunyuan-MT-7B-WEBUI网页推理功能详解

告别复杂配置&#xff01;Hunyuan-MT-7B-WEBUI网页推理功能详解 在今天这个信息爆炸、跨语言协作日益频繁的时代&#xff0c;谁能快速准确地“听懂”另一种语言&#xff0c;谁就掌握了沟通的主动权。无论是科研人员查阅外文文献&#xff0c;企业拓展海外市场&#xff0c;还是内…

作者头像 李华
网站建设 2026/3/31 7:06:13

Hunyuan-MT-7B-WEBUI为国际会议提供实时翻译支持

Hunyuan-MT-7B-WEBUI为国际会议提供实时翻译支持 在一场多国学者齐聚的国际学术会议上&#xff0c;一位藏族研究员用母语完成演讲后&#xff0c;现场大屏几乎同步显示出精准的英文字幕&#xff1b;会务组仅用几分钟就将上百页中文讲稿自动翻译成法语、阿拉伯语等多个版本。这一…

作者头像 李华