Android13-系统服务大管家-ServiceManager进程-启动篇

news/2025/2/8 11:46:07 标签: ServiceManager

文章目录

  • 关注 ServiceMager 原因
  • ServerManager需要掌握的知识
  • 资料参考
  • ServiceManager 进程启动
    • 启动脚本
    • Native层源码分析
      • main.cpp
      • 流程
      • 打开驱动 initWithDriver
        • init
        • make
        • ProcessState 构造方法
        • open_driver(driver)
      • 注册成Binder服务 addService
      • 注册成Binder服务 becomeContextManager
      • 轮询
      • 解析命令,执行命令
  • 总结


关注 ServiceMager 原因

  • 理解实现的原理

  • Framework层核心内容Service,绝绝大部分离不开ServiceManager的,framework层的各种Service
    都和ServiceManager打交道的。应用层调用系统Service也是和ServiceManager 关联的,

  • 方便后面理解各种Service源码

  • Binder 机制了解 怎么可能不去熟悉ServiceManager

ServerManager需要掌握的知识

资料参考

ServiceManager(Native)启动分析
系统服务大管家-ServiceManager
启动ServiceManager

ServiceManager__29">ServiceManager 进程启动

我们需要从两方面分析,Native层和framework层,本章我们作为 ServiceManager 源码的开篇,仅关注启动相关源码分析
为什么把ServiceManager 启动单独拿出来:方便分析,一步一个脚印理解。

启动脚本

涉及到的相关源码文件

为了方便理解,暂不用实际平台项目作为参考,直接用谷歌一套来check 源码的开篇,仅关注启动相关源码分析
部分路径和平台源码路径不一致很正常,在实际开发中以实际各个OEM厂商源码 位置为准。

在线源码XrefAndroid:
init.rc
servicemanager

/bootable/recovery/etc/init.rc 
/frameworks/native/cmds/servicemanager/servicemanager.rc

源码跟踪

ServiceManager_48">ServiceManager脚本启动位置

ServiceManager是在rc脚本中启动的:

/bootable/recovery/etc/init.rc 中

    # Start essential services
      start servicemanager
ServiceManager_57">ServiceManager关联脚本

servicemanager服务定义在frameworks\native\cmds\servicemanager\servicemanager.rc。
可以看到,servicemanger是一个Linux程序,它在设备中的存储路径是/system/bin/servicemanager,源码路径则是/frameworks/native/cmds/servicemanager。

在这里插入图片描述

 service servicemanager /system/bin/servicemanager
     class core animation   #表示这是一个核心服务,系统启动时优先运行
     user system            # 以 system 用户身份运 
     group system readproc
     critical               # 标记为关键服务,如果退出会触发系统重启
     onrestart restart apexd                             # 如果servicemanager重启 则 apexd也会重启
     onrestart restart audioserver                       # 如果servicemanager重启 则  audioserver
     onrestart restart gatekeeperd                       # 如果servicemanager重启 则  audioserver
     onrestart class_restart --only-enabled main          
     onrestart class_restart --only-enabled hal
     onrestart class_restart --only-enabled early_hal
     task_profiles ServiceCapacityLow
     shutdown critical 

简单介绍下这个文件脚本:
满足条件后执行程序 /system/bin/servicemanager,去Android 下面查看,果然有。
在这里插入图片描述

Native层源码分析

上面已经分析了servicemanager.rc 脚本了,我们看看该模块下的编译文件Android.bp
在这里插入图片描述

cc_binary {
name: "servicemanager",
defaults: ["servicemanager_defaults"],
init_rc: ["servicemanager.rc"],
srcs: ["main.cpp"],
}

这里就定位到了资源文件 main.cpp

main.cpp

     int main(int argc, char** argv) {
  #ifdef __ANDROID_RECOVERY__
      android::base::InitLogging(argv, android::base::KernelLogger);
  #endif

      if (argc > 2) {
          LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
      }

      const char* driver = argc == 2 ? argv[1] : "/dev/binder";  //检查输入参数,如果参数为空,则driver为"/dev/binder"

      sp<ProcessState> ps = ProcessState::initWithDriver(driver);   //创建ProcessState对象(进程唯一),并进行open、ioctl、mmap操作态
      ps->setThreadPoolMaxThreadCount(0);                 // 设置Binder线程池的最大线程数为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";
      }

      //保存ServiceManager作为BBinder对象到IPCThreadState实例中
      IPCThreadState::self()->setTheContextObject(manager);

      //向驱动注册自己成为全局唯一的ContextManager,全局只有一个ServiceManager
      ps->becomeContextManager();

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

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

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

      // should not be reached
      return EXIT_FAILURE;
  }

流程

上面的main方,可以分析Service启动流程的,我们先给出流程图,下一步一步一步分析说明
在这里插入图片描述

上面列举了main方法,给出了流程图,下面具体分析核心方法,具体在启动时候做了哪些动作

打开驱动 initWithDriver

initWithDriver

/frameworks/native/libs/binder/ProcessState.cpp

sp<ProcessState> ProcessState::initWithDriver(const char* driver)
 {
     return init(driver, true /*requireDefault*/);
 }
init
sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault)
   {
   
     ................
       std::call_once(gProcessOnce, [&](){
           if (access(driver, R_OK) == -1) {
               ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
               driver = "/dev/binder";
           }
   
           // we must install these before instantiating the gProcess object,
           // otherwise this would race with creating it, and there could be the
           // possibility of an invalid gProcess object forked by another thread
           // before these are installed
           int ret = pthread_atfork(ProcessState::onFork, ProcessState::parentPostFork,
                                    ProcessState::childPostFork);
           LOG_ALWAYS_FATAL_IF(ret != 0, "pthread_atfork error %s", strerror(ret));
   
           std::lock_guard<std::mutex> l(gProcessMutex);
           gProcess = sp<ProcessState>::make(driver);
       });
   ......
       verifyNotForked(gProcess->mForked);
       return gProcess;
   }

这里注意核心 内容 方法 make, 就是通过智能指针创建了ProcessState对象,走一遍构造方法。
Sp 关联的强指针-若指针参考

make

先看下make 方法位置和定义,在StrongPointer.h 里面
StrongPointer.h

// TODO: Ideally we should find a way to increment the reference count before running the
 // constructor, so that generating an sp<> to this in the constructor is no longer dangerous.
 template <typename T>
 template <typename... Args>
 sp<T> sp<T>::make(Args&&... args) {
     T* t = new T(std::forward<Args>(args)...);
     sp<T> result;
     result.m_ptr = t;
     t->incStrong(t);  // bypass check_not_on_stack for heap allocation
     return result;
 }

所以 m sp::make(driver) 回去执行 ProcessState 构造方法

ProcessState 构造方法
   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);
   
       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();
           }
       }
   
   #ifdef __ANDROID__
       LOG_ALWAYS_FATAL_IF(!opened.ok(), "Binder driver '%s' could not be opened. Terminating: %s",
                           driver, opened.error().message().c_str());
   #endif
   
       if (opened.ok()) {
           mDriverFD = opened.value();
       }
   }
open_driver(driver)

这里不就是打开驱动的逻辑嘛

 static base::Result<int> open_driver(const char* driver) {
       int fd = open(driver, O_RDWR | O_CLOEXEC);
       if (fd < 0) {
           return base::ErrnoError() << "Opening '" << driver << "' failed";
       }
       int vers = 0;
       status_t result = ioctl(fd, BINDER_VERSION, &vers);
       if (result == -1) {
           close(fd);
           return base::ErrnoError() << "Binder ioctl to obtain version failed";
       }
       if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
           close(fd);
           return base::Error() << "Binder driver protocol(" << vers
                                << ") does not match user space protocol("
                                << BINDER_CURRENT_PROTOCOL_VERSION
                                << ")! ioctl() return value: " << result;
       }
       size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
       result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
       if (result == -1) {
           ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
       }
       uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
       result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
       if (result == -1) {
           ALOGE_IF(ProcessState::isDriverFeatureEnabled(
                        ProcessState::DriverFeature::ONEWAY_SPAM_DETECTION),
                    "Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
       }
       return fd;
   }

在打开驱动时候进行了 ioctl 控制操作

注册成Binder服务 addService

ServiceManager.cpp

ServiceManager这个服务保存中mNameToService中,回调服务onRegistration()​方法。其实ServiceManager也是一个服务,用来管理其他服务,在其他服务启动注册前就已经就绪了。

 Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
      auto ctx = mAccess->getCallingContext();
  
      if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
          return Status::fromExceptionCode(Status::EX_SECURITY, "App UIDs cannot add services");
      }
  
      if (!mAccess->canAdd(ctx, name)) {
          return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denial");
      }
  
      if (binder == nullptr) {
          return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Null binder");
      }
  
      if (!isValidServiceName(name)) {
          LOG(ERROR) << "Invalid service name: " << name;
          return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Invalid service name");
      }
  
  #ifndef VENDORSERVICEMANAGER
      if (!meetsDeclarationRequirements(binder, name)) {
          // already logged
          return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "VINTF declaration error");
      }
  #endif  // !VENDORSERVICEMANAGER
  
      // implicitly unlinked when the binder is removed
      if (binder->remoteBinder() != nullptr &&
          binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
          LOG(ERROR) << "Could not linkToDeath when adding " << name;
          return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "linkToDeath failure");
      }
  
      // Overwrite the old service if it exists
      mNameToService[name] = Service {
          .binder = binder,
          .allowIsolated = allowIsolated,
          .dumpPriority = dumpPriority,
          .debugPid = ctx.debugPid,
      };
  
      auto it = mNameToRegistrationCallback.find(name);
      if (it != mNameToRegistrationCallback.end()) {
          for (const sp<IServiceCallback>& cb : it->second) {
              mNameToService[name].guaranteeClient = true;
              // permission checked in registerForNotifications
              cb->onRegistration(name, binder);
          }
      }
  
      return Status::ok();
  }

注册成Binder服务 becomeContextManager

其实就是通过ioctl 给系统发送了一条指令 BINDER_SET_CONTEXT_MGR_EXT,驱动被认定这个进程是ServiceManager.
android binder驱动层-BINDER_SET_CONTEXT_MGR_EXT

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);
      // fallback to original method
      if (result != 0) {
          android_errorWriteLog(0x534e4554, "121035042");
          int unused = 0;
          result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &unused);
      }
      if (result == -1) {
          ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
      }
      return result == 0;
  }

轮询

开启了死循环,通过Looper不停的pull,回调给相应的LooperCallback

 sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);

BinderCallback::setupTo(looper);
ClientCallbackCallback::setupTo(looper, manager);

while(true) {
    looper->pollAll(-1);
}



setupTo 方法:轮询读取命令
static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
      sp<BinderCallback> cb = sp<BinderCallback>::make();

      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,
                              Looper::POLL_CALLBACK,
                              Looper::EVENT_INPUT,
                              cb,
                              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.
      }
  };

解析命令,执行命令

上面轮训中看到 处理指令 handleEvent,最终回调方法是handlePolledCommands

status_t IPCThreadState::handlePolledCommands()
 {
     status_t result;
     do {
         result = getAndExecuteCommand();
     } while (mIn.dataPosition() < mIn.dataSize());
     processPendingDerefs();
     flushCommands();
     return result;
 }

总结

  • 了解ServiceManager 进程的启动,脚本和Native基本知识
  • 通过ServiceManager 的启动,为后续ServieManager的注册、获取、Binder和Service的交互打一个小基础

http://www.niftyadmin.cn/n/5844825.html

相关文章

CentOS 7配置samba服务设置文件共享

CentOS 7配置samba服务设置文件共享 一、生成另一个Linux系统&#xff0c;名为Linux-client&#xff0c;作为测试系统。 [rootliunx-client ~]# hostnamectl set-hostname Liunx-client二、如果没有则安装Samba服务&#xff0c;如果已经安装则省略此步。 yum install samba…

基于微信小程序的绘画学习平台的设计与开发

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

【MySQL】第二弹---数据库基础全解析:从概念到实践的深度探索

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【MySQL】 目录 1. 数据库基础 1.1 什么是数据库 1.2 主流数据库 1.3 基本使用 1.3.1 MySQL安装 1.3.2 连接服务器 1.3.3 服务器…

C++,设计模式,【单例模式】

文章目录 一、模式定义与核心价值二、模式结构解析三、关键实现技术演进1. 基础版(非线程安全)2. 线程安全版(双重检查锁)3. 现代C++实现(C++11起)四、实战案例:全局日志管理器五、模式优缺点深度分析✅ 核心优势⚠️ 潜在缺陷六、典型应用场景七、高级实现技巧1. 模板化…

ReactNative进阶(五十九):存量 react-native 项目适配 HarmonyOS NEXT

文章目录 一、前言二、ohos_react_native2.1 Fabric2.2 TurboModule2.2.1 ArkTSTurboModule2.2.2 cxxTurboModule&#xff1a; 三、拓展阅读 一、前言 2024年10月22日19:00&#xff0c;华为在深圳举办“原生鸿蒙之夜暨华为全场景新品发布会”&#xff0c;主题为“星河璀璨&…

58页PPT学习华为面向业务价值的数据治理实践

目录 1. 正文解读... 1 2. 华为数据质量管控的质量度量框架是怎样的?... 2 3. 如何在企业中实施类似华为的数据质量管控

Baumer工业相机堡盟相机的相机传感器芯片清洁指南

Baumer工业相机堡盟相机的相机传感器芯片清洁指南 Baumer工业相机1.Baumer工业相机传感器芯片清洁工具和清洁剂2.Baumer工业相机传感器芯片清洁步骤2.1、准备步骤2.2、清洁过程1.定位清洁工具2.清洁传感器3&#xff0e;使用吹风装置 Baumer工业相机传感器芯片清洁的优势设计与结…

树莓派5添加摄像头 在C++下调用opencv

由于树莓派5 os系统升级,正常libcamera创建对象每次失败。 改如下方法成功。 1 创建管道 rpicam-vid -t 0 --codec mjpeg -o udp://127.0.0.1:8554 > /dev/null 2>&1 2 opencv从管道里读取 #include <opencv2/opencv.hpp> #include <iostream>int mai…