i.mx6 Android5.1.1 Zygote
0. 总结:
0.1 相关源码目录:
framework/base/cmds/app_process/app_main.cpp
frameworks/base/core/jni/AndroidRuntime.cpp
frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
0.2 流程总结:
1. init.rc启动进入app_main.cpp
2. app_main.cpp查看init.rc给的相关参数,进行处理进入AndroidRuntime.cpp
3. AndroidRuntime.cpp启动虚拟机,初始化JNI,然后根据函数名通过反射机制加载zygote,进入JAVA层zygote的Zygote.java
4. 注册socket,加载各种资源(类,共享资源,共享库),启动SystemServer服务,循环接收socket,创建新进程
1. native层init.rc(进入zygote)

#名字为zygote的服务,可执行文件路径为/system/bin/app_process,后面几个为带的参数
#建立socket通讯
#运行后,只执行一次的几个服务
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd

2. native层的app_main.cpp
/framework/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[]){ //参数argv为:-Xzygote /system/bin --zygote --start-system-server
if (prctl(PR_SET_NO_NEW_PRIVS, , , , ) < ) {
// Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
// EINVAL. Don't die on such kernels.
if (errno != EINVAL) {
LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
return ;
}
} AppRuntime runtime(argv[], computeArgBlockSize(argc, argv));
// Process command line arguments
// ignore argv[0]
argc--;
argv++; int i;
for (i = ; i < argc; i++) {
if (argv[i][] != '-') {
break;
}
if (argv[i][] == '-' && argv[i][] == ) {
++i; // Skip --.
break;
}
runtime.addOption(strdup(argv[i]));
} // Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className; ++i; // Skip unused "parent dir" argument.
while (i < argc) { const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == ) {
//这里我们有
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == ) {
startSystemServer = true; //这里我们有
} else if (strcmp(arg, "--application") == ) {
application = true; //这里是进入应用,我们没有
} else if (strncmp(arg, "--nice-name=", ) == ) {
niceName.setTo(arg + ); //没有
} else if (strncmp(arg, "--", ) != break;
} else {
--i;
break;
}
}
Vector<String8>if (!className.isEmpty()) {
// We're not in zygote mode, the only argument we need to pass
// to RuntimeInit is the application argument.
//
// The Remainder of args get passed to startup class main(). Make
// copies of them before we overwrite them with the process name.
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
} else {
// We're in zygote mode.
maybeCreateDalvikCache();
//添加所有参数
}
} if (!niceName.isEmpty()) { //没有,不进入
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
} if (zygote) {
//进入这里,启动zygote
//args为:start-system-server --abi-list=armeabi-v71,armeabi -Xzygote /system/bin --zygote --start-system-server
runtime.start("com.android.internal.os.ZygoteInit", args);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return ;
}
}
3. native层的AndroidRuntime
frameworks/base/core/jni/AndroidRuntime.cpp
接着往下看:runtime.start
记住,我们传进来的className为:com.android.internal.os.ZygoteInit
参数为options为:start-system-server --abi-list=armeabi-v71,armeabi -Xzygote /system/bin --zygote --start-system-server
void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
ALOGD(">>>>>> START %s uid %d <<<<<<\n",
className != NULL ? className : "(unknown)", getuid()); static const String8 startSystemServer("start-system-server"); /*
* 'startSystemServer == true' means runtime is obsolete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
for (size_t i = ; i < options.size(); ++i) {
if (options[i] == startSystemServer) {//我们参数有,进入
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = ;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
}
//修改环境变量ANDROID_ROOT: /system
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
return;
}
setenv("ANDROID_ROOT", rootDir, );
} //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack); /* start the virtual machine */
//启动虚拟机,以后再分析
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env) != ) {
return;
}
onVmCreated(env); /*
* Register android functions.初始化JNI函数
*/
if (startReg(env) < ) {
ALOGE("Unable to register all android natives\n");
return;
} /*
* We want to call main() with a String array with arguments in it.
* At present we have two arguments, the class name and an option string.
* Create an array to hold them. 下面都是JNI的用法了,具体去查看JNI那章的博客
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
/*
*下面这一串代码就是通过JNI找到ZygoteInit.cpp,然后跳进去,流程是:
*1.找到String类,然后创建一个String = com.android.internal.os.ZygoteInit(这个变量是className参数传进来的)
*2.将com.android.internal.os.ZygoteInit转换成com/android/internal/os/ZygoteInit
*3.查找上面的com/android/internal/os/ZygoteInit这个类中的main函数,
*4.跳入main中
*/
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(options.size() + , stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, , classNameStr);
for (size_t i = ; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + , optionsStr);
} /*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
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 {
//在这里通过反射,正式进入JAVA层的zygote:根据上面的注释,可知这里的startClass为Zygote, startMeth为main
//strArry为参数:start-system-server --abi-list=armeabi-v71,armeabi -Xzygote /system/bin --zygote --start-system-server(不是很确定,应该是这个)
env->CallStaticVoidMethod(startClass, startMeth, strArray); #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() != )
ALOGW("Warning: VM did not shut down cleanly\n");
}
4. JAVA层的Zygote.java
frameworks/base/core/java/com/android/internal/os
ZygoteInit.java函数中的main中
参数如上所分析的argv为:start-system-server --abi-list=armeabi-v71,armeabi -Xzygote /system/bin --zygote --start-system-server
public static void main(String argv[]) {
try {
// Start profiling the zygote initialization.
// 不懂,以后看
SamplingProfilerIntegration.start(); boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true; //看上面的参数,这里有
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length()); //--abi-list: 这里有
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length()); //这个没有
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
} if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
//注册zygote的socket,我们socketname为默认的zygote
registerZygoteSocket(socketName);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
//注意:这个很重要,加载各种资源
preload();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis()); // Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot(); // Do an initial gc to clean up after startup
gc(); // Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false);
//在这里启动systemserver
if (startSystemServer) {
startSystemServer(abiList, socketName);
} Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList); closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
5. JAVA层的preload
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
static void preload() {
Log.d(TAG, "begin preload");
preloadClasses(); //加载类
preloadResources(); //加载资源
preloadOpenGL(); //加载OpenGL,这个是跟显示有关的图形库
preloadSharedLibraries(); //加载共享库
// Ask the WebViewFactory to do any initialization that must run in the zygote process,
// for memory sharing purposes.
WebViewFactory.prepareWebViewInZygote(); //加载???,等会再说
Log.d(TAG, "end preload"); //打印log,显示加载完成
}
5.1 加载类preloadClasses
这里用到的反射,忘记了可以看看:语言方面的知识
private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
private static void preloadClasses() {
final VMRuntime runtime = VMRuntime.getRuntime(); InputStream is;
try {
is = new FileInputStream(PRELOADED_CLASSES); //在这里面是预加载的类
} catch (FileNotFoundException e) {
Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
return;
} Log.i(TAG, "Preloading classes...");
long startTime = SystemClock.uptimeMillis(); // Drop root perms while running static initializers.
setEffectiveGroup(UNPRIVILEGED_GID);
setEffectiveUser(UNPRIVILEGED_UID); // Alter the target heap utilization. With explicit GCs this
// is not likely to have any effect.
float defaultUtilization = runtime.getTargetHeapUtilization();
runtime.setTargetHeapUtilization(0.8f); // Start with a clean slate.
System.gc();
runtime.runFinalizationSync();
Debug.startAllocCounting(); try {
BufferedReader br
= new BufferedReader(new InputStreamReader(is), 256); int count = 0;
String line;
while ((line = br.readLine()) != null) { //一行一行的读取出来
// Skip comments and blank lines.
line = line.trim();
if (line.startsWith("#") || line.equals("")) {
continue;
} try {
if (false) {
Log.v(TAG, "Preloading " + line + "...");
}
Class.forName(line); //注意:在这里加载的,是通过类名进行反射
if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
if (false) {
Log.v(TAG,
" GC at " + Debug.getGlobalAllocSize());
}
System.gc();
runtime.runFinalizationSync();
Debug.resetGlobalAllocSize();
}
count++;
} catch (ClassNotFoundException e) {
Log.w(TAG, "Class not found for preloading: " + line);
} catch (UnsatisfiedLinkError e) {
Log.w(TAG, "Problem preloading " + line + ": " + e);
} catch (Throwable t) {
Log.e(TAG, "Error preloading " + line + ".", t);
if (t instanceof Error) {
throw (Error) t;
}
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw new RuntimeException(t);
}
} Log.i(TAG, "...preloaded " + count + " classes in "
+ (SystemClock.uptimeMillis()-startTime) + "ms.");
} catch (IOException e) {
Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
} finally {
IoUtils.closeQuietly(is);
// Restore default.
runtime.setTargetHeapUtilization(defaultUtilization); // Fill in dex caches with classes, fields, and methods brought in by preloading.
runtime.preloadDexCaches(); Debug.stopAllocCounting(); // Bring back root. We'll need it later.
setEffectiveUser(ROOT_UID);
setEffectiveGroup(ROOT_GID);
}
}
5.2 加载共享资源preloadResources
private static void preloadResources() {
final VMRuntime runtime = VMRuntime.getRuntime(); Debug.startAllocCounting();
try {
System.gc();
runtime.runFinalizationSync();
mResources = Resources.getSystem();
mResources.startPreloading();
if (PRELOAD_RESOURCES) {
Log.i(TAG, "Preloading resources..."); long startTime = SystemClock.uptimeMillis();
TypedArray ar = mResources.obtainTypedArray(
com.android.internal.R.array.preloaded_drawables);
int N = preloadDrawables(runtime, ar);
ar.recycle();
Log.i(TAG, "...preloaded " + N + " resources in "
+ (SystemClock.uptimeMillis()-startTime) + "ms."); startTime = SystemClock.uptimeMillis();
ar = mResources.obtainTypedArray(
com.android.internal.R.array.preloaded_color_state_lists);
N = preloadColorStateLists(runtime, ar);
ar.recycle();
Log.i(TAG, "...preloaded " + N + " resources in "
+ (SystemClock.uptimeMillis()-startTime) + "ms.");
}
mResources.finishPreloading();
} catch (RuntimeException e) {
Log.w(TAG, "Failure preloading resources", e);
} finally {
Debug.stopAllocCounting();
}
}
5.3 加载共享库
private static void preloadSharedLibraries() {
Log.i(TAG, "Preloading shared libraries...");
System.loadLibrary("android");
System.loadLibrary("compiler_rt");
System.loadLibrary("jnigraphics");
}
5.4 加载prepareWebViewInZygote(不懂,预留)
6. socket
6.1 registerZygoteSocket
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
//fullSocketName=ANDROID_SOCKET_zygote,不过,我查了一下我们的代码,没有这个环境变量????不知道为什么
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
String env = System.getenv(fullSocketName); //ANDROID_SOCKET_zygote
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
} try {
//创建一个socket本地服务的对象,这里的sServerSocket是一个静态属性,我们后面会用到
sServerSocket = new LocalServerSocket(
createFileDescriptor(fileDesc));
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
String env = System.getenv(fullSocketName); //ANDROID_SOCKET_zygote
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
} try {
//这里的LocalServerSocket创建了一个对象,然后绑定socket,并listen
//createFileDescriptor是一个本地函数,通过JNI创建一个文件,并返回fd,如后面所示
sServerSocket = new LocalServerSocket(
createFileDescriptor(fileDesc));
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
6.2 com_android_internal_os_ZygoteInit.cpp
frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp
static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "setreuid", "(II)I",
(void*) com_android_internal_os_ZygoteInit_setreuid },
{ "setregid", "(II)I",
(void*) com_android_internal_os_ZygoteInit_setregid },
{ "setpgid", "(II)I",
(void *) com_android_internal_os_ZygoteInit_setpgid },
{ "getpgid", "(I)I",
(void *) com_android_internal_os_ZygoteInit_getpgid },
{ "reopenStdio",
"(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
"Ljava/io/FileDescriptor;)V",
(void *) com_android_internal_os_ZygoteInit_reopenStdio},
{ "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V",
(void *) com_android_internal_os_ZygoteInit_setCloseOnExec},
{ "selectReadable", "([Ljava/io/FileDescriptor;)I",
(void *) com_android_internal_os_ZygoteInit_selectReadable },
{ "createFileDescriptor", "(I)Ljava/io/FileDescriptor;",
(void *) com_android_internal_os_ZygoteInit_createFileDescriptor } /*这里就是上面所调用到的函数*/
};
static jobject com_android_internal_os_ZygoteInit_createFileDescriptor (
JNIEnv *env, jobject clazz, jint fd)
{
return jniCreateFileDescriptor(env, fd); //创建文件描述符
}
7. 启动SystemServer
这个函数是调用SystemServer.我就放入SystemServer的博客更合适一点
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_BLOCK_SUSPEND,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
OsConstants.CAP_NET_BROADCAST,
OsConstants.CAP_NET_RAW,
OsConstants.CAP_SYS_MODULE,
OsConstants.CAP_SYS_NICE,
OsConstants.CAP_SYS_RESOURCE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG
);
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null; int pid; try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); /* Request to fork the system server process */
//通过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) { //从子进程跳入systemserver
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
} handleSystemServerProcess(parsedArgs);
} return true;
}
8. loop循环接收其他进程,并创建新进程
8.1 runSelectLoop
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
这里用到的socket的select模式,可以查看:Linux知识点
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
FileDescriptor[] fdArray = new FileDescriptor[4]; //新建一个数组
//拿到fd(也就是我们之前socket创建的),并添加到容器
fds.add(sServerSocket.getFileDescriptor());
peers.add(null); int loopCount = GC_LOOP_COUNT;
while (true) {
int index; /*
* Call gc() before we block in select().
* It's work that has to be done anyway, and it's better
* to avoid making every child do it. It will also
* madvise() any free memory as a side-effect.
*
* Don't call it every time, because walking the entire
* heap is a lot of overhead to free a few hundred bytes.
*/
if (loopCount <= 0) {
gc();
loopCount = GC_LOOP_COUNT;
} else {
loopCount--;
} try {
//转换为数组
fdArray = fds.toArray(fdArray);
//调用本地函数去select,去监听数组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) {
//当select到了有可读数据之后,通过accept去监听
//这里的abiList是之前参数传进来的:--abi-list=armeabi-v71,armeabi
//新建以后再添加,监听
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDescriptor());
} else {
boolean done;
//当收到select以后,根据select索引,运行,具体查看章节9
done = peers.get(index).runOnce(); if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
8.2 com_android_internal_os_ZygoteInit.cpp
frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp
static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "setreuid", "(II)I",
(void*) com_android_internal_os_ZygoteInit_setreuid },
{ "setregid", "(II)I",
(void*) com_android_internal_os_ZygoteInit_setregid },
{ "setpgid", "(II)I",
(void *) com_android_internal_os_ZygoteInit_setpgid },
{ "getpgid", "(I)I",
(void *) com_android_internal_os_ZygoteInit_getpgid },
{ "reopenStdio",
"(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
"Ljava/io/FileDescriptor;)V",
(void *) com_android_internal_os_ZygoteInit_reopenStdio},
{ "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V",
(void *) com_android_internal_os_ZygoteInit_setCloseOnExec},
{ "selectReadable", "([Ljava/io/FileDescriptor;)I",
(void *) com_android_internal_os_ZygoteInit_selectReadable }, //这一个是监听可读
{ "createFileDescriptor", "(I)Ljava/io/FileDescriptor;",
(void *) com_android_internal_os_ZygoteInit_createFileDescriptor }
};
在这里关于select的用法和JNI的相关用法可以查看我的博客:
预留。。。
预留。。。
static jint com_android_internal_os_ZygoteInit_selectReadable (
JNIEnv *env, jobject clazz, jobjectArray fds)
{
if (fds == NULL) {
jniThrowNullPointerException(env, "fds == null");
return -;
} jsize length = env->GetArrayLength(fds);
fd_set fdset; if (env->ExceptionOccurred() != NULL) {
return -;
} FD_ZERO(&fdset); int nfds = ;
for (jsize i = ; i < length; i++) {
jobject fdObj = env->GetObjectArrayElement(fds, i);
if (env->ExceptionOccurred() != NULL) {
return -;
}
if (fdObj == NULL) {
continue;
}
int fd = jniGetFDFromFileDescriptor(env, fdObj);
if (env->ExceptionOccurred() != NULL) {
return -;
} FD_SET(fd, &fdset); if (fd >= nfds) {
nfds = fd + ;
}
} int err;
do {
err = select (nfds, &fdset, NULL, NULL, NULL); //在这里监听
} while (err < && errno == EINTR); if (err < ) {
jniThrowIOException(env, errno);
return -;
} for (jsize i = ; i < length; i++) {
jobject fdObj = env->GetObjectArrayElement(fds, i);
if (env->ExceptionOccurred() != NULL) {
return -;
}
if (fdObj == NULL) {
continue;
}
int fd = jniGetFDFromFileDescriptor(env, fdObj);
if (env->ExceptionOccurred() != NULL) {
return -;
}
if (FD_ISSET(fd, &fdset)) {
return (jint)i;
}
}
return -;
}
9. runOnce启动新进程(没有看的很懂,之后再分析)
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
从之前的
done = peers.get(index).runOnce();
然后查看peers类型
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
搜索ZygoteConnection可以找到
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors; long startTime = SystemClock.elapsedRealtime(); try {
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
Log.w(TAG, "IOException on command socket " + ex.getMessage());
closeSocket();
return true;
} checkTime(startTime, "zygoteConnection.runOnce: readArgumentList");
if (args == null) {
// EOF reached.
closeSocket();
return true;
} /** the stderr of the most recent request, if avail */
PrintStream newStderr = null; if (descriptors != null && descriptors.length >= 3) {
newStderr = new PrintStream(
new FileOutputStream(descriptors[2]));
} int pid = -1;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null; try {
parsedArgs = new Arguments(args); if (parsedArgs.abiListQuery) {
return handleAbiListQuery();
} if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) {
throw new ZygoteSecurityException("Client may not specify capabilities: " +
"permitted=0x" + Long.toHexString(parsedArgs.permittedCapabilities) +
", effective=0x" + Long.toHexString(parsedArgs.effectiveCapabilities));
} applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext); checkTime(startTime, "zygoteConnection.runOnce: apply security policies"); applyDebuggerSystemProperty(parsedArgs);
applyInvokeWithSystemProperty(parsedArgs); checkTime(startTime, "zygoteConnection.runOnce: apply security policies"); int[][] rlimits = null; if (parsedArgs.rlimits != null) {
rlimits = parsedArgs.rlimits.toArray(intArray2d);
} if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) {
FileDescriptor[] pipeFds = Os.pipe();
childPipeFd = pipeFds[1];
serverPipeFd = pipeFds[0];
ZygoteInit.setCloseOnExec(serverPipeFd, true);
} /**
* In order to avoid leaking descriptors to the Zygote child,
* the native code must close the two Zygote socket descriptors
* in the child process before it switches from Zygote-root to
* the UID and privileges of the application being launched.
*
* In order to avoid "bad file descriptor" errors when the
* two LocalSocket objects are closed, the Posix file
* descriptors are released via a dup2() call which closes
* the socket and substitutes an open descriptor to /dev/null.
*/ int [] fdsToClose = { -1, -1 }; FileDescriptor fd = mSocket.getFileDescriptor(); if (fd != null) {
fdsToClose[0] = fd.getInt$();
} fd = ZygoteInit.getServerSocketFileDescriptor(); if (fd != null) {
fdsToClose[1] = fd.getInt$();
} fd = null; checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize");
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize");
} catch (IOException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (ErrnoException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (IllegalArgumentException ex) {
logAndPrintError(newStderr, "Invalid zygote arguments", ex);
} catch (ZygoteSecurityException ex) {
logAndPrintError(newStderr,
"Zygote security policy prevents request: ", ex);
} try {
if (pid == 0) {
// in child
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr); // should never get here, the child is expected to either
// throw ZygoteInit.MethodAndArgsCaller or exec().
return true;
} else {
// in parent...pid of < 0 means failure
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
i.mx6 Android5.1.1 Zygote的更多相关文章
- i.mx6 Android5.1.1 初始化流程之init.rc解析(未完成)
接上一篇:i.mx6 Android5.1.1 初始化流程之init进程 参考资料:http://blog.csdn.net/mr_raptor/article/category/799879 这个博 ...
- i.mx6 Android5.1.1 System server
1. 概述: 1. Zygote进程是Android Java世界的开创者,所有的Java应用程序进程都由Zygote进程创建: 2. Zygote创建应用程序进程过程其实就是复制自身进程地址空间作为 ...
- i.mx6 Android5.1.1 初始化流程之框架
Android启动过程分为以下几个步骤: 1. Boot ROM: 上电后启动芯片固话代码. 2. BootLoader:固话代码会根据启动模式启动bootloader,(一般为启动引脚的电平的 ...
- i.mx6 Android5.1.1 servicemanager本地服务
接在之前的 i.mx6 Android5.1.1 初始化流程之init进程 i.mx6 Android5.1.1 初始化流程之init.rc解析 servicemanager是由init创建的本地服务 ...
- i.mx6 Android5.1.1 初始化流程之init进程(未完成)
概述: 接在i.mx6 Android5.1.1 初始化流程之框架之后 参考资料:http://blog.csdn.net/mr_raptor/article/category/799879 相关源码 ...
- i.mx6 Android5.1.1 系统属性
属性变更的请求时init事件循环处理的另一个事件,在Android平台中,为了让运行中的所有进程共享系统运行时所需要的各种设置值,系统开辟了属性存储区域,并提供了访问该区域的API.属性由键(key) ...
- i.mx6 Android5.1.1 build解析
参考资料:理解 Android Build 系统 把总结放前面: 1. 常用编译命令 make clean 执行清理,等同于:rm -rf out/. make sdk 编译出 Android 的 S ...
- i.mx6 Android5.1.1 vibrator系统服务流程
0. 概述 0.1 小结 下面来从APP一直分析到kernel的driver,因为vibrator是我所知的最简单的系统服务,分析过程过来,可以获取整个安卓服务的运行思路,把相关知识点都串联起来,又不 ...
- imx6 Android6.0.1 init.rc解析
1. 概述 1.1 概述 之前分析过android5的init.rc,不过还是不够仔细,现在来看看android6的,多的就不写了,只写关键点 忘记一些基本概念可以先看看之前的笔记: Android5 ...
随机推荐
- 手动编译安装lamp之php
转自马哥教育讲课文档 三.编译安装php-5.4.8 1.解决依赖关系: 请配置好yum源(可以是本地系统光盘)后执行如下命令: # yum -y groupinstall "X Softw ...
- leetcode 验证回文串
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写. 说明:本题中,我们将空字符串定义为有效的回文串. 示例 1: 输入: "A man, a plan, a c ...
- sql游标循环结果集
我们知道游标是一种对结果集操作的神器,使用游标,可以很方便的循环结果集,并对结果集进行数据处理. 1.建表 CREATE TABLE [dbo].[Student]( ,) NOT NULL, ) N ...
- sharepoint 2013 query slow
计划: ==== 1. 调整SharePoint以及SQL端的网卡设置, 注意修改这些属性可能会导致网络暂时中断,但会很快恢复,不需要重启服务器. A. 以管理员权限运行CMD B. 关闭烟囱卸载状态 ...
- 201621123023《Java程序设计》第12周学习总结
一.本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 二.书面作业 本次PTA作业题集多线程 1. 面向系统综合设计-图书馆管理系统或购物车 使用流与文件改造你的图书 ...
- Windows server 2008启动remote dosktop services服务报错1079
原创 欢迎转载,届时请注明出处 报错场景 今天,刚开始启动win server的远程连接服务(remote desktop services)时 该服务可以正常启动,然后选择了 “计算机--> ...
- Android跳转淘宝、京东APP商品详情页
import Android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; imp ...
- BERT和ULMFIT embedding比较文本分类结果
Instructions [THIS REPOSITORY IS UNDER DEVELOPMENT AND MOER DATASETS AND MODELS WILL BE ADDED] [FEEL ...
- Github使用笔记
========================Github使用===================概念解释:远程仓库Remote:就是指保存在github网站里的代码;本地仓库Repository ...
- Spring事务杂谈
1. 什么是事务 事务就是以一种可控的方式,对资源进行的一组操作,保证了资源在事务前后,始终应处于被期待的正确的状态.比如不会受到宕机等原因的影响.事务本身,具有如下4种属性-ACID.(所以说事务是 ...