Binder系列--ServiceManager的启动

这篇具有很好参考价值的文章主要介绍了Binder系列--ServiceManager的启动。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ServiceManager的启动
hongxi.zhu
Android 13

主要流程:
Binder系列--ServiceManager的启动,Android Framework,跨进程,binder,framework

1. 启动ServiceManager进程

ServiceManager是由init(pid = 1)进程启动的
system/core/rootdir/init.rc

on init
	...
	...
    # Start essential services.
    start servicemanager  //framework层使用
    start hwservicemanager  //hal层
    start vndservicemanager  //vendor内部

进程被创建后,进入main方法

2. 执行main方法

frameworks/native/cmds/servicemanager/main.cpp

int main(int argc, char** argv) {
	...
    const char* driver = argc == 2 ? argv[1] : "/dev/binder";

    sp<ProcessState> ps = ProcessState::initWithDriver(driver); //创建ProcessState对象(进程唯一),并进行open、ioctl、mmap操作
    ps->setThreadPoolMaxThreadCount(0);  //初始线程数实际为0
    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);

    sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());  //构造自己时构造Access对象,这个是用于权限检测
    //先注册自己作为服务
    if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
        LOG(ERROR) << "Could not self register servicemanager";
    }

    IPCThreadState::self()->setTheContextObject(manager); //保存ServiceManager作为BBinder对象到IPCThreadState实例中
    ps->becomeContextManager();  //向驱动注册自己成为全局唯一的ContextManager,全局只有一个ServiceManager

    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/); //获取一个Looper

    BinderCallback::setupTo(looper);  //将binder fd添加到Looper中监听,当驱动有事件时,回调handleEvent()处理
    ClientCallbackCallback::setupTo(looper, manager);  //这个是用于告知客户端当前服务端有多少个客户端绑定的回调监听

    while(true) {  //循环等待事件到来
        looper->pollAll(-1);  //阻塞等待event的到来,然后进行ioctl和驱动交互获取数据
    }

    // should not be reached
    return EXIT_FAILURE;
}
  1. 创建ProcessState对象,通过这个对象打开驱动节点,检验Binder版本和进行内存映射等操作,
  2. 设置线程池的初始大小为0,实际线程数并不是固定的,这个要根据实际任务决定是否新加线程到线程池(binder驱动中处理这个逻辑
  3. 然后创建ServiceManager对象,并通过addService添加自己到服务列表中。
  4. 保存ServiceManager作为BBinder对象到IPCThreadState实例中,并向Binder驱动注册自己成为全局唯一的ContextManager
  5. 然后创建Looper,通过Looper监听binder驱动的消息,当驱动有消息时回调handleEvent()处理(然后真正读数据是ioctl)
  6. 进入大循环阻塞等待事件到来

3. ProcessState::initWithDriver(driver)

frameworks/native/libs/binder/ProcessState.cpp

sp<ProcessState> ProcessState::initWithDriver(const char* driver)
{
    return init(driver, true /*requireDefault*/);
}

sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault)
{
	...
    [[clang::no_destroy]] static std::once_flag gProcessOnce;
    std::call_once(gProcessOnce, [&](){  //call_once单例模式确保每个进程只有一个ProcessState
        if (access(driver, R_OK) == -1) {  //测试下binder的节点是否可读
            ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
            driver = "/dev/binder";
        }
		...
        std::lock_guard<std::mutex> l(gProcessMutex);
        gProcess = sp<ProcessState>::make(driver);  //调用构造函数,构造ProcessState实例
    });
	...
    return gProcess;
}

#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)  //ServiceManager申请用于binder通信的虚拟内存大小也是 1MB-8KB
#define DEFAULT_MAX_BINDER_THREADS 15   //最大工作线程数 15 + 1(本身)
#define DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION 1  //开启异步垃圾通信检测
...
ProcessState::ProcessState(const char* driver)
      : mDriverName(String8(driver)),
        mDriverFD(-1),
        mVMStart(MAP_FAILED),
        mThreadCountLock(PTHREAD_MUTEX_INITIALIZER),
        mThreadCountDecrement(PTHREAD_COND_INITIALIZER),
        mExecutingThreadsCount(0),
        mWaitingForThreads(0),
        mMaxThreads(DEFAULT_MAX_BINDER_THREADS),
        mStarvationStartTimeMs(0),
        mForked(false),
        mThreadPoolStarted(false),
        mThreadPoolSeq(1),
        mCallRestriction(CallRestriction::NONE) {
    base::Result<int> opened = open_driver(driver);  //进行open、ioctl

    if (opened.ok()) {
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE,
                        opened.value(), 0);
        if (mVMStart == MAP_FAILED) {
            close(opened.value());
            // *sigh*
            opened = base::Error()
                    << "Using " << driver << " failed: unable to mmap transaction memory."; //内存不足
            mDriverName.clear();
        }
    }
	...
}

构造方法里做的最主要的两件事就是通过open_driver()mmap()

3.1 open_driver

static base::Result<int> open_driver(const char* driver) {
    int fd = open(driver, O_RDWR | O_CLOEXEC);  //通过open打开binder节点,获取binder设备驱动的fd
	...
    int vers = 0;
    status_t result = ioctl(fd, BINDER_VERSION, &vers);  //通过ioctl和binder驱动通信,查询binder驱动的binder版本,binder驱动的版本要和用户空间的binder协议的版本保持匹配,不然无法工作
	...
    size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;  //DEFAULT_MAX_BINDER_THREADS = 15
    result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);  //通过ioctl告知binder驱动,用户进程支持的最大binder工作线程数,默认是15+1 = 16个(加上本身)
	...
    uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
    result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);  //开启oneway方式垃圾请求攻击检测(类似于垃圾邮件攻击检测)
	...
    return fd;  //返回驱动的fd
}

open_driver主要做四件事:

  1. 通过系统调用open打开设备节点,获取设备驱动fd
  2. 通过系统调用ioctl获取驱动的binder版本
  3. 通过系统调用ioctl告知驱动用户进程支持的最大线程数,(默认是15+1,SystemServer进程默认是31+1)
  4. 通过系统调用ioctl设置垃圾oneway异步通信检测

3.2 mmap

		...
    if (opened.ok()) {
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE,
                        opened.value(), 0);  //BINDER_VM_SIZE = 1MB-8KB
        if (mVMStart == MAP_FAILED) {
            close(opened.value());
            // *sigh*
            opened = base::Error()
                    << "Using " << driver << " failed: unable to mmap transaction memory."; //内存不足(没有满足需求的连续内存)
            mDriverName.clear();
        }
    }
        ...

ProcessState构造函数接着会通过系统调用mmap将当前进程的一块虚拟内存(内核分配的虚拟地址,这个地址是进程地址空间的)映射到内核空间,这个系统调用最终实现是binder驱动中的binder_mmap(), binder驱动会在内核也申请一块空间(内核空间),并指向一块物理地址,注意这个仅仅用在这个进程作为服务端时,接收来自binder的消息,这个过程没有发生IO的拷贝。

4. setTheContextObject

void IPCThreadState::setTheContextObject(const sp<BBinder>& obj)
{
    the_context_object = obj;
}

保存ServiceManager作为BBinder对象到IPCThreadState实例中(这样处理其他进程获取SM时就不需要每次都创建BBinder的对象)

5. becomeContextManager

bool ProcessState::becomeContextManager()
{
    AutoMutex _l(mLock);

    flat_binder_object obj {
        .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
    };

    int result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj);  //注册自己成为ContextManager
	...
    return result == 0;
}

向驱动注册自己成为全局唯一的SM

6. BinderCallback::setupTo(looper)

class BinderCallback : public LooperCallback {  //继承于LooperCallback,当Looper通过epoll监听到对应fd有event时回调cb.handleEvent
public:
    static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
        sp<BinderCallback> cb = sp<BinderCallback>::make();   //创建BinderCallback对象

        int binder_fd = -1;
        IPCThreadState::self()->setupPolling(&binder_fd);
        LOG_ALWAYS_FATAL_IF(binder_fd < 0, "Failed to setupPolling: %d", binder_fd);

        int ret = looper->addFd(binder_fd,  //添加binder驱动的fd到Looper的监听fd
                                Looper::POLL_CALLBACK,
                                Looper::EVENT_INPUT,
                                cb,  //传递自己作为callback对象,有event就回调自己的handleEvent方法
                                nullptr /*data*/);
        LOG_ALWAYS_FATAL_IF(ret != 1, "Failed to add binder FD to Looper");

        return cb;
    }

    int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
        IPCThreadState::self()->handlePolledCommands();  //驱动有事件上报时,就去处理
        return 1;  // Continue receiving callbacks.
    }
};

将binder驱动的fd注册到Looper中监听,当驱动上报事件时回调handleEvent, 处理相关事务

6.1 setupPolling

status_t IPCThreadState::setupPolling(int* fd)
{
    if (mProcess->mDriverFD < 0) {
        return -EBADF;
    }

    mOut.writeInt32(BC_ENTER_LOOPER);
    flushCommands();
    *fd = mProcess->mDriverFD;
    return 0;
}

void IPCThreadState::flushCommands()
{
    if (mProcess->mDriverFD < 0)
        return;
    talkWithDriver(false);  //通过ioctl 通知驱动将当前线程加入Looper状态
	...
}

通过ioctl通知驱动将当前线程加入Looper状态文章来源地址https://www.toymoban.com/news/detail-523219.html

到了这里,关于Binder系列--ServiceManager的启动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android Framework——Binder 监控方案

    作者:低性能JsonCodec 在 Android 应用开发中,Binder 可以说是使用最为普遍的 IPC 机制了。我们考虑监控 Binder 这一 IPC 机制,一般是出于以下两个目的: 卡顿优化:IPC 流程完整链路较长,且依赖于其他进程,耗时不可控,而 Binder 调用本身通常又是以 RPC 形式对外提供能力的,

    2024年02月04日
    浏览(36)
  • [Android 13]Binder系列--获取服务

    获取服务 hongxi.zhu 2023-7-8 以 SurfaceFlinger 进程中获取 InputFlinger 服务为例 frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp 获取到SM的代理对象之前的文章已经分析过,请参考前面的:Binder系列–获取ServiceManager BpServiceManager::getService remote()从前面可知是SM的BpBinder对象,获取到SM的

    2024年02月13日
    浏览(54)
  • 【Android】Binder(一)Binder的介绍和AIDL使用Binder的实例

    Android 中的 Binder 是一个进程间通信机制,它允许不同进程之间相互调用方法和传递数据。Binder 主要用于实现系统服务和应用程序之间的通信,以及实现 IPC(Inter-Process Communication,进程间通信)。 Binder 的核心是 Binder 驱动程序,它负责管理不同进程之间的通信。每个进程都可

    2024年02月07日
    浏览(43)
  • Android 13(T) - binder阅读(1)- binder driver

    想要使用binder完成进程间通信(IPC)或者完成远程过程调用(RPC),那么我们需要有如下三个要素: 源:即调用者(Client) 目的:即服务提供者(Server)。这里会有一个问题,client怎么知道我要向哪里发送数据呢?这里就需要用到ServiceManager,Server需要先注册到ServiceManager中

    2024年02月11日
    浏览(35)
  • Android 13(T) - binder阅读(3)- binder相关的类

    原先准备在binder阅读(3)中记录ServiceManager的使用,但是写着写着发现,如果不了解和binder相关的类,那么阅读起来将会由很多困惑,所以就先来记录binder相关的类了。记录完发现特别凌乱…先就这样吧。 从 binder阅读(1)一开始的图中可以看到, getService 获得的是一个han

    2024年02月11日
    浏览(38)
  • Android 进阶——Binder IPC之Binder IPC架构及原理概述(九)

    前面几篇文章,为我们学习Binder IPC通信机制提供了扎实的理论基础,接下来将正式进入Binder IPC通信架构及原理的解读。 Binder 是基于 C/S 架构的,由一系列的组件组成,包括 Client进程、Server进程、Service Manager进程、Binder 驱动。其中 Client进程、Server进程、Service Manager进程运行

    2023年04月09日
    浏览(46)
  • Android Binder小结

    Binder是Android中一种跨进程通信方式,Binder也是一个虚拟设备,对于客户端来说Bidner是一个可以跨进程通信的一个类 Android底层是Linux,但是Linux已有的跨进程通信方式都不能满足Android移动设备的需求,在Android中跨进程通信方式,要求是CS的一对多的架构、需要保证安全,并且

    2023年04月08日
    浏览(41)
  • 【Android】深入Binder拦截

    ☞ Github ☜ ☞ Gitee ☜ Binder 作为 Android 系统跨进程通信的核心机制。网上也有很多深度讲解该机制的文章,如: Android跨进程通信详解Binder机制原理 Android系统核心机制Binder【系列】 这些文章和系统源码可以很好帮助我们理解Binder的实现原理和设计理念,为拦截做准备。借助

    2024年02月03日
    浏览(45)
  • Android Framework 之 ServiceManager

    ServiceManager 在 Android 系统中扮演了核心的角色。主要负责跨进程通信(IPC)的管理和服务的注册与查找。 管理系统服务 : ServiceManager 提供一个全局的服务注册表,用于存储所有的系统服务。一个服务一旦被注册到 ServiceManager,其他的进程就可以通过 **ServiceManager **来访问这

    2024年02月14日
    浏览(42)
  • 浅谈 Android Binder 监控方案

    在 Android 应用开发中,Binder 可以说是使用最为普遍的 IPC 机制了。我们考虑监控 Binder 这一 IPC 机制,一般是出于以下两个目的: 卡顿优化:IPC 流程完整链路较长,且依赖于其他进程,耗时不可控,而 Binder 调用本身通常又是以 RPC 形式对外提供能力的,使得我们在使用时更容

    2024年02月11日
    浏览(73)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包