1. Información general
En Android
el sistema, DVM
( Dalvik
máquina virtual) y ART
el proceso de servicio del sistema system_server
y el proceso de aplicación son Zygote
creados por el proceso (y Native
el programa, es decir, C/C++
el programa desarrollado por el proceso es init
creado e iniciado por el proceso). Zygote
El proceso también se denomina incubadora. fork(复制进程)
El proceso de aplicación y system_server
el proceso se crean en forma de. Dado que el proceso se creará o Zygote
cuando se inicie , el proceso de aplicación y el proceso creado al pasar pueden obtener una copia de instancia de o internamente .DVM
ART
fork
system_server
DVM
ART
Zygote
Un proceso se init
crea cuando se inicia el proceso Inicialmente, Zygote
el nombre del proceso no es Zygote
, sino que app_process
el nombre se /frameworks/base/cmds/app_process/Android.mk
define en . Zygote
Después de que comience el proceso, el sistema Linux
bajo el sistema pctrl
se llamará app_process
y su nombre se cambiará a Zygote
.
Zygote
es un C/S
modelo Zygote
Como servidor, el proceso Socket
se comunica con otros procesos a través del método. El "otro proceso" aquí se refiere principalmente al proceso de servicio del sistema system_server
.
En Linux
el sistema, fork
al llamar a una función para crear un proceso hijo, la memoria del proceso padre no se copiará, pero los procesos padre e hijo comparten un espacio de memoria, y la copia de memoria solo se realizará cuando el proceso hijo o el El proceso principal modifica los datos de la memoria, por lo tanto, el proceso principal y el proceso secundario tienen su propio espacio de memoria. Antes de eso, solo se compartirá como de solo lectura.
Copy-on-write ( copy-on-write
): el espacio de memoria no se asigna realmente hasta que se modifican los datos, que es una técnica que puede retrasar o incluso evitar la copia de datos. Esta es una optimización del rendimiento del programa, y el propósito de esto es evitar copias innecesarias.
Zygote
Como incubadora, algunos recursos se pueden cargar por adelantado, de modo que fork
el proceso secundario generado pueda usar directamente estos recursos sin recargar. Por ejemplo, system_server
un proceso puede usar directamente funciones, bibliotecas compartidas, clases comunes y recursos temáticos Zygote
en el proceso JNI
.
Zygote
El inicio del proceso funciona de la siguiente manera:
- Llame
AppRuntime/AndroidRuntime.start
al método, creeJava
una máquina virtual y registreJNI
el método para ello; - Ingrese a la capa del marco desde la capa llamando
JNI
al método ;ZygoteInit.main
Native
Java
- proceso de inicio
system_server
; - Cree un nuevo proceso de aplicación creando
ZygoteServer
una solicitud en el lado del servidorSocket
yZygoteServer.runSelectLoop
esperándola a través del método ;AMS
El siguiente es Zygote
el diagrama de tiempo para el arranque:
2 Zygote
guión de inicio
En el proceso de iniciar el proceso de inicio , se menciona que init
el proceso analizará init.rc
el archivo y luego creará y cargará service
el proceso especificado por el campo, y el proceso lo cargará Zygote
el proceso de esta manera . Use la declaración de tipo en el archivo init
para introducir el script de inicio, que está escrito por el lenguaje de inicialización ( ):init.rc
Import
Zygote
Android
Android Init Language
// /system/core/rootdir/init.rc
import /init.environ.rc
import /init.usb.rc
import /init.${
ro.hardware}.rc
import /vendor/etc/init/hw/init.${
ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${
ro.zygote}.rc // ${ro.zygote} 由厂商定义,与平台无关
Se puede observar que init.rc
no se importará directamente un archivo fijo, sino que ro.zygote
se importarán diferentes archivos según el contenido.
A partir de Android 5.0
, comenzamos a admitir 64
programas de 1 bit, Zygote
por lo que existe una diferencia 32
entre 1 bit y 1 64
bit, por lo que usamos ro.zygote
el atributo para controlar el uso de diferentes Zygote
scripts de inicio, de modo que se inicien diferentes versiones del proceso . y Zygote
se inician diferentes versiones del Zygote
proceso ro.zygote
, se tienen los siguientes valores 4
:
init.zygote32.rc
:Zygote
El programa de ejecución correspondiente al proceso esapp_process
(32 bit
modo puro);init.zygote32_64.rc
: Inicia dosZygote
procesos (zygote
yzygote_secondary
), y los programas de ejecución correspondientes sonapp_process32
(modo principal),app_process64
;init.zygote64.rc
:Zygote
El programa de ejecución correspondiente al proceso esapp_process64
(64 bit
modo puro);init.zygote64_32.rc
: Inicia dosZygote
procesos (zygote
yzygote_secondary
), y los programas de ejecución correspondientes sonapp_process64
(modo principal),app_process32
;
Estos Zygote
scripts de inicio se colocan system/core/rootdir
en el directorio de la siguiente manera:
Tomando 64
el procesador de bits como ejemplo, init.zygote64_32.rc
el código es el siguiente:
Hay dos declaraciones de tipo en el script , que indican que se iniciarán Service
dos procesos, uno se llama y el programa de ejecución es como modo principal; el otro se llama y el programa de ejecución es como modo secundario. Otros archivos de script son similares a este.Zygote
zygote
app_process64
zygote_secondary
app_process32
Tomemos init.zygote64_32.rc
, por ejemplo, su dirección de archivo de inicio es /system/bin/app_process64
(figura superior), y app_process64
el código correspondiente está en /frameworks/base/cmds/app_process
el directorio de .
Primero, eche un vistazo a Android.mk
:
// /frameworks/base/cmds/app_process/Android.mk
LOCAL_PATH:= $(call my-dir)
....
app_process_src_files := \
app_main.cpp \
...
LOCAL_MODULE:= app_process
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64
...
Como se puede ver en el código anterior, ya sea app_prcess
o app_prcess32
o app_prcess64
, el archivo fuente correspondiente es app_main.cpp
.
Zygote
proceso de inicio de 3 procesos
init
El proceso se inicia Zygote
principalmente llamando a la función app_main.cpp
en el archivo main
, entre los cuales el proceso se inicia AppRuntime
llamando al método :start
Zygote
// /frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
...
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
// 1
// 如果当前运行在Zygote进程中,则将zygote设置为true
zygote = true; // 2
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
// 3
// 如果当前运行在system_server进程中,则将startSystemServer设置为true
startSystemServer = true; // 4
}
...
}
...
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string(), true /* setProcName */);
}
// 如果运行在zygote进程中
if (zygote) {
// 5
runtime.start("com.android.internal.os.ZygoteInit", args, zygote); // 6
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
Zygote
Los procesos fork
crean subprocesos por sí mismos, por lo que tanto Zygote
el proceso como sus subprocesos pueden ingresar a la función app_main.cpp
de , por lo tanto, para distinguir qué proceso se está ejecutando actualmente en la función,main
main
1
juzgará si arg
el parámetro está incluido en el comentario. --zygote
, si contiene It, significa que main
la función se está ejecutando en Zygote
el proceso y el comentario 2
se zygote
establece en true
. De la misma manera, juzgue si 3
el parámetro está incluido en el comentario . Si está incluido, significa que la ejecución de prueba de la función está en proceso y se establece en el comentario .arg
--start-system-server
main
system_server
4
startSystemServer
true
En el comentario 5
, si zygote
es true
, significa que actualmente se está ejecutando en el proceso, y se llamará zygote
a la función en el comentario . Heredado de , y no anuló el método, por lo tanto, el proceso ingresado en , el código es el siguiente:6
AppRuntime
start
AppRuntime
AndroidRuntime
start
Zygote
AndroidRutime
// /frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
/* start the virtual machine 启动Java虚拟机 */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
// 1
return;
}
onVmCreated(env);
/*
* Register android functions. 为Java虚拟机注册JNI方法
*/
if (startReg(env) < 0) {
// 2
ALOGE("Unable to register all android natives\n");
return;
}
...
// 从app_main的main函数得知className为com.android.internal.os.ZygoteInit
classNameStr = env->NewStringUTF(className); // 3
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
* 将className的"."替换为"/"
*/
char* slashClassName = toSlashClassName(className != NULL ? className : ""); // 4
// 找到 zygoteInit
jclass startClass = env->FindClass(slashClassName); // 5
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
// 找到ZygoteInit的main函数
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V"); // 6
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
// 通过JNI调用ZygoteInit的main方法
env->CallStaticVoidMethod(startClass, startMeth, strArray); // 7
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);
ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
ALOGW("Warning: VM did not shut down cleanly\n");
}
1
Llame a la función en el comentario startVm
para crear Java
una máquina virtual y 2
llame startReg
a la función en el comentario para Java
registrar la máquina virtual JNI
. 3
El valor de en la anotación className
es el parámetro pasado y su valor es com.android.internal.os.ZygoteInit
. Use la función en el comentario 4
para reemplazar con , y asigne el valor reemplazado a , luego busque en el comentario de acuerdo con y llame al método en el comentario después de encontrar . Finalmente, el método será llamado en el comentario . ¿Por qué usar aquí ? Debido a que el método está escrito en el idioma, la lógica de ejecución actual está en , que debe llamarse a través de . De esta forma, se entra en la capa del marco desde la capa .toSlashClassName
className
.
/
com/android/internal/os/ZygoteInit
slashClassName
5
slashClassName
ZygoteInit
ZygoteInit
6
ZygoteInit.main
7
JNI
ZygoteInit.main
JNI
ZygoteInit.main
Java
Native
JNI
Java
Zygote
Native
Java
Después JNI
de llamar ZygoteInit.main
al método, Zygote
ingresa Java
a la capa del marco. Antes de eso, ningún código ingresó Java
a la capa del marco. En otras palabras, usted Zygote
creó Java
la capa del marco. ZygoteInit.main
El código del método es el siguiente:
// /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
// ZygoteServer是Zygote进程的Socket通讯服务端的管理类
ZygoteServer zygoteServer = null;
...
Runnable caller;
try {
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload(bootTimingsTraceLog); // 1
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
...
zygoteServer = new ZygoteServer(isPrimaryZygote); // 2
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer); // 3
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
Log.i(TAG, "Accepting command socket connections");
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList); // 4
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
...
}
Los comentarios 1
precargan clases y recursos. El comentario 2
crea un canal al Server
final Socket
que responde a ActivityManagerService
la solicitud Zygote
para crear un nuevo proceso de solicitud. 3
Inicie el proceso en el comentario , de modo que el proceso también inicie system_server
los servicios del sistema . El método se llama en el system_server
comentario para esperar una solicitud para crear un nuevo proceso.4
ZygoteServer.runSelectLoop
AMS
De lo anterior, podemos ver que ZygoteInit.main
el método hace principalmente 4
dos cosas:
- precargar clases y recursos ;
- El
Server
lado de la creaciónSocket
se utiliza para responder aActivityManagerService
la solicitud de crear un nuevo proceso de solicitud; - Inicie
system_server
el proceso, para que el servicio del sistema también seasystem_server
iniciado por ; - Esperando
ActivityManagerService
una solicitud para crear un nuevo proceso de solicitud;
referencia
Serie [Lanzamiento del sistema Android 10]: Zygote (incubadora de procesos)