Android系统zygote进程启动过程源码分析
2014-12-24 13:00
691 查看
一、简介
在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,这也许就是为什么要把它称为Zygote(受精卵)的原因。
zygote,ps中看到的进程名叫zygote,其最初的名字是app_process,通过直接调用pctrl把名字给改成了”zygote”
二、zygote在android中主要有三个作用:
1. 系统启动时init进程会创建Zygote进程,Zygote进程负责后续Android应用程序框架层的其它进程的创建和启动工作。
2. Zygote进程会首先创建一个SystemServer进程,SystemServer进程负责启动系统的关键服务,如包管理服务PackageManagerService和应用程序组件管理服务ActivityManagerService。
3. 当我们需要启动一个Android应用程序时,ActivityManagerService会通过Socket进程间通信机制,通知Zygote进程为这个应用程序创建一个新的进程。
三、zygote代码组成
在android中提到zygote,主要两块:
一个是C/C++编写的zygote,主要用来为应用和SystemService fork进程的。
/dalvik/vm/native/dalvik_system_Zygote.c
一个是java编写的zygote接口,负责为应用和service调用C/C++ zygote的接口执行fork,从而创建VM进程。
Zygote系统代码组成及其调用结构:
Zygote.java
提供访问Dalvik “zygote”的接口。主要是包装Linux系统的Fork,以建立一个新的VM实例进程。
ZygoteConnection.java
Zygote的套接口连接管理及其参数解析。其他Actvitiy建立进程请求是通过套接口发送命令参数给Zygote。
ZygoteInit.java
Zygote的main函数入口。
说明:在android中,service主要有NativeService和SystemService。SystemService主要是指系统中service,比如,InputMethodService、ActivityManagerService等。
Zygote系统代码层次调用(frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中)
main()
registerZygoteSocket();
startSystemServer()…
runSelectLoopMode()
Accept socket connection
Conntecion.RunOnce()
Read argument
folkAndSpecialize
folkAndSpecialize使用Native函数Dalvik_dalvik_system_Zygote_forkAndSpecialize(/dalvik/vm/native/dalvik_system_Zygote.c )
五、启动流程
Android系统所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统启动的过程,由init进程创建的。在系统启动脚本system/core/rootdir/init.rc文件中,我们可以看到启动Zygote进程的脚本命令:
[plain] view
plaincopy
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
onrestart restart media
onrestart restart netd
前面的关键字service告诉init进程创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process,后面是要传给app_process的参数。
接下来的socket关键字表示这个zygote进程需要一个名称为"zygote"的socket资源,这样,系统启动后,我们就可以在/dev/socket目录下看到有一个名为zygote的文件。这里定义的socket的类型为unix domain socket,它是用来作本地进程间通信用的,具体可以参考前面一篇文章Android学习启动篇提到的一书《Linux内核源代码情景分析》的第七章--基于socket的进程间通信。前面我们说到的ActivityManagerService就是通这个socket来和zygote进程通信请求fork一个应用程序进程的了。
最后的一系列onrestart关键字表示这个zygote进程重启时需要执行的命令。
我们先来看看它的启动序列图:
下面我们就详细分析每一个步骤。
Step 1、我们就知道Zygote进程要执行的程序便是system/bin/app_process了,它的源代码位于frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。
源码:
/*
* Main entry of app process.
*
* Starts the interpreted runtime, then starts up the application.
*
*/
#define LOG_TAG "appproc"
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <utils/Log.h>
#include <cutils/process_name.h>
#include <cutils/memory.h>
#include <android_runtime/AndroidRuntime.h>
#include <stdio.h>
#include <unistd.h>
namespace android {
void app_usage()
{
fprintf(stderr,
"Usage: app_process [java-options] cmd-dir start-class-name [options]\n");
}
status_t app_init(const char* className, int argc, const char* const argv[])
{
LOGV("Entered app_init()!\n");
AndroidRuntime* jr = AndroidRuntime::getRuntime();
jr->callMain(className, argc, argv);
LOGV("Exiting app_init()!\n");
return NO_ERROR;
}
//定义AppRuntime类
//继承于AndroidRuntime类, AndroidRuntime类定义在frameworks/base/core/jni/AndroidRuntime.cpp
//当AppRuntime对象创建时,会调用其父类AndroidRuntime的构造函数,而在AndroidRuntime类的构造函数里面,会将this指针保存在静态全局变量gCurRuntime中,这样,当其它地方需要使用这个AppRuntime对象时,就可以通过同一个文件中的getRuntime()函数来获取这个对象的指针
class AppRuntime : public AndroidRuntime
{
public:
AppRuntime()
: mParentDir(NULL)
, mClassName(NULL)
, mArgC(0)
, mArgV(NULL)
{
}
#if 0
// this appears to be unused
const char* getParentDir() const
{
return mParentDir;
}
#endif
const char* getClassName() const
{
return mClassName;
}
virtual void onStarted()
{
sp<ProcessState> proc = ProcessState::self();
if (proc->supportsProcesses()) {
LOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
app_init(mClassName, mArgC, mArgV);
if (ProcessState::self()->supportsProcesses()) {
IPCThreadState::self()->stopProcess();
}
}
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
if (proc->supportsProcesses()) {
LOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
}
virtual void onExit(int code)
{
if (mClassName == NULL) {
// if zygote
if (ProcessState::self()->supportsProcesses()) {
IPCThreadState::self()->stopProcess();
}
}
AndroidRuntime::onExit(code);
}
const char* mParentDir;
const char* mClassName;
int mArgC;
const char* const* mArgV;
};
}
using namespace android;
/*
* sets argv0 to as much of newArgv0 as will fit
*/
static void setArgv0(const char *argv0, const char *newArgv0)
{
strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
}
//主要做了什么?
//初始化了运行时环境,并且建立虚拟机创建一个AppRuntime变量,然后调用它的start成员函数
//运行再com.android.internal.os.ZygoteInit的main函数
int main(int argc, const char* const argv[])
{
//这几个参数重要,参数都在argv[]里面传进来的
//service zygote /system/bin/app_process -Xzygote
/system/bin --zygote --start-system-server
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--;
AppRuntime runtime;
const char* argv0 = argv[0];
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
// Everything up to '--' or first non '-' arg goes to the vm
int i = runtime.addVmArguments(argc, argv);
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
const char* parentDir = NULL;
const char* niceName = NULL;
const char* className = NULL;
while (i < argc) {
const char* arg = argv[i++];
if (!parentDir) {
parentDir = arg;
} else if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = "zygote";
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName = arg + 12;
} else {
className = arg;
break;
}
}
if (niceName && *niceName) {
setArgv0(argv0, niceName);
//改名字为zygote,不知道windows下的怎么改、linux下的可以用pctrl系统调用
set_process_name(niceName);
}
runtime.mParentDir = parentDir;
if (zygote) {
//在init.rc文件中,设置了app_process(也就是zygote)启动参数--zygote和--start-system-server,最终会执行
//这里的参数startSystemServer为true,表示要启动SystemServer组件。由于AppRuntime没有实现自己的start函数,它继承了父类AndroidRuntime的start函数
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
} else if (className) {
// Remainder of args get passed to startup class main()
runtime.mClassName = className;
runtime.mArgC = argc - i;
runtime.mArgV = argv + i;
runtime.start("com.android.internal.os.RuntimeInit",
application ? "application" : "tool");
} else {
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
return 10;
}
}
Step2、frameworks/base/core/jni/AndroidRuntime.cpp文件
[cpp] view
plaincopy
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*/
void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
//传人参数为:"com.android.internal.os.ZygoteInit"和"start-system-server"
......
char* slashClassName = NULL;
char* cp;
JNIEnv* env;
......
/* start the virtual machine */
//启动虚拟机,自己可以进去看它的源码
if (startVm(&mJavaVM, &env) != 0)
goto bail;
/*
* Register android functions.
*/
//JNI注册,其实就是注册一些JAVA中native函数在C++层对应的实现函数
if (startReg(env) < 0) {
LOGE("Unable to register all android natives\n");
goto bail;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we only have one argument, the class name. Create an
* array to hold it.
*/
//下面这些话,都是把c++的字符串转成JNI字符串
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring startSystemServerStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(2, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
startSystemServerStr = env->NewStringUTF(startSystemServer ?
"true" : "false");
env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
jclass startClass;
jmethodID startMeth;
slashClassName = strdup(className);
for (cp = slashClassName; *cp != '\0'; cp++)
if (*cp == '.')
*cp = '/';
startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
......
} else {
// 下面调用的就是com.android.internal.os.ZygoteInit类的main函数
startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
......
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
......
}
}
......
}
这个函数的作用是启动Android系统运行时库,它主要做了三件事情,一是调用函数startVM启动虚拟机,二是调用函数startReg注册JNI方法,三是调用了com.android.internal.os.ZygoteInit类的main函数。
Step 3.frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
[java] view
plaincopy
public class ZygoteInit {
......
public static void main(String argv[]) {
try {
......
registerZygoteSocket(); //创建了一个socket接口,用来和
ActivityManagerService通讯
......
......
if (argv[1].equals("true")) {
startSystemServer(); //启动SystemServer组件
} else if (!argv[1].equals("false")) {
......
}
......
if (ZYGOTE_FORK_MODE) {
......
} else {
runSelectLoopMode(); //进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程
}
......
} catch (MethodAndArgsCaller caller) {
......
} catch (RuntimeException ex) {
......
}
}
......
}
3.1、registerZygoteSocket函数
[java] view
plaincopy
public class ZygoteInit {
......
private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";
......
/**
* Registers a server socket for zygote command connections
*
* @throws RuntimeException when open fails
*/
private static void registerZygoteSocket() {
if (sServerSocket == null) {
int fileDesc;
try {
String env = System.getenv(ANDROID_SOCKET_ENV);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
......
}
try {
//这个socket接口是通过文件描述符来创建的,这个文件描符代表的就是我们前面说的/dev/socket/zygote文件了。这个文件描述符是通过环境变量ANDROID_SOCKET_ENV得到的
sServerSocket = new LocalServerSocket(
createFileDescriptor(fileDesc));
} catch (IOException ex) {
.......
}
}
}
......
}
那么,这个环境变量的值又是由谁来设置的呢?我们知道,系统启动脚本文件system/core/rootdir/init.rc是由init进程来解释执行的,而init进程的源代码位于system/core/init目录中,在init.c文件中,是由service_start函数来解释init.rc文件中的service命令的:
[cpp] view
plaincopy
void service_start(struct service *svc, const char *dynamic_args)
{
......
pid_t pid;
......
pid = fork();
if (pid == 0) {
struct socketinfo *si;
......
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);
if (s >= 0) {
publish_socket(si->name, s);
}
}
......
}
......
}
每一个service命令都会促使init进程调用fork函数来创建一个新的进程,在新的进程里面,会分析里面的socket选项,对于每一个socket选项,都会通过create_socket函数来在/dev/socket目录下创建一个文件,在这个场景中,这个文件便是zygote了,然后得到的文件描述符通过publish_socket函数写入到环境变量中去:
[cpp] view
plaincopy
static void publish_socket(const char *name, int fd)
{
char key[64] = ANDROID_SOCKET_ENV_PREFIX;
char val[64];
strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
name,
sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
snprintf(val, sizeof(val), "%d", fd);
add_environment(key, val);
/* make sure we don't close-on-exec */
fcntl(fd, F_SETFD, 0);
}
这里传进来的参数name值为"zygote",而ANDROID_SOCKET_ENV_PREFIX在system/core/include/cutils/sockets.h定义为:
[cpp] view
plaincopy
#define ANDROID_SOCKET_ENV_PREFIX "ANDROID_SOCKET_"
因此,这里就把上面得到的文件描述符写入到以"ANDROID_SOCKET_zygote"为key值的环境变量中。又因为上面的ZygoteInit.registerZygoteSocket函数与这里创建socket文件的create_socket函数是运行在同一个进程中,因此,上面的ZygoteInit.registerZygoteSocket函数可以直接使用这个文件描述符来创建一个Java层的LocalServerSocket对象。如果其它进程也需要打开这个/dev/socket/zygote文件来和Zygote进程进行通信,那就必须要通过文件名来连接这个LocalServerSocket了,ActivityManagerService是通过Process.start函数来创建一个新的进程的,而Process.start函数会首先通过Socket连接到Zygote进程中,最终由Zygote进程来完成创建新的应用程序进程,而Process类是通过openZygoteSocketIfNeeded函数来连接到Zygote进程中的Socket的:
[java] view
plaincopy
public class Process {
......
private static void openZygoteSocketIfNeeded()
throws ZygoteStartFailedEx {
......
for (int retry = 0
; (sZygoteSocket == null) && (retry < (retryCount + 1))
; retry++ ) {
......
try {
sZygoteSocket = new LocalSocket();
sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,
LocalSocketAddress.Namespace.RESERVED));
sZygoteInputStream
= new DataInputStream(sZygoteSocket.getInputStream());
sZygoteWriter =
new BufferedWriter(
new OutputStreamWriter(
sZygoteSocket.getOutputStream()),
256);
......
} catch (IOException ex) {
......
}
}
......
}
......
}
这里的ZYGOTE_SOCKET定义为:
[java] view
plaincopy
public class Process {
......
private static final String ZYGOTE_SOCKET = "zygote";
......
}
它刚好就是对应/dev/socket目录下的zygote文件了。
3.2、startSystemServer函数
SystemServer进程启动参见下一篇《Android系统SystemServer进程启动过程源码分析》
3.3、runSelectLoopMode函数
[java] view
plaincopy
public class ZygoteInit {
......
private static void runSelectLoopMode() throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList();
ArrayList<ZygoteConnection> peers = new ArrayList();
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
int loopCount = GC_LOOP_COUNT;
//无限循环,等待ActivityManagerService来连接这个Socket
//ZygoteInit会监听domain socket “dev/socket/zygote”,以执行framework层指定的fork操作
while (true) {
int index;
......
try {
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done;
//调用ZygoteConnection.runOnce函数来创建新的应用程序
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
......
}
在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,这也许就是为什么要把它称为Zygote(受精卵)的原因。
zygote,ps中看到的进程名叫zygote,其最初的名字是app_process,通过直接调用pctrl把名字给改成了”zygote”
二、zygote在android中主要有三个作用:
1. 系统启动时init进程会创建Zygote进程,Zygote进程负责后续Android应用程序框架层的其它进程的创建和启动工作。
2. Zygote进程会首先创建一个SystemServer进程,SystemServer进程负责启动系统的关键服务,如包管理服务PackageManagerService和应用程序组件管理服务ActivityManagerService。
3. 当我们需要启动一个Android应用程序时,ActivityManagerService会通过Socket进程间通信机制,通知Zygote进程为这个应用程序创建一个新的进程。
三、zygote代码组成
在android中提到zygote,主要两块:
一个是C/C++编写的zygote,主要用来为应用和SystemService fork进程的。
/dalvik/vm/native/dalvik_system_Zygote.c
一个是java编写的zygote接口,负责为应用和service调用C/C++ zygote的接口执行fork,从而创建VM进程。
Zygote系统代码组成及其调用结构:
Zygote.java
提供访问Dalvik “zygote”的接口。主要是包装Linux系统的Fork,以建立一个新的VM实例进程。
ZygoteConnection.java
Zygote的套接口连接管理及其参数解析。其他Actvitiy建立进程请求是通过套接口发送命令参数给Zygote。
ZygoteInit.java
Zygote的main函数入口。
说明:在android中,service主要有NativeService和SystemService。SystemService主要是指系统中service,比如,InputMethodService、ActivityManagerService等。
Zygote系统代码层次调用(frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中)
main()
registerZygoteSocket();
startSystemServer()…
runSelectLoopMode()
Accept socket connection
Conntecion.RunOnce()
Read argument
folkAndSpecialize
folkAndSpecialize使用Native函数Dalvik_dalvik_system_Zygote_forkAndSpecialize(/dalvik/vm/native/dalvik_system_Zygote.c )
五、启动流程
Android系统所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统启动的过程,由init进程创建的。在系统启动脚本system/core/rootdir/init.rc文件中,我们可以看到启动Zygote进程的脚本命令:
[plain] view
plaincopy
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
onrestart restart media
onrestart restart netd
前面的关键字service告诉init进程创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process,后面是要传给app_process的参数。
接下来的socket关键字表示这个zygote进程需要一个名称为"zygote"的socket资源,这样,系统启动后,我们就可以在/dev/socket目录下看到有一个名为zygote的文件。这里定义的socket的类型为unix domain socket,它是用来作本地进程间通信用的,具体可以参考前面一篇文章Android学习启动篇提到的一书《Linux内核源代码情景分析》的第七章--基于socket的进程间通信。前面我们说到的ActivityManagerService就是通这个socket来和zygote进程通信请求fork一个应用程序进程的了。
最后的一系列onrestart关键字表示这个zygote进程重启时需要执行的命令。
我们先来看看它的启动序列图:
下面我们就详细分析每一个步骤。
Step 1、我们就知道Zygote进程要执行的程序便是system/bin/app_process了,它的源代码位于frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。
源码:
/*
* Main entry of app process.
*
* Starts the interpreted runtime, then starts up the application.
*
*/
#define LOG_TAG "appproc"
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <utils/Log.h>
#include <cutils/process_name.h>
#include <cutils/memory.h>
#include <android_runtime/AndroidRuntime.h>
#include <stdio.h>
#include <unistd.h>
namespace android {
void app_usage()
{
fprintf(stderr,
"Usage: app_process [java-options] cmd-dir start-class-name [options]\n");
}
status_t app_init(const char* className, int argc, const char* const argv[])
{
LOGV("Entered app_init()!\n");
AndroidRuntime* jr = AndroidRuntime::getRuntime();
jr->callMain(className, argc, argv);
LOGV("Exiting app_init()!\n");
return NO_ERROR;
}
//定义AppRuntime类
//继承于AndroidRuntime类, AndroidRuntime类定义在frameworks/base/core/jni/AndroidRuntime.cpp
//当AppRuntime对象创建时,会调用其父类AndroidRuntime的构造函数,而在AndroidRuntime类的构造函数里面,会将this指针保存在静态全局变量gCurRuntime中,这样,当其它地方需要使用这个AppRuntime对象时,就可以通过同一个文件中的getRuntime()函数来获取这个对象的指针
class AppRuntime : public AndroidRuntime
{
public:
AppRuntime()
: mParentDir(NULL)
, mClassName(NULL)
, mArgC(0)
, mArgV(NULL)
{
}
#if 0
// this appears to be unused
const char* getParentDir() const
{
return mParentDir;
}
#endif
const char* getClassName() const
{
return mClassName;
}
virtual void onStarted()
{
sp<ProcessState> proc = ProcessState::self();
if (proc->supportsProcesses()) {
LOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
app_init(mClassName, mArgC, mArgV);
if (ProcessState::self()->supportsProcesses()) {
IPCThreadState::self()->stopProcess();
}
}
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
if (proc->supportsProcesses()) {
LOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
}
virtual void onExit(int code)
{
if (mClassName == NULL) {
// if zygote
if (ProcessState::self()->supportsProcesses()) {
IPCThreadState::self()->stopProcess();
}
}
AndroidRuntime::onExit(code);
}
const char* mParentDir;
const char* mClassName;
int mArgC;
const char* const* mArgV;
};
}
using namespace android;
/*
* sets argv0 to as much of newArgv0 as will fit
*/
static void setArgv0(const char *argv0, const char *newArgv0)
{
strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
}
//主要做了什么?
//初始化了运行时环境,并且建立虚拟机创建一个AppRuntime变量,然后调用它的start成员函数
//运行再com.android.internal.os.ZygoteInit的main函数
int main(int argc, const char* const argv[])
{
//这几个参数重要,参数都在argv[]里面传进来的
//service zygote /system/bin/app_process -Xzygote
/system/bin --zygote --start-system-server
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--;
AppRuntime runtime;
const char* argv0 = argv[0];
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
// Everything up to '--' or first non '-' arg goes to the vm
int i = runtime.addVmArguments(argc, argv);
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
const char* parentDir = NULL;
const char* niceName = NULL;
const char* className = NULL;
while (i < argc) {
const char* arg = argv[i++];
if (!parentDir) {
parentDir = arg;
} else if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = "zygote";
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName = arg + 12;
} else {
className = arg;
break;
}
}
if (niceName && *niceName) {
setArgv0(argv0, niceName);
//改名字为zygote,不知道windows下的怎么改、linux下的可以用pctrl系统调用
set_process_name(niceName);
}
runtime.mParentDir = parentDir;
if (zygote) {
//在init.rc文件中,设置了app_process(也就是zygote)启动参数--zygote和--start-system-server,最终会执行
//这里的参数startSystemServer为true,表示要启动SystemServer组件。由于AppRuntime没有实现自己的start函数,它继承了父类AndroidRuntime的start函数
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
} else if (className) {
// Remainder of args get passed to startup class main()
runtime.mClassName = className;
runtime.mArgC = argc - i;
runtime.mArgV = argv + i;
runtime.start("com.android.internal.os.RuntimeInit",
application ? "application" : "tool");
} else {
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
return 10;
}
}
Step2、frameworks/base/core/jni/AndroidRuntime.cpp文件
[cpp] view
plaincopy
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*/
void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
//传人参数为:"com.android.internal.os.ZygoteInit"和"start-system-server"
......
char* slashClassName = NULL;
char* cp;
JNIEnv* env;
......
/* start the virtual machine */
//启动虚拟机,自己可以进去看它的源码
if (startVm(&mJavaVM, &env) != 0)
goto bail;
/*
* Register android functions.
*/
//JNI注册,其实就是注册一些JAVA中native函数在C++层对应的实现函数
if (startReg(env) < 0) {
LOGE("Unable to register all android natives\n");
goto bail;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we only have one argument, the class name. Create an
* array to hold it.
*/
//下面这些话,都是把c++的字符串转成JNI字符串
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring startSystemServerStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(2, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
startSystemServerStr = env->NewStringUTF(startSystemServer ?
"true" : "false");
env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
jclass startClass;
jmethodID startMeth;
slashClassName = strdup(className);
for (cp = slashClassName; *cp != '\0'; cp++)
if (*cp == '.')
*cp = '/';
startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
......
} else {
// 下面调用的就是com.android.internal.os.ZygoteInit类的main函数
startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
......
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
......
}
}
......
}
这个函数的作用是启动Android系统运行时库,它主要做了三件事情,一是调用函数startVM启动虚拟机,二是调用函数startReg注册JNI方法,三是调用了com.android.internal.os.ZygoteInit类的main函数。
Step 3.frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
[java] view
plaincopy
public class ZygoteInit {
......
public static void main(String argv[]) {
try {
......
registerZygoteSocket(); //创建了一个socket接口,用来和
ActivityManagerService通讯
......
......
if (argv[1].equals("true")) {
startSystemServer(); //启动SystemServer组件
} else if (!argv[1].equals("false")) {
......
}
......
if (ZYGOTE_FORK_MODE) {
......
} else {
runSelectLoopMode(); //进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程
}
......
} catch (MethodAndArgsCaller caller) {
......
} catch (RuntimeException ex) {
......
}
}
......
}
3.1、registerZygoteSocket函数
[java] view
plaincopy
public class ZygoteInit {
......
private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";
......
/**
* Registers a server socket for zygote command connections
*
* @throws RuntimeException when open fails
*/
private static void registerZygoteSocket() {
if (sServerSocket == null) {
int fileDesc;
try {
String env = System.getenv(ANDROID_SOCKET_ENV);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
......
}
try {
//这个socket接口是通过文件描述符来创建的,这个文件描符代表的就是我们前面说的/dev/socket/zygote文件了。这个文件描述符是通过环境变量ANDROID_SOCKET_ENV得到的
sServerSocket = new LocalServerSocket(
createFileDescriptor(fileDesc));
} catch (IOException ex) {
.......
}
}
}
......
}
那么,这个环境变量的值又是由谁来设置的呢?我们知道,系统启动脚本文件system/core/rootdir/init.rc是由init进程来解释执行的,而init进程的源代码位于system/core/init目录中,在init.c文件中,是由service_start函数来解释init.rc文件中的service命令的:
[cpp] view
plaincopy
void service_start(struct service *svc, const char *dynamic_args)
{
......
pid_t pid;
......
pid = fork();
if (pid == 0) {
struct socketinfo *si;
......
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);
if (s >= 0) {
publish_socket(si->name, s);
}
}
......
}
......
}
每一个service命令都会促使init进程调用fork函数来创建一个新的进程,在新的进程里面,会分析里面的socket选项,对于每一个socket选项,都会通过create_socket函数来在/dev/socket目录下创建一个文件,在这个场景中,这个文件便是zygote了,然后得到的文件描述符通过publish_socket函数写入到环境变量中去:
[cpp] view
plaincopy
static void publish_socket(const char *name, int fd)
{
char key[64] = ANDROID_SOCKET_ENV_PREFIX;
char val[64];
strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
name,
sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
snprintf(val, sizeof(val), "%d", fd);
add_environment(key, val);
/* make sure we don't close-on-exec */
fcntl(fd, F_SETFD, 0);
}
这里传进来的参数name值为"zygote",而ANDROID_SOCKET_ENV_PREFIX在system/core/include/cutils/sockets.h定义为:
[cpp] view
plaincopy
#define ANDROID_SOCKET_ENV_PREFIX "ANDROID_SOCKET_"
因此,这里就把上面得到的文件描述符写入到以"ANDROID_SOCKET_zygote"为key值的环境变量中。又因为上面的ZygoteInit.registerZygoteSocket函数与这里创建socket文件的create_socket函数是运行在同一个进程中,因此,上面的ZygoteInit.registerZygoteSocket函数可以直接使用这个文件描述符来创建一个Java层的LocalServerSocket对象。如果其它进程也需要打开这个/dev/socket/zygote文件来和Zygote进程进行通信,那就必须要通过文件名来连接这个LocalServerSocket了,ActivityManagerService是通过Process.start函数来创建一个新的进程的,而Process.start函数会首先通过Socket连接到Zygote进程中,最终由Zygote进程来完成创建新的应用程序进程,而Process类是通过openZygoteSocketIfNeeded函数来连接到Zygote进程中的Socket的:
[java] view
plaincopy
public class Process {
......
private static void openZygoteSocketIfNeeded()
throws ZygoteStartFailedEx {
......
for (int retry = 0
; (sZygoteSocket == null) && (retry < (retryCount + 1))
; retry++ ) {
......
try {
sZygoteSocket = new LocalSocket();
sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,
LocalSocketAddress.Namespace.RESERVED));
sZygoteInputStream
= new DataInputStream(sZygoteSocket.getInputStream());
sZygoteWriter =
new BufferedWriter(
new OutputStreamWriter(
sZygoteSocket.getOutputStream()),
256);
......
} catch (IOException ex) {
......
}
}
......
}
......
}
这里的ZYGOTE_SOCKET定义为:
[java] view
plaincopy
public class Process {
......
private static final String ZYGOTE_SOCKET = "zygote";
......
}
它刚好就是对应/dev/socket目录下的zygote文件了。
3.2、startSystemServer函数
SystemServer进程启动参见下一篇《Android系统SystemServer进程启动过程源码分析》
3.3、runSelectLoopMode函数
[java] view
plaincopy
public class ZygoteInit {
......
private static void runSelectLoopMode() throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList();
ArrayList<ZygoteConnection> peers = new ArrayList();
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
int loopCount = GC_LOOP_COUNT;
//无限循环,等待ActivityManagerService来连接这个Socket
//ZygoteInit会监听domain socket “dev/socket/zygote”,以执行framework层指定的fork操作
while (true) {
int index;
......
try {
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done;
//调用ZygoteConnection.runOnce函数来创建新的应用程序
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
......
}
相关文章推荐
- Android系统SystemServer进程启动过程源码分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析(2)
- Android Zygote系统进程启动过程分析(Android N)
- Android系统进程Zygote启动过程的源代码分析(老罗的作品)
- Android系统进程Zygote启动过程的源代码分析
- Android 8.0系统源码分析--Zygote启动过程分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析(1)
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析(3)
- Android 8.0系统源码分析--应用进程启动过程分析
- Android系统进程Zygote启动过程的源代码分析
- Android系统进程Zygote启动过程的源代码分析