android系统启动流程之init启动分析

android系统启动流程之init启动分析_第1张图片

 先根据上图来描述下安卓整个系统的启动流程:

当上电时,系统先执行BootRom, 加载引导程序执行。

然后进入bootloader,在安卓系统中基本上这个bootloader是uboot, 通过uboot引导启动内核,此时运行在kernel空间,这时的idle属于内核中的进程,它的pid = 0,它负责初始化进程、内存、驱动等相关工作,随后由idle启动fork一个为init进程,这个属于用户空间的进程,pid = 1,然后再fork创建pid=2的kthreadd内核进程,这个是内核进程的鼻祖。init进程则是用户空间的鼻祖,应用空间的所有进程要么直接或间接都是由init进程创建的。

比如init会fork()创建zygote, 这个进程则是java进程的所有鼻祖,所有的java app均来自于zygote进程的fork操作,比如安卓非常重要的系统进程服务SystemServer也是由zygote孵化而来,SystemServer是zygote进程的大儿子,SystemServer进程被创建启动之后,将会创建系统所需要的各种Services, 如ActivityManagerService, WindowManagerService, PackageManagerServices等等,安卓系统中一共大约有90+种服务,均由SystemServer创建生成,因此所有的系统Service服务它们都属于SystemServer进程。

而app的启动过程,则是通过AMS通过发送socket消息给zygote进程,由zygote进程fork()创建这个app进程。

  •  init进程的启动

android系统启动流程之init启动分析_第2张图片

init进程的程序可执行源文件位于/system/bin/init中,前面的流程图可知init进程是由内核的idle进程启动的,先来看看内核中启动init进程的部分源码:

/kernel/common/init/main.c -->kernel_init():
    -->try_to_run_init_process("/bin/init"); //启动init进程。
        -->run_init_process("/bin/init");
            -->kernel_execve("/bin/init"); //还是熟悉的味道与配方

  init的入口函数是main.cpp文件的main函数,下面是真正的init的启动流程:

  main():
    //第一阶段重要工作:
    //1挂载文件系统,创建文件
    //2重定向输入输出,重定向内核日志
    //3启动selinux_setup
    -->第一阶段:FirstStageMain(argc, argv);
        -->mount("tmpfs","dev","tmpfs"); //挂载虚拟文件系统
           mount("devpts","/dev/pts", "devpts",0,NULL)
           mount("proc", "/proc",..);
           mount("sysfs","/sys","sysfs");
           mount("selinuxfs",...);
           mount("tmpfs","/mnt")
           //创建一些设备结点
           mknod("/dev/kmsg");
           mknod("/dev/null");

           SetStdioToDevNULL();
           InitKernelLogging(); //日志重定向
           DoFirstStageMount(); //挂载一些重要的分区设备
           //启动selinux_setup
           char* args[]={path, "selinux_setup"};
           execv(path, args);//参数传递进去继续执行。

    进入第二阶段:main()->SetupSelinux(argv):创建Selinux android强制访问机制
      -->SetStdioToDevNull(); //日志重定向
         InitKernelLogging();
         SelinuxSetupKernelLogging();
         SelinuxInitialize(); //linux安全策略初始化
         //Android --权限  用selinux最小权限原则来处理。
         char* args[]={path, "second_stage"};
         execv(path, args);//参数传递进去继续执行,进入第三阶段

    进入第三阶段:main()->SecondStageMain(argc, argv);
      -->SetStdioToDevNULL();
         InitKernelLogging(); //日志重定向
         PropertyInit(); //属性域初始化
           -->PropertyLoadBootDefaults();
         SelinuxSetupKernelLogging();
         SelabelInitialize();
         SelinuxRestoreContext();//恢复安全上下文
         //处理子进程的终止信号--防止僵尸进程
         Epoll epoll;
         InstallSignalFdHandler(&epoll);
         InstallInitNotifier(&epoll)
         StartPropertyService(&property_fd);//启动属性服务

         GetBuiltinFunctionMap();//命令与函数映射:如将mkdir命令-->mkdir函数匹配

         LoadBootScripts(am,sm); //解析init.rc文件
         while(1){ //进入while循环
            am.ExecuteOneCommand(); //执行解析出来的action里的指令
            auto pending_functions = epoll.Wait(epull_time);//等待
         }

下面看看LoadBootScripts它是如何进行init.rc文件的解析流程的:

LoadBootScripts(am,sm); //解析init.rc文件
  //创建解析器,action_manager结构可以保存所有的action列表
  //service_list:保存解析init.rc中的所有服务。
  -->Parser parser = CreateParser(action_manager, service_list);
      -->parser.AddSectionParser("service"); //service解析器
         parser.AddSectionParser("on"); //on解析器
         parser.AddSectionParser("import");//import解析器
     parser.ParseConfig("/system/etc/init/hw/init.rc");//解析init.rc
      -->ParseConfigFile(path); 
        -->ParseData(path, &config_contents.value());//具体的解析过程在里面,
  • 总结

init进程的重要处理事务:
1 挂载文件
2 设置selinux --安全策略
3 开启属性服务,注册到epoll中
4 解析init.rc文件
5 执行循环处理脚本 --启动ServiceManager zygote等
6 循环等待

你可能感兴趣的:(Android系统,android)