一个非系统工程师所关心的——Android开机流程

news/2024/11/8 22:56:40/

一、Loader层

1. Boot ROM:
        上电后,BootRom会被激活,引导芯片代码开始从预定义的地方(固化在ROM)开始执行,然后加载引导程序到RAM

2. Boot Loader引导程序

      Android是基于Linux系统的,它没有BIOS程序,取而代之的是BootLoader(系统启动引导程序)。引导程序是厂商加锁和限制的地方,它是针对特定的主板与芯片的。厂商要么使用很受欢迎的引导程序比如redbootubootARMboot等或者开发自己的引导程序,它不是Android操作系统的一部分。流程图如下:


 

 二、kernel层

      Linux内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。

1.init 进程的启动

      0号进程:
      swapper进程(pid=0):又称idle进程、空闲进程,由系统自动创建, 运行在内核态。
系统初始化过程Kernel由无到有开创的第一个进程, 也是唯一一个没有通过fork或者kernel_thread产生的进程。
swapper进程用于初始化进程管理、内存管理,加载Display,Camera Driver,Binder Driver等相关工作。

    1号进程(就是init进程)
init进程(pid=1):由0号进程通过kernel_thread创建,在内核空间完成初始化后, 加载init程序, 并最终运行在用户空间,init进程是所有用户进程的鼻祖,他的作用是:

   (1)是挂载tmpfs, devpts, proc, sysfs文件系统

   (2)是运行init.rc脚本,init将会解析init.rc,并且执行init.rc中的命令。

   (3)当一些关键进程死亡时,重启该进程;

   (4)提供Android系统的属性服务

    2号进程
kthreadd进程(pid=2):由0号进程通过kernel_thread创建,是Linux系统的内核进程,会创建内核工作线程kworkder,软中断线程ksoftirqd,thermal等内核守护进程。
kthreadd运行在内核空间, 负责所有内核线程的调度和管理 , kthreadd进程是所有内核进程的鼻

三、zygote才是重点

1.Zygote启动

我们关注的是:Linux内核启动后,会加载system/core/init/init.rc文件,启动init进程,init进程会fork Zygote进程,Zygote作为孵化器进程,它的main函数会创建好自己的环境准备孵化子进程,并开始等待孵化请求。

init.rc文件内容很多,我们就贴一点出来

chown system system /dev/stune/tasks

chmod 0664 /dev/stune/tasks

mkdir /dev/binderfs

mkdir /mnt/user/0/emulated/0 0755 root root

start servicemanager //重点2 servicemanager启动
start hwservicemanager
start vndservicemanager

import /system/etc/init/hw/init.${ro.zygote}.rc
trigger zygote-start
on zygote-start && property:ro.crypto.state=unencrypted
    wait_for_prop odsign.verification.done 1
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier_nonencrypted
    start statsd
    start netd
    start zygote
    start zygote_secondary

可见init启动了zygote、servicemanager等等。

那么我们先看zygote是怎么启动的,后面再看serviceManager。我们来看一下init.zygote64.rc文件 //重点1service启动

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote stream 660 root system

可见启动了app_process程序,app_process的源码在frameworks/base/cmds/app_process/app_main.cpp

int main(int argc, const char* const argv[])
{
    // These are global variables in ProcessState.cpp
    mArgC = argc;
    mArgV = argv;
    mArgLen = 0;
    for (int i=0; i<argc; i++) {
        mArgLen += strlen(argv[i]) + 1;
    }
    mArgLen--;
    AppRuntime runtime;
    const char* argv0 = argv[0];
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;
    // Everything up to '--' or first non '-' arg goes to the vm
    int i = runtime.addVmArguments(argc, argv);
    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    const char* parentDir = NULL;
    const char* niceName = NULL;
    const char* className = NULL;
    while (i < argc) {
        const char* arg = argv[i++];
        if (!parentDir) {
            parentDir = arg;
        } else if (strcmp(arg, "--zygote") == 0) {
            zygote = true;//zygote进程
            niceName = "zygote";
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;//启动系统服务
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName = arg + 12;
        } else {
            className = arg;
            break;
        }
    }
    if (niceName && *niceName) {
        setArgv0(argv0, niceName);
        set_process_name(niceName);
    }
    runtime.mParentDir = parentDir;
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit",
                startSystemServer ? "start-system-server" : "")
;//在这里通过runtime启动ZygoteInit从此由内核C层进入了我们的应用层。
    } else if (className) {
        // Remainder of args get passed to startup class main()
        runtime.mClassName = className;
        runtime.mArgC = argc - i;
        runtime.mArgV = argv + i;
        runtime.start("com.android.internal.os.RuntimeInit",
                application ? "application" : "tool");
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}

我们看看/java/com/android/internal/os/ZygoteInit.java 类都做了些什么

   static void preload(TimingsTraceLog bootTimingsTraceLog) {
        Log.d(TAG, "begin preload");
      
       
beginPreload();
        preloadClasses();//预加载类,其中就包括我们熟悉的系统API
       
cacheNonBootClasspathClassLoaders();加载无法放入Boot classpath的文件
        preloadResources();加载drawables、colors
       
nativePreloadAppProcessHALs();加载hal 硬件
       
maybePreloadGraphicsDriver();调用OpenGL/Vulkan加载图形驱动程序
       
preloadSharedLibraries();//加载共享库
       
preloadTextResources();初始化TextView ,对,你没看错
        WebViewFactory.prepareWebViewInZygote();//初始化webview
        endPreload();// 取消软引用保护
        warmUpJcaProviders(); 初始化JCA安全相关的参数,比如AndroidKeyStoreProvider安装
        sPreloadComplete = true;
    }

for系统服务:

 private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
       
        StructCapUserHeader header = new StructCapUserHeader(
                OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
        StructCapUserData[] data;
        try {
            data = Os.capget(header);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to capget()", ex);
        }
        capabilities &= Integer.toUnsignedLong(data[0].effective) |
                (Integer.toUnsignedLong(data[1].effective) << 32);
        String[] args = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                        + "1024,1032,1065,3001,3002,3003,3005,3006,3007,3009,3010,3011,3012",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
        };
        ZygoteArguments parsedArgs;
        int pid;
        try {
            ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
            try {
                parsedArgs = ZygoteArguments.getInstance(commandBuffer);
            } catch (EOFException e) {
                throw new AssertionError("Unexpected argument error for forking system server", e);
            }
            commandBuffer.close();
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);
            if (Zygote.nativeSupportsMemoryTagging()) {
                String mode = SystemProperties.get("arm64.memtag.process.system_server", "");
                if (mode.isEmpty()) {
                  /* The system server has ASYNC MTE by default, in order to allow
                   * system services to specify their own MTE level later, as you
                   * can't re-enable MTE once it's disabled. */
                  mode = SystemProperties.get("persist.arm64.memtag.default", "async");
                }
                if (mode.equals("async")) {
                    parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_ASYNC;
                } else if (mode.equals("sync")) {
                    parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_SYNC;
                } else if (!mode.equals("off")) {
                    /* When we have an invalid memory tag level, keep the current level. */
                    parsedArgs.mRuntimeFlags |= Zygote.nativeCurrentTaggingLevel();
                    Slog.e(TAG, "Unknown memory tag level for the system server: \"" + mode + "\"");
                }
            } else if (Zygote.nativeSupportsTaggedPointers()) {
                /* Enable pointer tagging in the system server. Hardware support for this is present
                 * in all ARMv8 CPUs. */
                parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
            }
            /* Enable gwp-asan on the system server with a small probability. This is the same
             * policy as applied to native processes and system apps. */
            parsedArgs.mRuntimeFlags |= Zygote.GWP_ASAN_LEVEL_LOTTERY;
            if (shouldProfileSystemServer()) {
                parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
            }
            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer( //调用zygote fork 系统服务
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }
        return null;
    }

所以最终调用  java/com/android/internal/os/Zygote.java 的 forkSystemServer,我们看一下源码

static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        ZygoteHooks.preFork();
        int pid = nativeForkSystemServer(
                uid, gid, gids, runtimeFlags, rlimits,
                permittedCapabilities, effectiveCapabilities);
        // Set the Java Language thread priority to the default value for new apps.
        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
        ZygoteHooks.postForkCommon();
        return pid;
    }

所以systemServer就这么启动了。

好了,具体的细节我们就跟踪到这里,有兴趣的可以看源码,源码有详细的过程。
 

2.servicemanager启动

我们看到 init 也启动了/system/bin/servicemanager程序,servicemanager程序的源码在android/frameworks/native/cmds/servicemanager/main.cpp

int main(int argc, char** argv) {
    android::base::InitLogging(argv, android::base::KernelLogger);
    if (argc > 2) {
        LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
    }
    const char* driver = argc == 2 ? argv[1] : "/dev/binder";
    LOG(INFO) << "Starting sm instance on " << driver;
    sp<ProcessState> ps = ProcessState::initWithDriver(driver);//驱动层创建binder_proc
    ps->setThreadPoolMaxThreadCount(0);
    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);

//创建ServiceManager
    sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<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);
    if (!ps->becomeContextManager()) {//注册成为binder服务的大管家
        LOG(FATAL) << "Could not become context manager";
    }

//开启looper 消息循环 监听 BinderCallback
    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
    BinderCallback::setupTo(looper); //处理Binder请求
    ClientCallbackCallback::setupTo(looper, manager);//定时通知client变化
#ifndef VENDORSERVICEMANAGER
    if (!SetProperty("servicemanager.ready", "true")) {
        LOG(ERROR) << "Failed to set servicemanager ready property";
    }
#endif
    while(true) {
        looper->pollAll(-1);
    }
    // should not be reached
    return EXIT_FAILURE;
}

。。。等待继续

 


http://www.ppmy.cn/news/85150.html

相关文章

【Axure教程】通过文本框维护下拉列表选项

下拉列表&#xff08;Dropdown List&#xff09;是一种常见的用户界面元素&#xff0c;用于提供一组选项供用户选择。它通常以一个展开的列表形式出现&#xff0c;用户可以点击或选择列表中的一个选项。一般来说&#xff0c;他的选项值是由系统代码组成的&#xff0c;所以一般是…

JAVA LIST 根据对象元素去重

应用场景&#xff1a;在开发中过程中 会存在根据List集合中的对象一个或者多个元素进行去重 1&#xff1a;根据List集合中的对象一个元素进行去重 List<PurchaseHead> organizationPurchaseHeadList purchaseHeadList.stream().collect(Collectors.collectingAndThe…

uniapp前端图片布局时z-index出现的几个问题

目录 图片的z-index是怎么看的 一些规则: 图片没有z-index吗&#xff1f; 图片会优先覆盖其他元素吗&#xff1f; z-index失效 static elative、absolute或fixed的元素 元素的z-index覆盖子元素吗 图片的z-index是怎么看的 z-index属性用于控制元素的堆叠顺序,它只对定位…

进程控制

目录 进程创建 fork函数 写时拷贝 进程终止 进程退出场景 进程常见退出方法 进程等待 进程等待的必要性 进程等待的方法 wait方法 waitpid方法 获取子进程status 等待行为options 进程替换 各类程序替换函数的使用 命名理解 execl函数 execv函数 execlp函数…

利用PaddleOCR识别增值税发票平台验证码(开箱即用)

前言:全国增值税发票查验平台验证码没什么好说的,根据指定的颜色识别验证码中的文字,图片如下 下面直接讲解利用paddleocr识别的思路,为什么使用paddleocr,因为paddle中集成了较好的ocr文字识别模型,开箱即用即可,废话不多说,剑指主题,识别思路步骤如下 步骤如下 1、…

react表格行下载文件方法总结

一、前言 下载文件时&#xff0c;后台接口返回的响应体是文件流格式的&#xff0c;前端接收时如果不进行处理&#xff0c;就会无法正确下载文件&#xff08;有可能会直接打开文件等&#xff09;。 在此记录下react的表格行使用file-saver下载文件的方法。&#xff08;注意不同…

手写源码之Js中的 call() apply() bind()

说多无益, 直接上代码, 肯定还有一些不完善的地方, 我参考了一下 原生js源码之JavaScript的call方法&#xff0c;自己来实现 call() use strictvar person {name: "Tom",sayHi(a, b) {// console.log(a, a)// console.log(b, b)// return this.name " 在向你…

最全面的ETL工具选型指南

什么是ETL? ETL是数据仓库和数据集成领域常用的缩写&#xff0c;代表Extract, Transform, Load&#xff08;提取、转换、加载&#xff09;三个步骤。它是一种数据处理过程&#xff0c;用于从不同的数据源中提取数据、对数据进行转换和清洗&#xff0c;并将处理后的数据加载到…