ServiceManager启动过程分析

196 阅读9分钟

在Android中,ServiceManager是Binder服务框架中的核心组件,负责管理系统中所有的Binder服务。init进程通过init.rc和servicemanager.rc启动servicemanage函数,serviceManager的启动先于所有应用进程。
本文以Android 13源码为例进行分析。
1,在init.rc和servicemanager.rc中关于servicemanager的代码如下:
在system/core/rootdir/Init.rc中

on init
	start servicemanager

在frameworks/native/cmds/servicemanager/servicemanager.rc中

service servicemanager /system/bin/servicemanager
        class core animation  //指定了servicemanager所属的服务类别。在这个例子中,它被归类为core和animation两个类别,不同的类别可能有不同的启动顺序或优先级
        user system	   //指定了运行servicemanager服务的用户为system
        group system readproc
        critical
        onrestart restart apexd
        onrestart restart audioserver
        onrestart restart gatekeeperd
        onrestart class_restart --only-enabled main //指定了当servicemanager服务重启时,应该根据服务是否已启用(enabled)来重启属于main、hal和early_hal类别的服务。这允许系统仅重启那些已配置为启用且属于指定类别的服务。
         onrestart class_restart --only-enabled hal
         onrestart class_restart --only-enabled early_hal
         task_profiles ServiceCapacityLow //表明在系统关闭过程中,servicemanager也被视为一个关键服务
         shutdown critical

2,在frameworks/native/cmds/servicemanager/Android.bp中

cc_binary { // 定义了一个名为servicemanager的二进制文件,它使用了servicemanager_defaults默认设置,并指定了main.cpp作为源文件,同时指定了servicemanager.rc作为init脚本。
	    name: "servicemanager",
	    defaults: ["servicemanager_defaults"],
	    init_rc: ["servicemanager.rc"],
	    srcs: ["main.cpp"],
	}

从上面的配置可以看出,servicemanager.rc文件解析后的入口函数是main.cpp。

3,在frameworks/native/cmds/servicemanager/main.cpp中

// main函数代码是Android Binder服务管理器(ServiceManager)的启动脚本,它负责初始化Binder系统,注册ServiceManager自身为服务,并进入一个事件循环以处理Binder通信。
    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::initWithDriver函数用于初始化Binder状态
        ps->setThreadPoolMaxThreadCount(0); // 设置Binder线程池的最大线程数为0(表示使用默认设置)
        ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
    
        sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>()); // 创建一个ServiceManager实例
        if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) { // 将其自身注册为一个服务。注册失败时打印错误日志
            LOG(ERROR) << "Could not self register servicemanager";
        }
    
    	 // 将ServiceManager实例设置为当前IPC线程的上下文对象,并使其成为Binder的上下文管理器。这样,所有通过Binder进行的IPC调用都会通过ServiceManager进行路由。
        IPCThreadState::self()->setTheContextObject(manager);
        ps->becomeContextManager(); //设置成为 binder上下文管理者
    
        sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/); // 创建一个Looper实例,用于处理事件循环
    
    	 // 设置Binder回调和客户端回调到Looper。这些回调用于处理Binder通信中的特定事件。
        BinderCallback::setupTo(looper);
        ClientCallbackCallback::setupTo(looper, manager);
    
    	 // 进入一个无限循环,通过Looper的pollAll方法等待并处理事件。-1参数表示无限期等待,直到有事件到来。
        while(true) {
            looper->pollAll(-1);
        }
    
        // should not be reached
        return EXIT_FAILURE;
    }

上面的代码调用 ProcessState::initWithDriver 初始化binder状态,每个进程只会有一个ProcessState对象。

4,在frameworks/native/libs/binder/ProcessState.cpp中
initWithDriver函数:

[[clang::no_destroy]] static sp<ProcessState> gProcess;
	[[clang::no_destroy]] static std::mutex gProcessMutex;
	
	// initWithDriver 函数返回一个指向 ProcessState 对象的智能指针 sp<ProcessState>,sp 是 Android 系统中常用的智能指针类型,用于自动管理对象的生命周期。
    sp<ProcessState> ProcessState::initWithDriver(const char* driver)
    {
        return init(driver, true /*requireDefault*/);
    }
	
	sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault)
    {
    
        if (driver == nullptr) {
            std::lock_guard<std::mutex> l(gProcessMutex);
            if (gProcess) {
                verifyNotForked(gProcess->mForked);
            }
            return gProcess;
        }
    
        // 声明一个带有 [[clang::no_destroy]] 属性的静态 std::once_flag 对象 gProcessOnce。这个属性告诉编译器不要销毁这个对象,因为 std::call_once 需要它在整个程序的生命周期内都保持有效。
        [[clang::no_destroy]] static std::once_flag gProcessOnce; 
        // 调用 std::call_once,确保传入的 lambda 表达式只被执行一次。这是用来确保 ProcessState 的初始化只发生一次。
        std::call_once(gProcessOnce, [&](){// 如下匿名函数只会执行一次。使用C++ 11新特性,std::once_flag和std::call_once使得在多线程环境下如下函数只会执行一次。这样就确保了一个进程当中只有一个ProcessState对象,所有线程共享一个ProcessState对象。
            if (access(driver, R_OK) == -1) { // 访问指定的 driver 路径,检查它是否可读
                ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
                driver = "/dev/binder"; //如果不可读则重新赋值为/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); //定义了fork进程的三个回调函数,目的是确保gProcess对象在父进程和子进程中状态的一致性
            LOG_ALWAYS_FATAL_IF(ret != 0, "pthread_atfork error %s", strerror(ret));
    
            std::lock_guard<std::mutex> l(gProcessMutex); // 再次使用 std::lock_guard<std::mutex> 锁定 gProcessMutex,以确保在创建或修改 gProcess 时没有其他线程同时访问它。
            gProcess = sp<ProcessState>::make(driver); //  创建一个新的 ProcessState 实例,并将其智能指针赋值给 gProcess。创建gProcess对象,这里执行的是ProcessState的构造函数。
        });
    
        if (requireDefault) {
            // Detect if we are trying to initialize with a different driver, and
            // consider that an error. ProcessState will only be initialized once above.
            LOG_ALWAYS_FATAL_IF(gProcess->getDriverName() != driver,
                                "ProcessState was already initialized with %s,"
                                " can't initialize with %s.",
                                gProcess->getDriverName().c_str(), driver); // 检查gProcess的driverName跟传入的是否一致
        }
    
        verifyNotForked(gProcess->mForked);
        return gProcess;
    }

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) {
    	// 调用 open_driver 函数尝试打开指定的 Binder 驱动文件
        base::Result<int> opened = open_driver(driver); // open_driver
    
        if (opened.ok()) {
            // mmap the binder, providing a chunk of virtual address space to receive transactions.
    		// 调用mmap接口向Binder驱动申请内核空间的内存,并将其映射到进程的虚拟地址空间中,这块内存用于接收 Binder 事务。函数的返回值是最后文件映射到进程空间的地址.
			//mmap 的作用是将 /dev/binder 设备文件的一部分内存映射到调用进程的虚拟地址空间。它将从 /dev/binder 开始的 BINDER_VM_SIZE 大小的内存区域映射到进程地址空间中的 mVMStart 地址。
			//这种映射使得进程能够直接访问 Binder 驱动的数据区域,从而高效地进行进程间通信(IPC)。
            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(); // 将打开的文件描述符(opened.value())赋值给 mDriverFD 成员变量,以便后续操作使用
        }
    }

becomeContextManager函数

bool ProcessState::becomeContextManager()
    { // 在 Android 的 Binder 架构中,上下文管理器是一个特殊的进程,负责管理 Binder 节点(Binder Nodes)和引用(References),以及处理跨进程通信中的安全上下文信息。
        AutoMutex _l(mLock);
    
        flat_binder_object obj {
            .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
        };
    
    	// 通过 ioctl 系统调用,使用 BINDER_SET_CONTEXT_MGR_EXT 命令和之前准备的 obj 对象尝试成为上下文管理器。
        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;
    }

在ProcessState构造函数中调用了open_driver函数打开binder驱动文件,通过mmap向Binder驱动申请内核空间的内存,并将其映射到进程的虚拟地址空间中。
open_driver函数

static base::Result<int> open_driver(const char* driver) {
	    int fd = open(driver, O_RDWR | O_CLOEXEC); // 打开binder驱动设备,得到文件描述符fd,内核里对应函数为binder_open
	    if (fd < 0) {
	        return base::ErrnoError() << "Opening '" << driver << "' failed";
	    }
		// 下面的ioctl函数,在内核里对应的是binder_ioctl
	    int vers = 0;
	    status_t result = ioctl(fd, BINDER_VERSION, &vers); // 获取binder版本
	    if (result == -1) {
	        close(fd);
	        return base::ErrnoError() << "Binder ioctl to obtain version failed";
	    }
		//如果 ioctl 调用返回值不为 0 或获取的版本号 vers 不等于用户空间协议版本 BINDER_CURRENT_PROTOCOL_VERSION,表示版本不匹配,关闭文件描述符并返回错误。
	    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;
	    }
		//设置 Binder 驱动的最大线程数,可以控制系统中用于处理 Binder 请求的并发线程数量。有助于防止资源过度消耗,提高系统稳定性和性能。(这里是15)
	    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); //启用 Binder 驱动的单向(oneway)垃圾检测功能,以防止 Binder 通信中可能的滥用行为。
	    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;
	}

在上面的open_driver函数中,ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable)启用 Binder 驱动的单向(oneway)垃圾检测功能,以防止 Binder 通信中可能的滥用行为。
单向消息(Oneway Message)分析:
定义:单向消息是一种特殊类型的 IPC(进程间通信)调用。与普通的同步 IPC 调用不同,单向消息是异步的,即调用者发出请求后立即返回,而不等待被调用者处理完成。
使用场景:单向消息通常用于不需要立即返回结果的操作。例如,发送通知或更新状态等。
单向垃圾(Oneway Spam)分析:
单向垃圾:单向垃圾指的是大量的、不受控制的单向消息。这些消息可能会被滥用,导致系统资源耗尽或性能下降。
滥用可能会导致资源耗尽和性能下降。
资源耗尽:频繁发送单向消息可能会占用大量的系统资源(如内存、CPU),影响系统的稳定性。
性能下降:过多的单向消息处理可能会导致系统响应变慢,影响用户体验。
单向垃圾检测(Oneway Spam Detection)
单向垃圾检测功能用于监控和限制单向消息的发送,以防止滥用行为。
通过启用单向垃圾检测,可以确保系统不会因为过多的单向消息而受到影响。