首页 > 系统相关 >android系统启动流程- ServiceManager进程启动流程

android系统启动流程- ServiceManager进程启动流程

时间:2024-07-14 18:29:28浏览次数:10  
标签:系统启动 流程 driver binder system servicemanager init fd ServiceManager

*注:基于Android11源码

ServiceManager进程是在init进程创建的,所以我们从init进程的main()开始分析:

// 文件路径: system/core/init/main.cpp
 
int main(int argc, char** argv) {
 
    ...
     if (!strcmp(argv[1], "second_stage")) {  //TODO  根据条件会走到这个分支
            return SecondStageMain(argc, argv);
     }
 
}
 
 
int SecondStageMain(int argc, char** argv) {
 
   ...
   //用来存放解析出的内容
   ActionManager& am = ActionManager::GetInstance();
   ServiceList& sm = ServiceList::GetInstance();
   //在这个方法中会对 /system/core/rootdir/init.rc 脚本文件文件进行解析
   LoadBootScripts(am, sm);
 
   //循环处理init.rc脚本中的command命令,处理完就进入等待
    while (true) {
         if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) 
         {
            //内部遍历执行每个action中携带的command对应的执行函数
			am.ExecuteOneCommand();
         }
    }
}
 
 
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
    //创建解析器
	Parser parser = CreateParser(action_manager, service_list);
 
    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
		//解析init.rc ,这个是手机设备上的路径,和源码中system/core/init/init.rc是一个文件
        parser.ParseConfig("/system/etc/init/hw/init.rc");
        if (!parser.ParseConfig("/system/etc/init")) {
            late_import_paths.emplace_back("/system/etc/init");
        }
        // late_import is available only in Q and earlier release. As we don't
        // have system_ext in those versions, skip late_import for system_ext.
        parser.ParseConfig("/system_ext/etc/init");
        if (!parser.ParseConfig("/product/etc/init")) {
            late_import_paths.emplace_back("/product/etc/init");
        }
        if (!parser.ParseConfig("/odm/etc/init")) {
            late_import_paths.emplace_back("/odm/etc/init");
        }
        if (!parser.ParseConfig("/vendor/etc/init")) {
            late_import_paths.emplace_back("/vendor/etc/init");
        }
    } else {
        parser.ParseConfig(bootscript);
    }
}

下面是init.rc中启动servicemanager进程相关的部分:

on init
    # Start essential services.
    start servicemanager  #启动servicemanager进程
    start hwservicemanager
    start vndservicemanager

有关servicemanager进程启动的细节配置被放在了 frameworks\native\cmds\servicemanager\servicemanager.rc

#此脚本文件描述了启动servicemanager进程时的一些细节
#service用于通知init进程创建名为servicemanager的进程,这个进程执行程序的路径是/system/bin/servicemanager
#在手机系统中是能找到这个文件的
service servicemanager /system/bin/servicemanager
    class core animation
    #表明此进程是以system身份运行的
    user system
    group system readproc
    #说明servicemanager是系统中的关键服务,关键服务是不会退出的,若退出系统则会重启,系统重启则会重启
    #以下onrestart修饰的进程,也可以说明这些进程是依赖于servicemanager进程的
    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
    onrestart restart keystore
    onrestart restart gatekeeperd
    onrestart restart thermalservice
    writepid /dev/cpuset/system-background/tasks
    shutdown critical

当执行到 start servicemanager 这条命令,就会运行android设备(比如手机)中 /system/bin/servicemanager这个可执行文件,而这个可执行程序就是servicemanager进程,他由 frameworks\native\cmds\servicemanager\main.cpp 文件编译生成的。什么?你不信?打开frameworks\native\cmds\servicemanager\Android.bp,这就是证据:

...
# cc_binary表示编译成一个二进制文件
cc_binary {
    name: "servicemanager", #文件名
    defaults: ["servicemanager_defaults"],
    init_rc: ["servicemanager.rc"],  #配置详情
    srcs: ["main.cpp"],   #要编译的源文件
}
 
...

这样我们就知道运行servicemanager这个可执行文件就是运行到了frameworks\native\cmds\servicemanager\main.cpp这个文件了。

int main(int argc, char** argv) {
    if (argc > 2) {
        LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
    }
 
    //此时要使用的binder驱动为 "/dev/binder",同样这个路径也是android设备上的路径
    const char* driver = argc == 2 ? argv[1] : "/dev/binder";
    //打开binder驱动文件并将此进程与binder驱动进行内存映射,ProcessState是用来保存进程状态的一个类
    sp<ProcessState> ps = ProcessState::initWithDriver(driver); //注释1
    //设置最大线程数
    ps->setThreadPoolMaxThreadCount(0);
    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
    //实例化ServiceManager
    sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
    //将自身作为服务添加
	if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
        LOG(ERROR) << "Could not self register servicemanager";
    }
    //创建服务端Bbinder对象
    IPCThreadState::self()->setTheContextObject(manager); //注释2
	//设置称为binder驱动的context manager,称为上下文的管理者
    ps->becomeContextManager(nullptr, nullptr);
    //通过Looper epoll机制处理binder事务
    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
    //Binder驱动中数据变化的监听
    BinderCallback::setupTo(looper); //注释3
    ClientCallbackCallback::setupTo(looper, manager); 
 
    while(true) { 
        looper->pollAll(-1);
    }
 
    // should not be reached
    return EXIT_FAILURE;
}

先看注释1:

//frameworks\native\libs\binder\ProcessState.cpp
 
 
sp<ProcessState> ProcessState::initWithDriver(const char* driver)
{
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != nullptr) {
        // Allow for initWithDriver to be called repeatedly with the same
        // driver. 允许使用同一驱动程序重复调用initWithDriver()
        if (!strcmp(gProcess->getDriverName().c_str(), driver)) {//若当前ProcessState对象的驱动与传参不同
            return gProcess;  //直接返回现有的ProcessState对象
        }
        LOG_ALWAYS_FATAL("ProcessState was already initialized.");
    }
 
    if (access(driver, R_OK) == -1) {
        ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
        driver = "/dev/binder";
    }
 
    //第一次调用gProcess为空,走这里
    gProcess = new ProcessState(driver); //创建新对象
    return gProcess;
}
 
//ProcessState类的构造函数
ProcessState::ProcessState(const char *driver)
    : mDriverName(String8(driver))  //以下都是成员变量初始化赋值,设置驱动名
    , mDriverFD(open_driver(driver)) //打开驱动文件,拿到驱动文件的文件描述符
    , mVMStart(MAP_FAILED)
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
    , mStarvationStartTimeMs(0)
    , mBinderContextCheckFunc(nullptr)
    , mBinderContextUserData(nullptr)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
    , mCallRestriction(CallRestriction::NONE)
{
 
    if (mDriverFD >= 0) { //大于0,说明打开binder驱动成功
        // mmap内存映射,提供一块虚拟地址空间来接收事务(即从客户端发送的请求(数据))。
        // BINDER_VM_SIZE 地址空间大小BINDER_VM_SIZE = 1M - 8k
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {//映射失败
            // *sigh*
            ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
            close(mDriverFD);
            mDriverFD = -1;
            mDriverName.clear();
        }
    }
    ...
}
 
 
static int open_driver(const char *driver)
{
    //得到驱动的文件描述符
    int fd = open(driver, O_RDWR | O_CLOEXEC);
    if (fd >= 0) {
        int vers = 0;
		//binder驱动版本检查
        status_t result = ioctl(fd, BINDER_VERSION, &vers);
        if (result == -1) {
            ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
            close(fd);
            fd = -1;
        }
        if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
          ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
                vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
            close(fd);
            fd = -1;
        }
        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));
        }
    } else {
        ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
    }
    return fd;
}
 

接下来到注释2部分:

//	frameworks\native\libs\binder\IPCThreadState.cpp
 
//IPCThreadState是线程单例
IPCThreadState* IPCThreadState::self()
{
    //不是初次调用的情况,TLS的全称为Thread Local Storage
    if (gHaveTLS.load(std::memory_order_acquire)) {
restart:
	    //初次调用,生成线程私有变量key后
	    //TLS 表示线程本地存储空间,和java中的ThreadLocal是一个意思
        const pthread_key_t k = gTLS;
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
        if (st) return st;
		//没有的话就实例化一个
        return new IPCThreadState;
    }
 
    // Racey, heuristic test for simultaneous shutdown.
    // IPCThreadState shutdown后不能再获取
    if (gShutdown.load(std::memory_order_relaxed)) {
        ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
        return nullptr;
    }
 
    // 首次获取时gHaveTLS为false,会先走这里
    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS.load(std::memory_order_relaxed)) {
		//创建一个key,作为存放线程本地变量的key
        int key_create_value = pthread_key_create(&gTLS, threadDestructor);
        if (key_create_value != 0) {
            pthread_mutex_unlock(&gTLSMutex);
            ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
                    strerror(key_create_value));
            return nullptr;
        }
		//创建完毕,gHaveTLS设置为true
        gHaveTLS.store(true, std::memory_order_release);
    }
    pthread_mutex_unlock(&gTLSMutex);
	// 回到gHaveTLS为true的case
    goto restart;
}
 
 
 
sp<BBinder> the_context_object;
 
void IPCThreadState::setTheContextObject(sp<BBinder> obj)
{   
    //赋值给一个BBinder类型的成员变量,即传进来的这个manager就是服务端的BBinder
    the_context_object = obj;
}
 
 

为了更好的理解ServiceManager这个类,下面是一张它的继承关系图:

image

下面来到注释3:

static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
        sp<BinderCallback> cb = new BinderCallback;
 
        int binder_fd = -1;
		//向binder驱动发送BC_ENTER_LOOPER事务请求,并获得binder驱动的文件描述符
        IPCThreadState::self()->setupPolling(&binder_fd);
        LOG_ALWAYS_FATAL_IF(binder_fd < 0, "Failed to setupPolling: %d", binder_fd);
 
        // Flush after setupPolling(), to make sure the binder driver
        // knows about this thread handling commands.
        // 检查写缓存是否有可写数据,有的话发给binder驱动
        IPCThreadState::self()->flushCommands();
 
        // 监听binder文件描述符
        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;
    }
 
    // 当binder驱动发来消息后,就可以通过次函数接收处理了
    int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
        //处理消息
		IPCThreadState::self()->handlePolledCommands();
        return 1;  // Continue receiving callbacks.
    }
};

servicemanager进程启动过程中,主要做了以下四件事:

1)初始化binder驱动

2)将自身以“manager” 添加到servicemanager中的map集合中

3)注册成为binder驱动的上下问管理者

  1. 给Looper设置callback,进入无限循环,处理client端发来的请求

总结:

1.ServiceManager是一个独立的进程,由init进程创建,且在创建zygote进程之前被创建。

2.IBinder是什么?它是实现了AIDL接口的实体类,它实现了接口中的所有方法。

标签:系统启动,流程,driver,binder,system,servicemanager,init,fd,ServiceManager
From: https://www.cnblogs.com/linhaostudy/p/18301854

相关文章

  • T113-i系统启动速度优化方案
    背景:        硬件:T113-i+emmc        软件:uboot2018+linux5.4+QT应用        分支:longan问题:        全志T113-i的官方系统软件编译出的固件,开机启动时间10多秒,启动时间太长,远远超过行业内linux系统的开机速度,需要进一步优化。T1......
  • 公司产品上云流程规范
    关于公司产品上云流程规范,可以考虑如下几个方面:1.产品架构设计:详细说明产品在云环境中的组件,以及各组件之间的关系,并给出需要考虑的技术难题。2.资源申请:详细说明云资源的申请、配置和管理流程,并给出云资源的使用标准。3.软件部署:详细说明软件的部署流程,并给出软件的部署要求。......
  • Linux可执行程序启动流程
    进程是如何启动的?进程启动过程示例代码#include<stdio.h>intmain(){printf("hello,world\r\n");return0;}启动两个终端,使用strace命令跟踪进程启动过程strace-f-s655000-i-T-ooutput.txt-p19510各个选项参考strace的man手册-f跟......
  • 阳澄湖礼券怎样兑换实物:了解阳澄湖礼券兑换实物的流程与注意事项,享受购物优惠
    ①:了解礼券信息:有效期:确认礼券的有效期,避免过期失效。使用范围:了解可以使用礼券的商家或兑换地点。面值和数量:确认礼券的面值和数量,以便兑换时使用。②:选择商品或服务:查看产品目录:在指定商家或网站上查看可以使用礼券兑换的商品或服务目录。③:兑换流程:到店......
  • Spring的启动流程refresh方法、配置类解析流程@Component、@Configuration、@Import、
    Spring的启动流程概述:核心方法:refresh方法,作用就是实例化spring容器中的所有单例。 3步:生成BeanFactory容器(有beanDefinition类信息和bean对象实例)生成BeanDefinition类信息生成bean对象实例 需要知道的知识:1、先有beanDefinition类信息,再有bean对象。2、在beanDefi......
  • WebKit简介及工作流程
    目录WebKit的架构WebKit的工作流程工作流程示意图结论WebKit是一个开源的浏览器引擎,最初由苹果公司开发,用于其Safari浏览器。它被广泛应用于许多操作系统和平台中,包括macOS、iOS、Windows和Linux。WebKit的主要功能是将HTML、CSS和JavaScript转换成可以在网......
  • HALCON 2D高精密测量项目全流程解析
    1.标定相关的任务–>>解决畸变和坐标系的转换1.1描述和查找标定对象1.2补偿透视和径向变形,径向畸变包括枕形畸变和桶形畸变1.3相机参数(内外参)1.4图像坐标到世界坐标的转换1.5自标定:不用标定板用图像四周包含直线特征进行标定1.6其他标定:一台相机标定、多台相机......
  • 在Linux中,我们都知道FTP协议有两种工作模式,它们的大概的⼀个工作流程是怎样的?
    在Linux中,FTP(FileTransferProtocol,文件传输协议)协议支持两种工作模式:主动模式(ActiveMode)和被动模式(PassiveMode)。这两种模式在数据传输的发起和连接建立的方式上存在显著差异。以下分别详细说明这两种模式的工作流程:一、主动模式(ActiveMode)建立控制连接:客户端首先通过TC......
  • STM32F407外设ADC配置流程及代码示例
    STM32F407外设ADC配置流程及代码示例STM32的ADC(模拟-数字转换器)是STM32微控制器系列中集成的一个关键外设,用于将模拟信号(如温度、压力、光强等传感器输出的电压或电流信号)转换为数字信号,以便微控制器能够处理和分析这些信号。ADC配置流程:时钟配置:启用GPIOF和ADC的时钟。这是......
  • 深度学习 - 门禁系统的人脸录入和识别流程
    门禁系统中的人脸录入和识别通常采用以下几种算法和技术:1.人脸检测(FaceDetection)人脸检测是人脸识别系统的第一步,用于在图像或视频中定位和提取人脸区域。常用的算法包括:HaarCascades (OpenCV):经典的基于特征的检测方法。HOG(HistogramofOrientedGradients) + S......