Android M 启动源码分析笔记之 - Zygote 孵化

本文详细解析了Android系统从zygote进程启动到Home应用程序的整个流程,包括init进程、zygote进程、system_server进程及Home Activity启动的源码分析。

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

< 接上一篇:Android M 启动源码分析笔记之 - init 进程>

zygote 到 Home 程序启动源码分析:

先上总时序图:


查看大图


下面开始每一个阶段详细源码分析。时序图【1-5】

/* init进程的main函数服务启动代码段 */
int main(int argc, char** argv) {
...
    while (true) {
        if (!waiting_for_exec) {
            execute_one_command();
            restart_processes();
        }
...
    }
    return 0;
}

展开看:

/* 传入服务的SVC_RESTARTING 的标记,匹配此标记的才执行启动 */
static void restart_processes()
{
    process_needs_restart = 0;
    service_for_each_flags(SVC_RESTARTING,
                           restart_service_if_needed);
}

/* 从服务容器链表service_list中取出每一个svc,
   匹配到标记的执行func动作,service_list 是把每个svc结构内存
   链接起来的listnode链表头指针,只要找到该svc数据结构的slist,
   就可以通过node_to_item指针操作找到对应的svc数据结构首地址.
*/
void service_for_each_flags(unsigned matchflags,
                            void (*func)(struct service *svc))
{
    struct listnode *node;
    struct service *svc;
    list_for_each(node, &service_list) {
        svc = node_to_item(node, struct service, slist);
        if (svc->flags & matchflags) {
            func(svc);
        }
    }
}

/* 宏展开 */
#define node_to_item(node, container, member) \
    (container *) (((char*) (node)) - offsetof(container, member))
    
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

这里有一个重要的数据结构需要特别注意下, 这就是内核中常见的container_of 提取容器数据结构大法. node_to_item 是一个宏,通过指针操作很方便实现提取容器数据结构实例,很巧妙, 简单而又深刻的展现了指针的强大和一些特定场合的不可替代性. 这里有必要深入理解分析下改方法的实现,因为这个东西使用 实在是太普遍了,特别是内核源代码中到处都是.初步看上去,这个宏 数据结构相当复杂,难以理解,这里可以分解几步来看:

1、&((TYPE *)0)->MEMBER --> 将0转换为TYPE类型的指针,那么->MEMBER则是相对0这个指针的偏移地址;

2、offsetof(TYPE, MEMBER) --> 所以就是返回成员MEMBER在TYPE结构中的内存偏移量.

3、((char*) (node)) - offsetof(container, member) --> 则是由member的具体地址(node指针)减去偏移量内存地址反推到container的首地址. 再强制转换成container类型,实现提取容器数据结构的操作!

内核中的定义是类似的

#define container_of(ptr, type, member) ({			\
	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
	(type *)( (char *)__mptr - offsetof(type,member) );})

图解:


有了这个理解就好了,言归正传,继续分析service_for_each_flags函数,如果匹配到了允许启动的标记,那么久会继续执行:

static void restart_service_if_needed(struct service *svc)
{
    time_t next_start_time = svc->time_started + 5;

    if (next_start_time <= gettime()) {
        svc->flags &= (~SVC_RESTARTING);
        
// 进入svc启动入口.
        service_start(svc, NULL);
        return;
    }


/* svc 启动函数*/
void service_start(struct service *svc, const char *dynamic_args)
{
// flags 复位.
    svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
    
// 初始化启动时间,开始计时.
    svc->time_started = 0;
    
// 接下来一堆条件、权限检查,略过..
...

/* 看到了熟悉的fork函数,直接fork一个新的进程.fork函数的执行一次
   返回两次,pid = 0 执行child proc路径,pid > 0 执行parent proc代码路径.
*/
    pid_t pid = fork();
    if (pid == 0) {
// 执行子进程代码:
        struct socketinfo *si;
        struct svcenvinfo *ei;
        char tmp[32];
        int fd, sz;

...
// 创建socket 监听,用于父子进程通信.
        for (si = svc->sockets; si; si = si->next) {
            int socket_type = (
                    !strcmp(si->type, "stream") ? SOCK_STREAM :
                        (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));
            int s = create_socket(si->name, socket_type,
                                  si->perm, si->uid, si->gid, si->socketcon ?: scon);
            if (s >= 0) {
                publish_socket(si->name, s);
            }
        }
..
        if (!dynamic_args) {
/* 真正开始执行子进程系统调用入口代码,svc->args[0]为进程名称,
   svc->args为传入参数.
*/
            if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
                ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
            }
        } else {
...
        }
        _exit(127);
    }

    freecon(scon);

    if (pid < 0) {
        ERROR("failed to start '%s'\n", svc->name);
        svc->pid = 0;
        return;
    }

    svc->time_started = gettime();
    
// 父进程执行路径,记录pid,标记为运行状态.
    svc->pid = pid;
    svc->flags |= SVC_RUNNING;

    if ((svc->flags & SVC_EXEC) != 0) {
        INFO("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...\n",
             svc->pid, svc->uid, svc->gid, svc->nr_supp_gids,
             svc->seclabel ? : "default");
        waiting_for_exec = true;
    }

// 更新设置该服务为 “running” 状态.
    svc->NotifyStateChange("running");
}

小结:

1、从service_list链表中依次取出符合restarting启动条件的svc;

2、svc启动权限等一系列要求检查;

3、fork()子进程,创建socket监听,execve子进程程序;

4、记录子进程pid,发通知标记为“runing”状态;

至此,一个新的服务启动完成,也可以抓开机trace看具体有哪些进程被依次fork出来:

Line 4974: [    3.123846] <0>.(2)[155:init]init: >>start execve(/sbin/ueventd): /sbin/ueventd
	Line 5460: [    6.995649] <1>.(0)[200:init]init: >>start execve(/system/bin/debuggerd): /system/bin/debuggerd
	Line 5464: [    7.002603] <0>.(0)[201:init]init: >>start execve(/system/bin/vold): /system/bin/vold
	Line 5516: [    8.123684] <0>.(0)[209:init]init: >>start execve(/system/bin/logd): /system/bin/logd
	Line 5584: [    8.246659] <1>.(1)[221:init]init: >>start execve(/system/bin/servicemanager): /system/bin/servicemanager
	Line 5590: [    8.276387] <0>.(1)[222:init]init: >>start execve(/system/bin/surfaceflinger): /system/bin/surfaceflinger
	Line 5676: [    8.328844] <3>.(1)[228:init]init: >>start execve(/vendor/bin/nvram_daemon): /vendor/bin/nvram_daemon
	Line 5735: [    8.357851] <3>.(1)[246:init]init: >>start execve(/vendor/bin/batterywarning): /vendor/bin/batterywarning
	Line 5769: [    8.376744] <3>.(1)[252:init]init: >>start execve(/system/bin/cameraserver): /system/bin/cameraserver
	Line 5779: [    8.384829] <3>.(0)[255:init]init: >>start execve(/system/bin/keystore): /system/bin/keystore
	Line 5803: [    8.400396] <3>.(1)[258:init]init: >>start execve(/system/bin/mediaserver): /system/bin/mediaserver
	Line 5805: [    8.401733] <3>.(2)[251:init]init: >>start execve(/system/bin/audioserver): /system/bin/audioserver
	Line 5815: [    8.417515] <3>.(2)[250:init]init: >>start execve(/system/bin/app_process): /system/bin/app_process
	Line 5817: [    8.423806] <2>.(2)[224:init]init: >>start execve(/system/bin/sh): /system/bin/sh
	Line 5823: [    8.436931] <3>.(3)[256:init]init: >>start execve(/system/bin/mediadrmserver): /system/bin/mediadrmserver
	Line 6329: [   10.084763] <1>.(3)[384:init]init: >>start execve(/sbin/adbd): /sbin/adbd
	Line 7039: [   11.081987] <3>.(0)[442:init]init: >>start execve(/system/bin/bootanimation): /system/bin/bootanimation

上面看到的第一个被init启动的进程是ueventd, 而 app_process 就是后面的zygote 进程, app_process 进程入口代码在:

时序图【8-16】

frameworks/base/cmsd/app_process/App_main.cpp

int main(int argc, char* const argv[])
{
...
/* AppRuntime 继承于AndroidRuntime,这里本质是new了一个
   AndroidRuntime的实例.
*/
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
...
    if (!niceName.isEmpty()) {
    
// 这里的niceName为ZYGOTE_NICE_NAME,所以进程名被改为zygote
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }

// 通过AndroidRuntime 启动 java world 函数 ZygoteInit 入口.
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } 
...
}

小结:

1、new 一个AndroidRuntime的实例;

2、更改进程名为zygote;

3、进入 AndroidRuntime.start,创建VM,切换到java world;

继续分析 AndroidRuntime:

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
  ...

// 初始化JNI,创建、启动虚拟机.
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

// 这里注册JNI,所以java world才可以无障碍的使用JNI功能.
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
 ...
 
// 转换类型.
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
    
// 获取startClass中的 main 方法.
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
        
// JNI 调用 com.android.internal.os.ZygoteInit 类的main函数入口,传入参数.
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
        }
    }
...
}

小结:

1、初始化jni引擎,创建启动VM虚拟机;

2、注册jni,这样java world才可以无障碍使用jni支持;

3、jni回调ZygoteInit类的main函数,切换到 java workd;

然后继续分析 ZygoteInit:时序图【17-26】

public static void main(String argv[]) {
        try {
    ...
    // 注册socket监听,socket名字为“zygote”,用于接受子进程创建req.
            registerZygoteSocket(socketName);
           ...
    // 预加载资源、opengl等各种必要类库.
            preload();
     ...
    // 进入启动system_server 进程
            if (startSystemServer) {
                startSystemServer(abiList, socketName);
            }

    // 进入while(1)循环等待创建子进程的socket连接请求.
            runSelectLoop(abiList);
            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
        
    /* 这个地方设计很巧妙,通过try catch 实现了goto语句的效果,每一个进程fork完成
       后都是通过这个函数反射启动新进程入口. */
            caller.run();
        } catch (RuntimeException ex) {
            closeServerSocket();
            throw ex;
        }
    }

zygoteInit.main 干的事情小结:

1、 注册名为zygote的socket监听;

2、预加载各种必要类库资源;

3、启动system_server进程;

4、进入while(1)循环监听来自创建子进程的请求, 巧妙运用异常铺货实现goto语句效果;


下面重点分析 startSystemServer 流程:

private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
       // 设置启动system_server进程的各种参数.
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };
...

        try {
...
           /* fork 出system_server 子进程 ,这里封装了fork()的实现,本质都是系统调用内核的fork实现进程复制 */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
...
        /* 处理system server子进程 */
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }
    
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
...
            /* 进入RuntimeInit */
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }
    }
    
    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
...
    /* 公共部分初始化:handler、timezone、user agent等 */
        commonInit();
        
    /* 调用native函数启动binder线程池用于支持binder通信 */
        nativeZygoteInit();
        applicationInit(targetSdkVersion, argv, classLoader);
    }
    

  private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
  ...
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }

那么关键部分就来了:

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        Class<?> cl;

/* 通过className获取需要反射启动的class<>参数:*/
        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

/* 获取该类的main 方法作为入口:*/
        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }
...
        /* 抛出异常,然后被zygoteInit.main里的try catch捕获到,执行run()函数. */
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }

下面就来看看这个类的原型:

public static class MethodAndArgsCaller extends Exception
            implements Runnable {
        
        private final Method mMethod;
        private final String[] mArgs;

        public MethodAndArgsCaller(Method method, String[] args) {
        /* 传入反射调用参数: main, com.android.server.SystemServer */
            mMethod = method;
            mArgs = args;
        }

        public void run() {
            try {
            /* 执行反射调用:com.android.server.SystemServer.main */
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw new RuntimeException(ex);
            }
        }
    }

到这一步执行路径就直接切到SystemServer类的main方法了:

时序图【28-36】

public static void main(String[] args) {
        new SystemServer().run();
    }

main函数很简单,就是new 一个对象,然后重点来看 run() 的源码分析:

private void run() {
      ...
      
    /* system_server 进程就正式开始执行了,下面这句log比较关键,用于分析
       定位问题很有标志意义 ,分析system_server卡住问题标志性log.
    */
        Slog.i(TAG, "Entered the Android system server!");
        
    /* 设置当前线程的优先级等. */
        android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
        android.os.Process.setCanSelfBackground(false);
        
    /* 创建主线程. */
        Looper.prepareMainLooper();

    /* 初始化加载 native jni库. */
        System.loadLibrary("android_servers");

    /* 检查上一次关机是否成功,如果失败就进入关键流程 */
        performPendingShutdown();

        // 初始化创建系统上下文.
        createSystemContext();

        // 创建系统服务管理服务.
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

    // 依次进入启动各种系统框架服务:
        try {
        
    /* 启动跟boot依赖较大的服务,比如:ActivityManagerService、
       PowerManagerService、PackageManagerService、UserManagerService 、
       SensorManagerService ext. */
            startBootstrapServices();
            
    /* 启动核心服务:BatteryService、UsageStatsService、WebViewUpdateService */  
            startCoreServices();

    /* 其他服务:CameraService、VibratorService、InputManagerService、
       NetworkManagementService ..启动 watchdog线程 等 */
            startOtherServices();
        } catch (Throwable ex) {
        ...
        }
...
    // 进入线程消息循环,永不退出.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

那么在什么时候启动Home 应用程序呢?继续看:

时序图【35-39】

private void startOtherServices() {
    ...
    // 从这里进入开始启动Home程序:
        mActivityManagerService.systemReady(new Runnable() {
            @Override
            public void run() {
                ...
            }
        }
    }
    
    // 走
    public void systemReady(final Runnable goingCallback) {
        ...
            if (!PowerOffAlarmUtility.isAlarmBoot()) {
                startHomeActivityLocked(mCurrentUserId, "systemReady");
            }
    }
    
    // 继续走
    boolean startHomeActivityLocked(int userId, String reason) {
        ...
        // 获取home的intent
        Intent intent = getHomeIntent();
        ActivityInfo aInfo =
            resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
           ...
                // start 
                mStackSupervisor.startHomeActivity(intent, aInfo, reason);
            }
        }

        return true;
    }

   void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
   // 将Home的activity挪到栈顶.
        moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
        
   // 启动Home程序的主Activity:
        startActivityLocked(null /* caller */, intent, null /* resolvedType */, aInfo,
                null /* voiceSession */, null /* voiceInteractor */, null /* resultTo */,
                null /* resultWho */, 0 /* requestCode */, 0 /* callingPid */, 0 /* callingUid */,
                null /* callingPackage */, 0 /* realCallingPid */, 0 /* realCallingUid */,
                0 /* startFlags */, null /* options */, false /* ignoreTargetSecurity */,
                false /* componentSpecified */,
                null /* outActivity */, null /* container */,  null /* inTask */);
      ...
        }
    }

SystemServer 小结:

1、创建主线程,初始化native库,创建系统上下文Context;

2、启动跟boot依赖大的服务、核心服务、其它服务,包括watchdog线程;

3、启动Home程序主Activity入口,这里会涉及到app进程的创建等一系列过程;

4、进入线程消息循环; 

从zygote到home启动流程就分析完了,那么回到最开始的问题:zygote如何实现孵化作用,成为java world所有进程的父进程呢?本文可以看到system_server进程是由zygote创建,那么其它app程序呢?所以,这个问题还得等分析完app的启动流程就可以完整的回答这个问题。


下一篇Android M 启动源码分析笔记之 - App 进程


< 转载请注明出处,谢谢. >

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值