图解ServiceManager的启动过程

Android ServiceManager进阶 ServiceManager,直通 阅读详情

概述

笔者阅读了很多博客和相关书籍,自己也浏览了Android8.1系统源代码中关于ServiceManager的部分,有些书中称ServiceManager为Binder机制中的DNS服务器,负责某Binder服务在ServiceManager注册时提供的名称到底层Binder驱动分配的值的解析,我觉得这么理解倒也很贴切,在笔者整理关于ServiceManager的这篇博客时,发现想绕过Binder机制来单独来分析ServiceManager不太现实,而将Binder和ServiceManager合并一起来分析,篇幅过长,因此,笔者还是觉得先从最基本的开始,由简入深,逐个击破。

ServiceManager的启动

之前的博客已经大致分析了Android系统的启动过长,也大致了解了启动过程,今天的主角是ServiceManager,ServiceManager分为framework层和native层,我们这里要说的native层的ServiceManager,它在system/core/rootdir/init.rc脚本中描述并由init进程启动。

下面是关于init.rc脚本中,关于servicemanager启动的描述:

on post-fs
	......
    load_system_props
    # start essential services
    start logd
    //启动servicemanager
    start servicemanager
    start hwservicemanager
    start vndservicemanager

这里对应frameworks/native/cmds/servicemanager.rc描述脚本

service servicemanager /system/bin/servicemanager
    class core animation
    user system
    group system readproc
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart audioserver
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart inputflinger
    onrestart restart drm
    onrestart restart cameraserver
    writepid /dev/cpuset/system-background/tasks
    shutdown critical

在学习源码的过程中,笔者强烈建议大家用画图的形式来理解这些模块的实现机制,这里笔者综合一些优秀的博文和一些书籍(文章结尾参考)以及笔者阅读Android8.1系统源代码相关的模块整理出的一张启动流程图

你一定很疑惑,上面那张图里面为什么会有两个binder.c的源代码,这里要说明的是native层的那个binder.c源代码在frameworks/native/cmds/servicemanager这个目录

它的实现如下:

struct binder_state *binder_open(const char* driver, size_t mapsize)
{
    ......
    bs->fd = open(driver, O_RDWR | O_CLOEXEC);
    ......
    if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
        ......
    }
    bs->mapsize = mapsize;
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
    ......
    return NULL;
}

以binder_open为例,它实际是对用户空间open,mmap,ioctl等操作的封装,用户态的程序调用内核层驱动需要陷入内核态,进行系统调用Syscall,比如打开Binder驱动方法的调用链为:open-> __open() -> binder_open()。 open()为用户空间的方法,__open()便是系统调用中相应的处理方法,通过查找,对应调用到内核binder驱动的binder_open()方法,其他的从用户态陷入内核态的流程也基本一致,而内核层的那个binder.c源代码则对应goldfish/drivers/staging/android/binder.c,它会通过copy_from_user和copy_to_user函数和用户空间以共享内存的方式进行数据交换

启动过程分析

下面是native层的源代码frameworks/native/cmds/servicemanager/service_manager.c中比较关键的几个函数,servicemanager进程启动之后会从main函数执行:

int main(int argc, char** argv)
{
    struct binder_state *bs;
    union selinux_callback cb;
    char *driver;

    if (argc > 1) {
        driver = argv[1];
    } else {
        driver = "/dev/binder";
    }
    //打开/dev/binder驱动,映射区块大小为128K
    bs = binder_open(driver, 128*1024);

    ......

    //有些书上说是将自己注册成`Binder机制`的管家,当然你也可以这么理解
    if (binder_become_context_manager(bs)) {
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

    ......

    //进入循环等待客户进程的请求
    binder_loop(bs, svcmgr_handler);

    return 0;
}

基于事件驱动的消息循环模型:

void binder_loop(struct binder_state *bs, binder_handler func)
{
    ......

    binder_write(bs, readbuf, sizeof(uint32_t));

    for (;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;

        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);

        if (res < 0) {
            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
            break;
        }

        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);

        ......
    }
}

下面这个函数,是我们在binder_loop循环里,经过binder_parse处理后,最终回调的一个函数:

int svcmgr_handler(struct binder_state *bs,
                   struct binder_transaction_data *txn,
                   struct binder_io *msg,
                   struct binder_io *reply)
{
    ......
    switch(txn->code) {
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        //遍历内部链表,获取目标Server对象的句柄
        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
        if (!handle)
            break;
        bio_put_ref(reply, handle);
        return 0;

    case SVC_MGR_ADD_SERVICE:
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        handle = bio_get_ref(msg);
        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
        //添加具体的服务
        if (do_add_service(bs, s, len, handle, txn->sender_euid,
            allow_isolated, txn->sender_pid))
            return -1;
        break;

    case SVC_MGR_LIST_SERVICES: {
        uint32_t n = bio_get_uint32(msg);

        if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
            ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
                    txn->sender_euid);
            return -1;
        }
        si = svclist;
        while ((n-- > 0) && si)
            si = si->next;
        if (si) {
            bio_put_string16(reply, si->name);
            return 0;
        }
        return -1;
    }
    default:
        ALOGE("unknown code %d\n", txn->code);
        return -1;
    }

    bio_put_uint32(reply, 0);
    return 0;
}

struct svcinfo
{
    struct svcinfo *next;
    uint32_t handle;
    struct binder_death death;
    int allow_isolated;
    size_t len;
    uint16_t name[0];
};

struct svcinfo *svclist = NULL;

有了上述的代码块,看到了do_add_service,do_find_service,svcinfo等相关关键字,这些是干什么的呢?你可以按照你对进程间通信等的理解,猜猜看,这些操作实现的具体作用?

其实在servicemanager内部维护着一个svclist链表,用于存储所有Server相关信息,查询和注册都是基于这个数据结构展开的
当函数svcmgr_handler处理完成之后,binder_parse会进一步通过binder_send_reply来将执行结果返回给底层的Binder驱动,进而传递给客户端进程
接着binder_parse会进入下一轮的循环

由上面的过程我们基本可以归纳出,servicemanager的启动过程由三个步骤组成:

1. 通过binder_open()打开设备文件/dev/binder,以及将它映射到本进程的地址空间;
2. 通过binder_become_context_manager()将自己注册为Binder进程间通信机制的上下文管理者;
3. 通过binder_loop()来循环等待并通过binder_parse()处理Client进程的通信请求。

小结

当然了,关于ServiceManager和Binder通信机制远比想象的要复杂,后续笔者会基于进程间通信有更详细的博客来逐步分析。

参考

https://blog.youkuaiyun.com/freekiteyu/article/details/70082302
《Android系统源代码情景分析》
《深入理解android内核设计思想 第2版》

servicemanger的前世今生--Android 12 前边好几节介绍了Java层的SystemService类、ServiceManager类、SystemServiceManager类,以及SystemServer类中启动三大类服务的解析,我们知道启动系统服务时有的会调用SystemServiceManager.startService()或者ServiceManager.addService(),两者除了参数要求不一致外,都最终会调用IServiceManager.addService()中。 阅读详情

相关推荐

Binder系列(1)——ServiceManager

1. 概述 在一台Android 8.1的手机中,能看到三个servicemanager: servicemanager,管理系统服务,本文只讨论servicemanager; vndservicemanager,管理厂商服务,对应的文件节点是/dev/vndbinder,servicemanager和vndservicemanager使用的是同一份代码,都是由service_manager.c...

Burning Water 1169

HwServiceManager篇-Android10.0 HwBinder通信原理(五)

1.概述 HwServiceManager是HAL服务管理中心,负责管理系统中的所有HAL服务,由init进程启动。 HwServiceManager 的主要工作就是收集各个硬件服务,当有进程需要服务时由HwServiceManager 提供特定的硬件服务。 2.HwBinder架构 HwBinder通信原理: 3.hwservicemanager的启动 在init.rc中,当init进程启动后,会去启动servicemanager、hwservicemanager、vn...

转载和创作优秀的博客 4083

Android Framework--开机启动流程

Android启动流程boot引导启动–&amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;kernel启动–&amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;Android核心启动(init–&amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;runtime-&amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;zygote–&amp;amp;amp;am

瑜艾 1214

安卓进阶七:图解binder(2)-ServiceManager启动过程

这是学习罗升阳大佬的《安卓系统源代码情景分析》的笔记和总结。 图1 ServiceManager如何成为守护进程的详细代码 图2ServiceManager被Server唤醒后的详细代码 图3 ServiceManager的代码结构、流程的总结,方便整体把握 图1 图2 图3 ...

我的安卓之路 263

内核工作FAST‘25 Artifact Evaluation流程记录

在我们的paper中,复现需要用到傲腾持久化内存,因此,需要AE Reviewer访问到内网服务器中。我们的思路是购买云服务器,将其作为跳板机,内网服务器通过SSH反向代理与公网服务器建立隧道,AE Reviewer通过隧道访问内网服务器。我们在AE过程中使用。然后,把一切复现需要的代码环境,在chroot里面配置完成。

不定期更新系统使用、编程小技巧,哔哩哔哩账号:https://space.bilibili.com/399455629,欢迎关注 1215

立创EDA手动拼板实战:当自带功能不够用,如何用‘复制粘贴’搞定异形拼版与特殊布局

本文详细介绍了立创EDA手动拼板技术在异形拼版与特殊布局中的应用实战。通过CTRL+SHIFT+V等核心操作技巧,解决混合尺寸拼板、特殊间距需求等复杂场景,提升PCB设计效率与灵活性,特别适合需要高精度控制的射频电路和医疗设备项目。

weixin_31967485的博客 385

android 作为服务端_3分钟图解 Android 进程间通讯(看不懂算我输)

码个蛋(codeegg)第 772次推文作者: Master原文:https://mp.weixin.qq.com/s/lRLFzASMwEPKvLTWPiCzdQ概述最近在学习 Binder 机制,在网上查阅了大量的资料,也看了老罗的 Binder 系列的博客和 Innost 的深入理解 Binder 系列的博客,都是从底层开始讲的,全是 C 代码,虽然之前学过 C 和 C++,然...

weixin_33694136的博客 303

解决ArcGIS-OpenStreetMap Toolbox-Load OSM File错误

在安装成功OpenStreetMap Toolbox后,首次运行Load OSM File工具,出现以下错误

Zjf的博客 8820

android jni 结构体_3分钟图解 Android 进程间通讯(看不懂算我输)

码个蛋(codeegg)第 772次推文作者: Master原文:https://mp.weixin.qq.com/s/lRLFzASMwEPKvLTWPiCzdQ概述最近在学习 Binder 机制,在网上查阅了大量的资料,也看了老罗的 Binder 系列的博客和 Innost 的深入理解 Binder 系列的博客,都是从底层开始讲的,全是 C 代码,虽然之前学过 C 和 C++,然...

weixin_39689819的博客 270

Golang实战:用Quic-Go v0.46.0搭建高性能文件传输服务(附完整代码)

本文详细介绍了如何使用Golang和Quic-Go v0.46.0构建高性能文件传输服务,涵盖服务端和客户端的完整实现。通过QUIC协议的多路复用、零RTT连接等特性,显著提升文件传输效率,特别适合高延迟或不稳定网络环境。文章提供完整代码示例和性能调优技巧,帮助开发者快速部署高效的文件传输解决方案。

weixin_33737134的博客 447

手把手教你学Simulink--基于新能源与储能系统的场景实例:压缩空气储能(CAES)系统热力学建模

本文介绍了使用Simulink进行压缩空气储能(CAES)系统热力学建模的详细步骤。系统模型包含压缩机、储气装置、膨胀机、热交换器和控制器等核心模块,通过MATLAB函数计算各部件参数,并设置仿真条件。文章详细说明了从模型创建到性能评估的完整流程,包括压缩/膨胀过程的能量转换、温度压力变化等关键指标分析。该建模方法可验证设计方案的有效性,并为系统优化提供参考,适用于新能源与储能领域的研究与应用。

MHD0815的博客 9172

一篇文章了解相见恨晚的 Android Binder 进程间通讯(1)

考虑到文章的篇幅问题,我把这些问题和答案以及我多年面试所遇到的问题和一些面试资料做成了PDF文档《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!试所遇到的问题和一些面试资料做成了PDF文档[外链图片转存中…(img-pOgRUles-1712861360782)][外链图片转存中…(img-jbjKKrtR-1712861360782)]《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

2401_84149570的博客 614

【docker】--- 详解 WSL2 中的 Ubuntu 和 Docker Desktop 的区别和关系!

在编程的艺术世界里,代码和灵感需要寻找到最佳的交融点,才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里,我们将共同追寻这种完美结合,为未来的世界留下属于我们的独特印记。

秋知叶i 1314

一篇文章了解相见恨晚的 Android Binder 进程间通讯机制

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

wurensen的专栏 407

D19: OpenClaw 安全性配置指南

在 OpenClaw 的 30 天探索旅程中,我们已经探讨了邮件自动化(D18)。今天进入安全专题,我将分享一个至关重要的话题:OpenClaw 安全性配置指南。 随着 OpenClaw 深入工作流核心,它掌握了越来越多的敏感信息: API Keys(GitHub、飞书、Notion、Jira...) 企业数据(代码库、文档、聊天记录) 个人数据(日历、邮件、任务) 系统权限(文件读写、命令执行、网络访问) 安全不是可选项,而是必选项。一次配置失误可能导致: API Key 泄露 → 账号被盗用权限

刘一说的IT专栏 203

PCL点云处理之计算点到空间直线距离的四种方法(二十三)

PCL点云处理之计算点到空间直线距离的四种方法

weixin_44329757的博客 3020

Android启动init,Zygote,systemServer,ServiceManager,app

材料引用blog:http://gityuan.com/ App主要是具体的UI业务需求. AMS则是管理系统四大组件以及进程管理,尤其是Activity的各种栈以及状态切换等管理; WMS则是管理Activiy所相应的窗口系统(系统窗口以及嵌套的子窗口); SurfaceFlinger则是将应用UI绘制到frameBuffer(帧缓冲区),最终由硬件完成渲染到屏幕上 交互 App跟AMS通信,会建立Session连接到WMS,后续便通过IWindowSesson跟WMS通信; WMS跟SF通信,.

fdsafwagdagadg6576的专栏 1818

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

图解Android系统的启动过程

Android系统是基于Linux的,启动必须经历3个阶段,即:Boot Loader,Linux Kernel,Android系统服务,笔者今天就基于Android 8.1 系统源代码来分析一下启动过程。

handy周 1081

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Android内核开发:图解Android系统的启动过程

Android内核开发:图解Android系统的启动过程 2015-06-07 20:36:07 标签:Android 内核 启动 分析 图解 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://ticktick.blog.51cto.com/823160/1659473 本文是《Android内核开

lqxandroid2012的专栏 506

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

安卓进阶七:图解binder(3)-Server启动及被ServiceManager唤醒之后

这是学习罗升阳《安卓系统源代码情景分析》的笔记和总结。 图1 Server启动过程及被ServiceManager唤醒后详细代码 图2 代码的架构和流程的总结,方便整体把握 图1 图2 ...

我的安卓之路 278

详细图解 Android vndBinder

详细图解 Android vndBinder 注意:本文基于 Android 8.1 进行分析 Qidi 2020.07.03 (Markdown & Haroopad) 【前言】 图虽然是根据 vndBinder 的类关系和调用顺序画出的,但实际上对于 Binder 和 hwBinder 也适用。 Binder driver 代码十分庞杂,基于安全考虑还存在与 LSM 的交互,所以这部分的调用关系图有所省略。 【Binder 通信概要】 如果说 Binder 通信机制是 Android 的心脏

一程山水一程歌 1589

[Android] Android启动过程图解

Android手机开机执行过程图:   从开机到桌面的过程为: Bootloader ➪Kernel ➪Init进程 ➪ Zygote ➪ SystemServer ➪ ServiceManager ➪ Home Launcher   Android服务包括系统服务和应用服务,系统服务是指Android系统在启动过程就已经启动实现了的服务,对于系统服务又分为Java服务和本

grace的专栏 536
上一篇: 图解Android系统的启动过程
下一篇: Android中Service的启动过程时序图
handy周
handy周 领域专家: 操作系统技术领域 领域专家: 操作系统技术领域
博客等级 码龄14年 507粉丝 240原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值