基于Android 14系统启动流程之zygote进程启动解析 (详细分析从kernel启动到zygote启动完了的过程)

本文详细分析了Android 14系统从kernel启动到zygote启动的过程,涵盖init进程的三次启动、zygote进程启动的时机及内容,以及zygote进程如何通过反射和JNI通信执行Java代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

最近在看android framework 的源码,发现网上对最新android framework代码讲解较少,且很多内容存在变更,导致理解起来很吃力,因此打算出一系列关于android framework源码的解析的文章。
本篇文章主要讲解zygote是如何启动的,从内核kernel启动开始,一直贯穿到java层代码,包括以下几部分:

  • init 进程的启动时机
  • init 进程都做了哪些事情
  • zygote进程启动的时机,都做了哪些内容
  • java代码是如何运行的
  • 简单画了函数之间的调用关系。

二、init 进程的启动时机

1、系统是如何运行的

  • 电源和系统启动:当用户按下开机按键时,引导芯片会从预定的地方(Boot ROM)开始执行,加载引导程序BootLootLoader到RAM。
  • 启动操作系统:BootLoader 会引导操作系统启动。
  • Linux内核启动:swapper(pid=0) 进程启动,用于启动init(pid=1)进程和kthreadd(pid=2)进程。
  • 启动进程init:init 进程主要实现的功能是,创建文件、挂载文件、设置selinux(安全策略)、初始化系统属性、挂载额外的系统文件、监听子进程状态,回收僵尸进程、启动系统属性服务、设置commands指令所对应的函数map、解析init.rc、执行rc命令。

2、init 进程的启动

这里从内核启动讲起,而内核的启动是在kernel/common/init/main.c函数在完成的,下面分析一下main.c文件。代码解析如下:

//kernel/common/init/main.c

872 void start_kernel(void)
873 {
   
    
//省略初始化相关的代码,只看主线代码
...
//系统还活着,做剩下的初始化内容,其中包括init启动和kthread的启动
1070     arch_call_rest_init();
...
1079 }

823 void __init __weak __noreturn arch_call_rest_init(void)
824 {
   
   
//继续向下调用
825     rest_init();
826 }

//nolinline是强制不内联
682 noinline void __ref __noreturn rest_init(void)
683 {
   
   
//省略初始化相关的代码,只看主线代码
...
//在用户态线程下运行kernel_init,因为这样可以保证init的进程为0,
//然后在创建kthreadd进程。
693     pid = user_mode_thread(kernel_init, NULL, CLONE_FS);
...
//启动kthreadd进程,主要是创建内核的工作线程kworkder,
//软中断线程ksofttirqd,thermal等内核守护进程,
//这里不是本次的重点,不关注。
706     pid = kernel_thread(kthreadd, NULL, NULL, CLONE_FS | CLONE_FILES);
...
729 }

//继续分析kernel_init进程
1430 static int __ref kernel_init(void *unused)
1431 {
   
   
//可以看到从这开始启动了init进程
1495     if (!try_to_run_init_process("/sbin/init") ||
1496     ¦   !try_to_run_init_process("/etc/init") ||
1497     ¦   !try_to_run_init_process("/bin/init") ||
1498     ¦   !try_to_run_init_process("/bin/sh"))
1499         return 0;
1500 
1501     panic("No working init found.  Try passing init= option to kernel. "
1502     ¦   ¦ "See Linux Documentation/admin-guide/init.rst for guidance.");
1503 }

try_to_run_init_process函数主要是用于启动进程的,下面是对try_to_run_init_process的分析:

//继续分析try_to_run_init_process
1358 static int try_to_run_init_process(const char *init_filename)
1359 {
   
      
1360     int ret;
1361 
//通过调用run_init_process启动进程
1362     ret = run_init_process(init_filename);
1363 
1364     if (ret && ret != -ENOENT) {
   
   
1365         pr_err("Starting init: %s exists but couldn't execute it (error %d)\n",
1366         ¦   ¦  init_filename, ret);
1367     }
1368 
1369     return ret;
1370 }

下面对run_init_process分析:

//继续分析run_init_process,注意看最后一行。
1343 static int run_init_process(const char *init_filename)
1344 {
   
      
1345     const char *const *p;
1346     
1347     argv_init[0] = init_filename;
1348     pr_info("Run %s as init process\n", init_filename);
1349     pr_debug("  with arguments:\n");
1350     for (p = argv_init; *p; p++)
1351         pr_debug("    %s\n", *p);
1352     pr_debug("  with environment:\n");
1353     for (p = envp_init; *p; p++)
1354         pr_debug("    %s\n", *p);
//调用系统函数kernel_execve来启动用户空间的进程。
1355     return kernel_execve(init_filename, argv_init, envp_init);
1356 }

经过以上的步骤,init 进程就顺利的启动了,下面我们分析inti进程都做了哪些事情。

三、init 进程都做了哪些事情

根据bp 文件可以轻松的找到init进程源码以及函数入口,bp 文件分析如下:

system/core/init/Android.bp
267 cc_binary {                                                                
268     name: "init_second_stage",                                             
269     recovery_available: true,                                              
270     stem: "init",                                                          
271     defaults: ["init_defaults"],                                           
272     static_libs: ["libinit"],         
//注意看这里,init进程的如何函数在main.cpp中,接下来分析main.cpp源码                                     
273     srcs: ["main.cpp"],                                                    
274     symlinks: ["ueventd"],                                                 
275     target: {                                                              
276     ¦   platform: {                                                        
277     ¦   ¦   required: [                                                    
278     ¦   ¦   ¦   "init.rc",                                                 
279     ¦   ¦   ¦   "ueventd.rc",                                              
280     ¦   ¦   ¦   "e2fsdroid",                                               
281     ¦   ¦   ¦   "extra_free_kbytes",                                       
282     ¦   ¦   ¦   "make_f2fs",                                               
283     ¦   ¦   ¦   "mke2fs",                                                  
284     ¦   ¦   ¦   "sload_f2fs",                                              
285     ¦   ¦   ],                                                             
286     ¦   },                                                                 
287     ¦   recovery: {                                                        
288     ¦   ¦   cflags: ["-DRECOVERY"],                                        
289     ¦   ¦   exclude_static_libs: [                                         
290     ¦   ¦   ¦   "libxml2",                                                 
291     ¦   ¦   ],                                                             
292     ¦   ¦   exclude_shared_libs: [                                         
293     ¦   ¦   ¦   "libbinder",                                               
294     ¦   ¦   ¦   "libutils",                                                
295     ¦   ¦   ],                                                             
296     ¦   ¦   required: [                                                    
297     ¦   ¦   ¦   "init_recovery.rc",                                        
298     ¦   ¦   ¦   "ueventd.rc.recovery",                                     
299     ¦   ¦   ¦   "e2fsdroid.recovery",                                      
300     ¦   ¦   ¦   "make_f2fs.recovery",                                      
301     ¦   ¦   ¦   "mke2fs.recovery",                                         
302     ¦   ¦   ¦   "sload_f2fs.recovery",                                     
303     ¦   ¦   ],                                                             
304     ¦   },                                                                 
305     },                                                                     
306     visibility: ["//packages/modules/Virtualization/microdroid"],          
307 }                                                                          

废话不多说,下面直接分析system/core/init/main.cpp 代码。这里要格外注意,main.cpp 代码会执行三遍!!!main.cpp 代码会执行三遍!!!main.cpp 代码会执行三遍!!!

1、init 进程第一遍启动

这里是init启动的第一遍,是由上章 try_to_run_init_process(“/sbin/init”) 启动的,启动init时没有传入任何参数!!!分析内容如下:

//system/core/init/main.cpp

53 int main(int argc, char** argv) {
   
                                                   
//省略初始化相关的代码,只看主线代码
...
65     if (argc > 1) {
   
   
66     ¦   if (!strcmp(argv[1], "subcontext")) {
   
                                       
67     ¦   ¦   android::base::InitLogging(argv, &android::base::KernelLogger);      
68     ¦   ¦   const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();    
69     
70     ¦   ¦   return SubcontextMain(argc, argv, &function_map);                    
71     ¦   }   
72     
73     ¦   if (!strcmp(argv[1], "selinux_setup")) {
   
                                    
76     ¦   ¦   return SetupSelinux(argv);                                           
77     ¦   }                                                                        
78 
79    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值