android 的Zygote 分析(转)

来源:互联网 发布:java框架搭建 编辑:程序博客网 时间:2024/05/01 19:33

jollen 發表於 April 5, 2010 3:14 PM

Android 作業系統開機時,會經由 init.rc 來啟動許多外部程式,其中有一個最重要 process 稱為 Zygote。Zygote 是 Android 的 monitor process,它主要負責二項工作:

1. 啟動 system server
2. 執行 Android 應用程式

「System Server」是由 Zygote 所建立的另外一個 process,建立 system server 的方式是使用典型的 Linux system call - fork()。當 Zygote 成功建立 system server 後,便進入 socket listening 模式。在此模式下,zygote 會監聽(listen)由 socket 所傳入的「命令」,並依據命令的內容啟動 Android 應用程式。

Zygote 啟動外部 Android 應用程式的方式,同樣是使用 Linux kernel 所提供的 fork() system call。因此,在 socket 做 listening,並依據命令來 fork() 並執行外部 Android 應用程式,稱之為「Zygote Mode」。

    android的系统应用中的一个重要的进程就是zygote,所有的java应用程序进程都是由zygote派生出来的,zygote这个进程的作用就是“生儿子”。具体的一个应用如何出来的大家可以看我以前的一篇文章-----Android 应用初始化及窗体事件的分发。

   首先要了解一点初始化语言的基本知识吧:

Services(服务)是一个程序,他在初始化时启动,并在退出时重启(可选)。Services(服务)的形式如下:

       service <name> <pathname> [ <argument> ]*
          <option>
          <option>
Options为选项,具体可以参考linux service命令
zygote进程正是在linux kernel startup后通过这个文件启动的,具体看init.rc中这一段:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    socket zygote stream 666
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
一段一段的分析这个代码:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
启动服务名字zygote.   /system/bin/app_process 进程的bin文件具体路径,后面跟的就是启动参数-Xzygote /system/bin --zygote --start-system-server。这段参数有什么作用可以对照看代码app_main.cpp

if (i < argc) {
        arg = argv[i++];
        if (0 == strcmp("--zygote", arg)) {
            bool startSystemServer = (i < argc) ?
                    strcmp(argv[i], "--start-system-server") == 0 : false;
            setArgv0(argv0, "zygote");
            set_process_name("zygote");
           runtime.start("com.android.internal.os.ZygoteInit",
                startSystemServer);
        } else {
            set_process_name(argv0);

            runtime.mClassName = arg;

            // Remainder of args get passed to startup class main()
            runtime.mArgC = argc-i;
            runtime.mArgV = argv+i;

            LOGV("App process is starting with pid=%d, class=%s./n",
                 getpid(), runtime.getClassName());
            runtime.start();
        }
    }

-Xzygote 这个参数的意义是在jvm中设置gDvm.zygote = true;至于这个参数的具体作用大家自己看代码吧。 其流程是 androidRuntime->start() call---> JNI_CreateJavaVM() call ---->dvmStartup()(戴维林虚拟机初始化) call---->dvmProcessOptions().

/system/bin :也许是告知系统应用的路径吧,大家看到了告诉我。

onrestart write /sys/android_power/request_state wake:

如果这个服务重启了,打开/sys/android_power/request_state 这个文件写入wake字符串。

Zygote Service

在本章我们会接触到这两个单词:

•Zygote [生物] 受精卵, 接合子, 接合体
•Spawn:产卵
通过这两个单词,我们就可以大体知道Zygote是干什么的了,就是叫老母鸡下蛋。通过“Zygote”产出不同的子“Zygote”。从大的架构上讲,Zygote是一个简单的典型C/S结构。其他进程作为一个客服端向Zygote发出”孵化”请求,Zygote接收到命令就“孵化”出一个Activity进程来。

Zygote系统代码组成及其调用结构:
•Zygote.java
  提供访问Dalvik “zygote”的接口。主要是包装Linux系统的Fork,以建立一个新的VM实例进程。
•ZygoteConnection.java
  Zygote的套接口连接管理及其参数解析。其他Actvitiy建立进程请求是通过套接口发送命令参数给Zygote。
•ZygoteInit.java
  Zygote的main函数入口。

Zygote系统代码层次调用


main()

 Startsystemserver()…

 RunSelectLoopMode()

  Accept socket connection

   Conntecion.RunOnce()

   Read argument

    folkAndSpecialize

folkAndSpecialize使用Native函数Dalvik_dalvik_system_Zygote_forkAndSpecialize

//native 的获取
 dalvik/vm/native


//dalvik_system_Zygote.c

  const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {

    { "fork",            "()I",

        Dalvik_dalvik_system_Zygote_fork },

    { "forkAndSpecialize",            "(II[II[[I)I",

        Dalvik_dalvik_system_Zygote_forkAndSpecialize },

    { "forkSystemServer",            "(II[II[[I)I",

        Dalvik_dalvik_system_Zygote_forkSystemServer },

    { NULL, NULL, NULL },

};


在这里我们就有了Zygote服务的全貌理解,也在Code中印证了,Activity在本质上是个什么东西,就是一个Linux进程。但是不是一个简单的Linux进程,毕竟Activity是在Andoid概念空间中才有效的。在这个概念空间中,Activity被包装,在屏幕上呈现UI,用户看到的整个屏幕或者一个窗口,对于机器来讲,呈现在用户面前的就叫Actvitiy。从分析中我们可以看到,Android使用了Linux的fork机制。在Linux中Fork是很高效的。


一个Android的Activity实际上一个Linux进程,所谓进程具备下面几个要素,
 a.要有一段程序供该进程运行,程序是可以被多个进程共享的。

 b..进程专用的系统堆栈空间。
 c.进程控制块,在linux中具体实现是task_struct
 d.有独立的存储空间。

fork 创造的子进程复制了父亲进程的资源,包括内存的内容task_struct内容,在复制过程中,子进程复制了父进程的task_struct,系统堆栈空间和页面表,而当子进程改变了父进程的变量时候,会通过copy_on_write的手段为所涉及的页面建立一个新的副本。所以只有子进程有改变变量时,子进程才新建了一个页面复制原来页面的内容,基本资源的复制是必须的,整体看上去就像是父进程的独立存储空间也复制了一遍。

 再看看下面Google在讲解Dalvik虚拟机的图片,我们就大体有了Android系统中Actvitiy的实际映射状态有了基本的认识。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/maxleng/archive/2010/04/20/5508488.aspx