《Android进阶解密》读书笔记--第2章 Android系统启动

2.1 init 进程启动过程

  1. init 进程是 Android 系统中用户空间的第一个进程,进程号为 1,主要创建 Zygote(孵化器)和系统服务,文件位于 system/core/init 中。

2.1.1 引入 init 进程

  1. Android 系统启动流程
启动步骤 简介
启动电源以及系统启动 引导芯片代码从预定义的地方(固话ROM)开始执行,加载引导程序BootLoader到RAM中,执行
引到程序BootLoader 把系统OS拉起来运行
Linux内核启动 设置缓存、被保护存储器、计划列表、加载驱动。在内核完成系统设置后,他首先在系统文件中寻找init.rc 文件,启动 init 进程
init进程启动 初始化和启动属性服务,启动 Zygote进程

2.1.2 init 进程的入口函数

int main(int argc, char** argv) {
    if (!strcmp(basename(argv[0]), "ueventd")) {
        return ueventd_main(argc, argv);
    }
    if (!strcmp(basename(argv[0]), "watchdogd")) {
        return watchdogd_main(argc, argv);
    }
    if (argc > 1 && !strcmp(argv[1], "subcontext")) {
        InitKernelLogging(argv);
        const BuiltinFunctionMap function_map;
        return SubcontextMain(argc, argv, &function_map);
    }
    if (REBOOT_BOOTLOADER_ON_PANIC) {
        InstallRebootSignalHandlers();
    }
    bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);
    if (is_first_stage) {
        boot_clock::time_point start_time = boot_clock::now();
        //1.清理 umask
        umask(0);
        //2.创建和挂在启动所需的文件目录 tmpfs、devpts、proc、sysfs、selinuxfx(只有系统运行时,才存在)
        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
        mkdir("/dev/pts", 0755);
        mkdir("/dev/socket", 0755);
        mount("devpts", "/dev/pts", "devpts", 0, NULL);
        ......
        //3.初始化Kernale的log,便于获取Kernel日志
        InitKernelLogging(argv);
}
//5.对属性服务进行初始化
property_init();
//6.创建 epoll 句柄
epoll_fd = epoll_create1(EPOLL_CLOEXEC);
    if (epoll_fd == -1) {
        PLOG(FATAL) << "epoll_create1 failed";
}
//7.设置子进程信号处理函数,如果子进程(Zygote)异常退出,init 进程会调用该函数中设定的信号处理函数处理
//7.1.防止子进程变僵尸进程(子进程以及挂了,父进程不知道(还保留进程号、退出状态、运行时间等))
sigchld_handler_init();
//8.导入默认的环境变量
property_load_boot_defaults();
export_oem_lock_status();
//9.启动属性服务
start_property_service();
set_usb_controller();
if (bootscript.empty()) {
  //10.解析 init.rc 文件
  parser.ParseConfig("/init.rc");
  parser.set_is_system_etc_init_loaded(
  parser.ParseConfig("/system/etc/init"));
  parser.set_is_vendor_etc_init_loaded(
  parser.ParseConfig("/vendor/etc/init"));
  parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));
} else {
  parser.ParseConfig(bootscript);
  parser.set_is_system_etc_init_loaded(true);
  parser.set_is_vendor_etc_init_loaded(true);
  parser.set_is_odm_etc_init_loaded(true);
}   
...
 while (true) {
        int epoll_timeout_ms = -1
        if (!(waiting_for_prop || Service::is_exec_service_running())) {
             //11.内部遍历执行每个 action 中携带的 command 对应的执行函数
            am.ExecuteOneCommand();
        }
        if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
            //12.重启死去的进程
            restart_processes();
         }
}        

2.1.3 解析 init.rc

  1. 非常重要配置文件,由 Android 初始语言编写脚步(Action、Command、Service、Option、Import)
  2. 分析 Zygote 启动脚本
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main // Zygote 的 classname 为 main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks
//1.Service 通知 init 进程 创建 zygote 进程,执行路径为 /system/bin/app_process64

2.1.4 解析 Service

  1. init.rc 中 Action 和 Service 都有相应的类来解析,分别为 ActionParse、ServiceParse
  2. 看 ServiceParse,在 system/core/init/service.cpp
//1.ParseSection 解析 Service的 rc 文件,用来搭建 Service 的架子
//2.ParseLineSection 用于解析子项目
Result<Success> ServiceParser::ParseSection(std::vector<std::string>&& args,
                                            const std::string& filename, int line) {
    if (args.size() < 3) {//判断 Service 是否有 name 可执行
        return Error() << "services must have a name and a program";
    }

    const std::string& name = args[1];
    if (!IsValidName(name)) { //检查 Service 是否有效
        return Error() << "invalid service name '" << name << "'";
    }
    std::vector<std::string> str_args(args.begin() + 2, args.end());
    //构建一个 Servie 对象
    service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args);
    return Success();
}

2.1.5 init 启动 zygote

  1. 在 system/core/init/builtins.cpp# do_class_start 遍历 Service 链表,找到 classname 为 main 的 zygote,执行 system/core/init/service.cpp#StartIfNotDisabled -> 调用 system/core/init/service.cpp#Start()->froameworks/base/cmds/app_process/app_process/app_main.cpp#main() 函数中,通过 runtime.start() 启动 zygote。

2.1.6 属性服务

  1. 类似于 Window 的注册表管理器(键值对存储记录用户、软件信息)
  2. init 进程启动时,会启动属性服务,为其分配内存,存储属性。
//sysytem/core/property_service.cpp
//1.初始属性内存区域
void property_init() {
if (__system_property_area_init()) {
        LOG(ERROR) << "Failed to initialize property area";
        exit(1);
    }
}
//2.开启属性服务
void start_property_service() {
   property_set("ro.property_service.version", "2");
   //2.1.创建非阻塞的 Socket
   property_set_fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
                                    0666, 0, 0, NULL);
   if (property_set_fd == -1) {
        PLOG(ERROR) << "start_property_service socket creation failed";
        exit(1);
    }
    //2.2.对property_set_fd 监听,server,8代表为8个试图设置属性的用户提供服务
    listen(property_set_fd, 8);
    //2.3.将property_set_fd 放入 epoll 中,epoll 监听 property_set_fd ,有数据时候,init 调用handle_property_set_fd函数进行处理
    //2.3.1.epoll 是Linux 内核为处理大批量文件描述符改进的 poll,多路复用I/O 接口 select/poll 增强,epoll 采用   是红黑树,查找速度快,select 采用数组,查找速度慢
    register_epoll_handler(property_set_fd, handle_property_set_fd);
}
//3.服务处理客户端请求,调用 handle_property_set_fd
static void handle_property_set_fd() {
   .....
   switch (cmd) {
   case PROP_MSG_SETPROP: {
       char prop_name[PROP_NAME_MAX];
       char prop_value[PROP_VALUE_MAX];
       //3.1如果socket 读取不到属性服务 就返回
       if (!socket.RecvChars(prop_name, PROP_NAME_MAX, &timeout_ms) ||
           !socket.RecvChars(prop_value, PROP_VALUE_MAX, &timeout_ms)) {
           PLOG(ERROR) << "sys_prop(PROP_MSG_SETPROP): error while reading name/value from the socket";
          return;
        }
        prop_name[PROP_NAME_MAX-1] = 0;
        prop_value[PROP_VALUE_MAX-1] = 0;
        //3.2.处理客户端请求
        handle_property_set(socket, prop_value, prop_value, true);
        break;
     }
}
//4.处理客户端请求
static void handle_property_set(SocketConnection& socket,
                                const std::string& name,
                                const std::string& value,
                                bool legacy_protocol) {
  const char* cmd_name = legacy_protocol ? "PROP_MSG_SETPROP" : "PROP_MSG_SETPROP2";
  if (!is_legal_property_name(name)) {
    LOG(ERROR) << "sys_prop(" << cmd_name << "): illegal property name \"" << name << "\"";
    socket.SendUint32(PROP_ERROR_INVALID_NAME);
    return;
  }

  struct ucred cr = socket.cred();
  char* source_ctx = nullptr;
  getpeercon(socket.socket(), &source_ctx);
   //4.1.ctl.开头,控制属性(执行一些命令、例如开机动画等)
  if (android::base::StartsWith(name, "ctl.")) {
    //4.2.检查客户端权限
    if (check_control_mac_perms(value.c_str(), source_ctx, &cr)) {
      //4.3.设置控制权限
      handle_control_message(name.c_str() + 4, value.c_str());
      if (!legacy_protocol) {
        socket.SendUint32(PROP_SUCCESS);
      }
    } else {
      LOG(ERROR) << "sys_prop(" << cmd_name << "): Unable to " << (name.c_str() + 4)
                 << " service ctl [" << value << "]"
                 << " uid:" << cr.uid
                 << " gid:" << cr.gid
                 << " pid:" << cr.pid;
      if (!legacy_protocol) {
        socket.SendUint32(PROP_ERROR_HANDLE_CONTROL_MESSAGE);
      }
    }
  } else {
    //4.4.普通属性()
    //检查客户端权限
    if (check_mac_perms(name, source_ctx, &cr)) {
     //4.5.修改普通属性,判断属性是否合法,合法,查找属性,存在,更新属性,否则,添加属性
      uint32_t result = property_set(name, value);
      if (!legacy_protocol) {
        socket.SendUint32(result);
      }
    } else {
      LOG(ERROR) << "sys_prop(" << cmd_name << "): permission denied uid:" << cr.uid << " name:" << name;
      if (!legacy_protocol) {
        socket.SendUint32(PROP_ERROR_PERMISSION_DENIED);
      }
    }
  }

  freecon(source_ctx);
}

2.1.7 init 进程启动总结

  1. 创建和挂载启动所需的文件目录(文件)
  2. 初始化和启动属性服务(属性服务)
  3. 解析 init.rc 配置文件 并且启动 zygote(zygote)

2.2 Zygote 进程启动过程

2.2.1 Zygote概述

  1. Zygote进程:DVM和ART、应用程序进程以及运行系统的服务 SystemServe,称为孵化器,通过 fork 进程形式
  2. Zygote进程名称叫做 “app_process”,在 Android.mk 中定义,Linux系统下的 pctrl 会调用 app_pocess,将名称换成 zygote

2.2.2 Zygote 启动脚本

  1. Android 初始化语言
  2. import/init.${ro.zygote}.rc:1.init.zygote32.rc;2.init.zygote32_64.rc;3.init.zygote64.rc;4.init.zygote64_32.rc
  3. 在 sysytem/core/rootdir 中

2.2.3 Zygote进程启动过程介绍

//frameworkd/base/cmds/app_process/app_main.cpp
//1.main函数 zygote 进程通过 fork 自身创建子进程,自身和子进程可以进入 main 函数
int main(int argc, char* const argv[]){
  while (i < argc) {
        const char* arg = argv[i++];
        //1.1.如果运行在zygote进程中,将zygote设置true
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            //1.2.如果运行在startSystemServer 进程中,将startSystemServer 设置true
            startSystemServer = true;
        } 
    }
  
  //1.2.如果运行在zygote进程中  
  if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
  }
}

// frameworks/base/core/jni/AndroidRuntime.cpp
//2.AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote){
    //2.1启动 java虚拟机
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    //2.2.为java虚拟机注册方法
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    //2.3.通过 JNI 调用 ZygoteInit.java 的 main 方法,进入 java 层了,Zygote 开创了 java
    //java 框架
     env->CallStaticVoidMethod(startClass, startMeth, strArray);
      
}
//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
//3.ZygoteInit.java
public static void main(String argv[]) {
      
     //3.1.创建一个Server端的Socket,socketName 为 zygote 
     zygoteServer.registerServerSocket(socketName);
     //3.2.启动SystemServer进程
     if (startSystemServer) {
             startSystemServer(abiList, socketName, zygoteServer);
     }
     //3.3.等待AMS请求,创建新的应用程序进程
     zygoteServer.runSelectLoop(abiList);
}
//frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
//4.ZygoteServer.java
void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
      //4.1. mServerSocket 就是registerServerSocket 中 socket
     fds.add(mServerSocket.getFileDescriptor());
     //4.2.等待AMS请求 zygote 进程创建新的应用程序
     while (true) {
     }
}

  1. ZygoteInit main 方法
    1.创建一个 Server端Socket
    2.预加载类和资源
    3.启动SystemServer
    4.等待AMS请求创建新的应用程序进程

2.2.4 Zygote进程启动总结

  1. 创建 AppRuntime 并调用 start,启动 Zygote 方法
  2. 创建 java虚拟机,注册 JNI方法
  3. JNI调用 ZygoteInit 的main函数进去 Zygote 的 java 层中
  4. 通过 registerZygoteSocket 创建服务端 socket,并通过 runSelectLoop 等待 AMS请求 来创建新的应用进程。
  5. 启动 SystemServer 进程

2.3 SystemServer 处理过程

2.3.1 Zygote 处理 SystemServer 进程

//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
//1.ZygoteInit.java
private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
            throws Zygote.MethodAndArgsCaller, RuntimeException {
      //1.1.当前运行在 SystemServer中      
     if (pid == 0) {
           if (hasSecondZygote(abiList)) {
               waitForSecondaryZygote(socketName);
            }
            //1.2.关闭Zygote 创建的Socket
            zygoteServer.closeServerSocket();
            //1.3.启动 SystemServer
            handleSystemServerProcess(parsedArgs);
     }
}
private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
           throws Zygote.MethodAndArgsCaller {
     ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}

public static final void zygoteInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
        //启动 Binder 线程池 native 方法    
        ZygoteInit.nativeZygoteInit();
        // 进入 SystemServer 的 main 方法
        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);  
}

2.3.2 解析 SystemServer 进程

//frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
     new SystemServer().run();
}

private void run() {
   //创建 Looper
   Looper.prepareMainLooper()
   //加载动态库 libandroid_servers
   System.loadLibrary("android_servers");
   //创建系统 context 
   createSystemContext();
   //创建 SystemServiceManager(生命周期管理)
   mSystemServiceManager = new SystemServiceManager(mSystemContext);
   try {
      //启动引导服务(Installer、AMS、PowerMS、PMS)
      startBootstrapServices();
      //启动核心服务(DropBoxMS、BatteryService、UsageStateService、WebViewUpdateService)
      startCoreServices();
      //启动其他服务(VrMS、CameraService)
      startOtherServices();
   }
}

2.3.3 SystemServer 进程总结

  1. 启动 Binder 线程池,与其他进程通信
  2. 创建 SystemServiceManager,对系统服务生命周期管理
  3. 启动各种服务

2.4 Launcher 启动过程

2.4.1 Launcher 概述

  1. 最后一步启动一个应用程序来显示系统安装的应用程序,Launcher。
  2. 请求 PMS 返回系统已经安装的应用程序信息,封装成快捷图标列表展示在屏幕上
  3. 作用
    1.作为Android系统启动器,用于启动应用程序
    2.作为Android系统桌面,显示和管理应用程序的快捷图标或其他桌面组件。
SystemServer AMS ActStackSupervisor ActivityStack systemReady 调用 AMS中方法,launcher 入口 resumeFocusedStack resumeToActivity resumeToActivityInnerLocked resumeHomeStackTask startHomeActivityLocked mFactoryTest非工 厂模式、低级、 高级 SystemServer AMS ActStackSupervisor ActivityStack

2.4.3 Launcher 中应用图标显示过程

//packages/apps/Launcher/src/com/android/launcher3/Launcher.java;
//1.Launcher.java
protected void onCreate(Bundle savedInstanceState) {
   //1.1.获取 LauncherAppState
   LauncherAppState app = LauncherAppState.getInstance(this);
   //1.2.setLauncher,传入 Launcher 对象
   mModel = app.setLauncher(this);
   //1.3.开始 创建 HeadlerThread,将 LoaderTask(绑定工作区、加载安应用程序) 消息发送给 HandlerThread
   mModel.startLoader()
}

//2.LauncherAppState.java
LauncherModel setLauncher(Launcher launcher) {
        getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
        //2.1.调用 initialize 方法
        mModel.initialize(launcher);
        return mModel;
    }

public void initialize(Callbacks callbacks) {
        synchronized (mLock) {
            Preconditions.assertUIThread();
            //2.2.将Launcher封装成弱引用对象
            mCallbacks = new WeakReference<>(callbacks);
        }
    }
 
 //3.Launcher.java
 //将所有app信息设置进去,最后 AllAppsRecyclerView 设置布局
 public void bindAllApplications(ArrayList<AppInfo> apps) {
        mAppsView.getAppsStore().setApps(apps);
        if (mLauncherCallbacks != null) {
            mLauncherCallbacks.bindAllApplications(apps);
        }
    }

2.5 Android系统启动流程

步骤 简介
1.启动电源以及系统启动 加载引导程序BootLoader到RAM
2.引导程序BootLoader 系统OS拉起来
3.Linux内核启动 1.设置缓存、被保护存储器、计划列表、加载驱动;2.寻找 init.rc,启动 init 进程
4.init进程启动 1.初始化和启动属性服务;2.启动zygote进程
5.Zygote进程启动 1.创建java虚拟机,注册JNI方法;2.创建服务端Socket;3.启动SystemServer
6.SystemServer进程启动 1.启动Binder线程池和SystemServiceManager;2.启动各种系统服务(AMS,PMS);
7.Launcher启动 已安装的应用程序快捷图标显示到桌面上

1.按下电源,加载 BootLoader 把系统 OS 拉起来,Linux 内核启动,紧接着启动 init 进程,init 进程初始化和启动属性服务,并且启动 zygote进程,zygote 进程创建虚拟机加载JNI方法,创建服务端的 Socket,并且启动 SystemServer,SystemServer会启动Binder线程池和系统服务管理,包括AMS、PMS 等系统服务,最后,AMS 启动 Launcher,加载安装应用的图标。

发布了40 篇原创文章 · 获赞 14 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_44947117/article/details/104151235
今日推荐