云计算百科
云计算领域专业知识百科平台

Android 15 ServiceManager与Binder服务注册深度解析

引言

在上一篇文章中,我们深入分析了Binder驱动的内核机制。但是有一个核心问题还没有回答:Client如何知道Server的Binder句柄?

想象一下,你想打电话给朋友,但你不知道他的电话号码。这时你需要查电话簿(Yellow Pages)。在Android系统中,ServiceManager就是这本\”电话簿\”——它维护了系统中所有服务的注册表,提供服务的注册和查询功能。

没有ServiceManager,Binder IPC就无法工作。所有的系统服务(如ActivityManagerService、WindowManagerService)都需要先向ServiceManager注册,客户端才能通过ServiceManager查询到它们的Binder句柄,进而进行跨进程调用。

本文将深入Android 15源码,剖析ServiceManager的工作机制:

你将学到:

  • ServiceManager的启动流程与特殊性
  • 服务注册(addService)的完整实现
  • 服务查询(getService)的查找机制
  • 死亡通知(DeathRecipient)的工作原理
  • VINTF声明验证与安全机制
  • Android 15的新特性与优化

ServiceManager的特殊性

在深入代码前,我们先理解ServiceManager的几个特殊之处。

1. Handle 0:ServiceManager的唯一标识

在Binder系统中,ServiceManager有一个硬编码的句柄值:0。

// ProcessState.cpp
enum {


CONTEXT_MGR_HANDLE = 0 // ServiceManager的句柄固定为0
};

这是一个\”先有鸡还是先有蛋\”的问题:

  • 所有服务都需要向ServiceManager注册
  • 但客户端如何获取ServiceManager的句柄?

解决方案:将ServiceManager的句柄硬编码为0。这样,所有进程都知道,要与ServiceManager通信,只需要使用handle=0。

💡 设计巧思: Handle 0是Binder协议的特殊约定,在Binder驱动初始化时就预留了这个位置给ServiceManager。这是一个优雅的引导机制(Bootstrap)。

2. Context Manager:成为Binder上下文管理者

ServiceManager不仅仅是一个普通服务,它还是Binder上下文管理者(Context Manager)。

// main.cpp (Android 15)
int main(int argc, char** argv) {


const char* driver = argc == 2 ? argv[1] : \”/dev/binder\”;

sp<ProcessState> ps = ProcessState::initWithDriver(driver);

sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());

// 关键步骤1:将自己设置为Context Object
IPCThreadState::self()->setTheContextObject(manager);

// 关键步骤2:向驱动注册为Context Manager
if (!ps->becomeContextManager()) {


LOG(FATAL) << \”Could not become context manager\”;
}

// 进入消息循环
sp<Looper> looper = Looper::prepare(false);
while(true) {


looper->pollAll(1);
}
}

becomeContextManager做了什么?

// ProcessState.cpp
bool ProcessState::becomeContextManager() {


// 通过ioctl告诉驱动:\”我是ServiceManager\”
flat_binder_object obj{


.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS,
};

binder_write_read bwr{

};
binder_transaction_data tr{

};
tr.target.handle = 0;
tr.code = BINDER_SET_CONTEXT_MGR;

// 驱动会将handle 0绑定到当前进程
int result = ioctl(mDriverFD, BINDER_WRITE_READ, &bwr);
return result == 0;
}

驱动收到BINDER_SET_CONTEXT_MGR命令后,会:

  • 检查调用进程是否有权限(需要root或system权限)
  • 将handle 0永久绑定到ServiceManager进程
  • 确保只有一个进程能成为Context Manager
  • 3. 单例且唯一

    整个Android系统中,只能有一个ServiceManager实例。它由init进程在系统启动早期启动,并一直运行直到系统关闭。

    # init.rc中的ServiceManager启动配置
    service servicemanager /system/bin/servicemanager
    class core animation
    user system
    group system readproc
    critical
    onrestart restart apexd
    onrestart restart audioserver
    # …重启时需要重启依赖的服务

    critical标志:ServiceManager被标记为关键服务,如果它崩溃,系统会自动重启进入恢复模式。

    ServiceManager架构概览

    在深入启动流程前,先看看ServiceManager的整体架构:

    在这里插入图片描述

    图1: ServiceManager架构 – SystemServer注册服务,Client查询服务,ServiceManager维护服务注册表

    ServiceManager启动流程

    让我们跟踪ServiceManager从启动到就绪的完整流程。

    1. main函数:初始化与准备

    // main.cpp (Android 15)
    int main(int argc, char** argv) {


    // 1. 初始化日志
    android::base::InitLogging(argv, android::base::KernelLogger);

    const char* driver = argc == 2 ? argv[1] : \”/dev/binder\”;

    #if !defined(VENDORSERVICEMANAGER)
    android::register_perfetto_te_categories(); // Perfetto追踪
    #endif

    LOG(INFO) << \”Starting sm instance on \” << driver;

    // 2. 初始化ProcessState
    sp<ProcessState> ps = ProcessState::initWithDriver(driver);
    ps->setThreadPoolMaxThreadCount(0); // 不使用线程池,单线程处理
    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);

    // 3. 禁用后台调度,确保高优先级
    IPCThreadState::self()->disableBackgroundScheduling(true);

    // 4. 创建ServiceManager实例
    sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());

    // 5. 自己也要注册为服务(服务的服务)
    if (!manager->addService(\”manager\”, manager,
    false /*allowIsolated*/,
    IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {


    LOG(ERROR) << \”Could not self register servicemanager\”;
    }

    // 6. 成为Context Manager
    IPCThreadState::self()->setTheContextObject(manager);
    if (!ps->becomeContextManager()) {


    LOG(FATAL) << \”Could not become context manager\”;
    }

    // 7. 设置事件循环
    sp<Looper> looper = Looper::prepare(false);

    sp<BinderCallback> binderCallback = BinderCallback::setupTo(looper);
    ClientCallbackCallback::setupTo(looper, manager, binderCallback);

    // 8. 设置ready属性,通知其他进程可以使用了
    #ifndef VENDORSERVICEMANAGER
    if (!SetProperty(\”servicemanager.ready\”, \”true\”)) {


    LOG(ERROR) << \”Failed to set servicemanager ready property\”;
    }
    #endif

    // 9. 进入消息循环,永不退出
    while(true) {


    looper->pollAll(1); // 阻塞等待Binder事务
    }

    return EXIT_FAILURE; // 不应该到达这里
    }

    关键点解析:

  • 单线程模式:setThreadPoolMaxThreadCount(0)表示不使用Binder线程池,只用主线程处理,简化并发控制
  • 只接受单向调用:FATAL_IF_NOT_ONEWAY确保所有对ServiceManager的调用都是异步的,防止死锁
  • 高优先级:disableBackgroundScheduling(true)确保ServiceManager不会被降优先级
  • 自我注册:ServiceManager也将自己注册为名为\”manager\”的服务,供特殊情况使用
  • Ready属性:通过系统属性通知其他等待的进程
  • 2. Looper事件循环

    ServiceManager使用Looper而不是传统的Binder线程池:

    // BinderCallback:处理Binder事件
    class BinderCallback : public LooperCallback {


    public:
    static sp<BinderCallback> setupTo(const sp<Looper>& looper) {


    sp<BinderCallback> cb = sp<BinderCallback>::make

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Android 15 ServiceManager与Binder服务注册深度解析
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!