从源码解析-Android中Zygote进程是如何fork一个APP进程的

从源码解析-Android中Zygote进程是如何fork一个APP进程的

zygote进程fork子进程

前言

创建一个线程大家肯定非常熟悉了,继承Thread,实现Runnable接口或者Callable接口;但是线程没有独立的地址空间,而是与所在进程共享内存,其实从Linux角度看,进程线程都是一个task_struct结构体,除了是否共享资源外,并没有其他本质的区别。

但是创建进程可能就没有那么熟悉了,每个APP可能运行在一个进程,也可能在多个进程,这些进程拥有自己独立的资源;然而这些进程都是由Zygote进程fork出来的,再往前一步其实是system server进程使用LocalSocket去通知zygote进程,然后zygote去fork一个子进程,也就是APP进程(更往前一步就是APP进程使用Binder机制去通知system server进程中的ActivityManagerService),注意这里是子进程,不是子线程

强烈推荐

在接下来的讲述中会涉及到system server进程和zygote进程的操作,对于这两个进程不了解的强烈推荐先看下Android系统启动流程概述 init进程启动 zygote进程启动 system server进程启动

进程创建流程

  • 1 不管从桌面启动应用还是应用内启动其它应用,如果这个应用所在进程不存在的话,都需要发起进程通过Binder机制告诉system server进程的AMS

  • 2 system server进程的AMS调用Process.start()方法,通过socket向zygote进程发送创建新进程的请求

  • 3 在zygote进程的ZygoteInit.main方法中,有一个runSelectLoop循环体,通过acceptCommandPeer方法获取链接过来的客户端,再通过runOnce方法去创建进程

  • 4 新的进程执行handleChildProc方法,最后通过反射调用ActivityThread.main()方法,这样一个新的APP进程就创建完成了

APP启动第三方应用

startActivity

当你在桌面启动一个应用或者在一个APP内启动一个应用,本质都是一样的,因为Android手机桌面其实就是一个APP(这点可参考Android之Activity启动流程源码深入解析),两种方式经过层层调用之后都会走到ActivityStackSupervisor.startSpecificActivityLocked方法,判断如果对方进程不存在,就需要去创建一个进程

startService

调用startService启动一个服务,该方法经过层层调用最终会走到ActiveServices.bringUpServiceLocked方法,如果判断对方进程不存在也会去创建一个新进程

sendBroadcast

调用sendBroadcast方法去发送一个广播,经过层层调用后走到BroadcastQueue.processNextBroadcast方法,也会判断BroadcastReceiver所在进程不存在就需要去创建进程

ContentResolver.query

在ContentProvider的处理过程中,ContentResolver.query方法经过层层调用会走到ActivityManagerService.getContentProviderImpl方法,判断ContentProvider所在的进程不存在就会创建新进程

System Server请求创建进程

以下叙述中ActivityManagerService同意简称为AMS

以下源码基于API24

上述四种途径最终都会走到如下方法

AMS.startProcessLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
long startTime = SystemClock.elapsedRealtime();
ProcessRecord app;
//不处于孤立进程
if (!isolated) {
//根据进程名和进程uid获取进程对应的ProcessRecord
//ProcessRecord封装了正在运行的进程的完整信息
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
checkTime(startTime, "startProcess: after getProcessRecord");

if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
// 如果当前进程处于后台进程,就判断是否在Bad进程列表
if (mAppErrors.isBadProcessLocked(info)) {
return null;
}
} else {
// 如果用户明确启动该进程,则清除其crash计数,保证其不处于Bad进程列表,直到下次再弹出crash框
mAppErrors.resetProcessCrashTimeLocked(info);
if (mAppErrors.isBadProcessLocked(info)) {
EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
UserHandle.getUserId(info.uid), info.uid,
info.processName);
mAppErrors.clearBadProcessLocked(info);
if (app != null) {
app.bad = false;
}
}
}
} else {
// 如果是孤立进程,就没办法重用已存在的进程
app = null;
}

......

//当ProcessRecord已经存在;
//并且调用者不认为进程已经死亡,或者没有thread对象依附到该进程,这样我们就知道他不会crash;
//该进程已经分配了pid,说明它正在启动或正在运行
//这些情况下我们不需要做什么,直接返回
if (app != null && app.pid > 0) {
if ((!knownToBeDead && !app.killed) || app.thread == null) {
//我们已经启动了这个app,或者正在等待它启动(分配了pid但是没有thread依附),就keep it
// 如果这是该进程中的一个新的package,那就添加到package列表
app.addPackage(info.packageName, info.versionCode, mProcessStats);
checkTime(startTime, "startProcess: done, added package to proc");
return app;
}

// 如果ProcessRecord已经attach到先前的进程,那就清除它
checkTime(startTime, "startProcess: bad proc running, killing");
killProcessGroup(app.uid, app.pid);
handleAppDiedLocked(app, true, true);
checkTime(startTime, "startProcess: done killing old proc");
}

String hostingNameStr = hostingName != null
? hostingName.flattenToShortString() : null;

if (app == null) {
checkTime(startTime, "startProcess: creating new process record");
// 创建新的Process Record对象
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
if (app == null) {
return null;
}
app.crashHandler = crashHandler;
checkTime(startTime, "startProcess: done creating new process record");
} else {
// 如果这是该进程中的一个新的package,那就添加到package列表
app.addPackage(info.packageName, info.versionCode, mProcessStats);
checkTime(startTime, "startProcess: added package to existing proc");
}

// 如果系统还没有准备就绪,那就暂停该进程启动,将当前进程加入到mProcessesOnHold,直到准备就绪
if (!mProcessesReady
&& !isAllowedWhileBooting(info)
&& !allowWhileBooting) {
if (!mProcessesOnHold.contains(app)) {
mProcessesOnHold.add(app);
}
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
"System not ready, putting on hold: " + app);
checkTime(startTime, "startProcess: returning with proc on hold");
return app;
}

checkTime(startTime, "startProcess: stepping in to startProcess");
startProcessLocked(
app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
checkTime(startTime, "startProcess: done starting proc!");
return (app.pid != 0) ? app : null;
}

经过上面重重判断后决定需要创建进程,继续走到startProcessLocked方法,这个方法在AMS里有4个重载的方法

其中的hostingType参数有”activity”,”service”,”broadcast”,”content provider”四个值
hostingNameStr数据类型为ComponentName,封装了组件的包名和自己的路径

继续调用AMS.startProcessLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
long startTime = SystemClock.elapsedRealtime();
//当app的pid大于0且不是当前进程的pid,则从mPidsSelfLocked中移除该app.pid
if (app.pid > 0 && app.pid != MY_PID) {
checkTime(startTime, "startProcess: removing from pids map");
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
checkTime(startTime, "startProcess: done removing from pids map");
app.setPid(0);
}

//从mProcessesOnHold移除该app
mProcessesOnHold.remove(app);

checkTime(startTime, "startProcess: starting to update cpu stats");
updateCpuStats();
checkTime(startTime, "startProcess: done updating cpu stats");

try {
try {
final int userId = UserHandle.getUserId(app.uid);
AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
//当前package已被冻结,则抛出异常
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}

int uid = app.uid;
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
int[] permGids = null;
try {
checkTime(startTime, "startProcess: getting gids from package manager");
//通过Package Manager获取gids
final IPackageManager pm = AppGlobals.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName,
MATCH_DEBUG_TRIAGED_MISSING, app.userId);
MountServiceInternal mountServiceInternal = LocalServices.getService(
MountServiceInternal.class);
mountExternal = mountServiceInternal.getExternalStorageMountMode(uid,
app.info.packageName);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}


//添加APP和配置文件GID,以便app可以共享某些资源
if (ArrayUtils.isEmpty(permGids)) {
gids = new int[2];
} else {
gids = new int[permGids.length + 2];
System.arraycopy(permGids, 0, gids, 2, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
}
checkTime(startTime, "startProcess: building args");

......

app.gids = gids;
app.requiredAbi = requiredAbi;
app.instructionSet = instructionSet;

......

// 请求zygote创建进程,成功后会返回新进程的pid,否则会抛出异常
//ProcessStartResult是Process内部类,封装了启动进程的结果
//这是一个阻塞过程
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
checkTime(startTime, "startProcess: returned from zygote!");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

......

//重置ProcessRecord的成员变量
app.setPid(startResult.pid);
app.usingWrapper = startResult.usingWrapper;
app.removed = false;
app.killed = false;
app.killedByAm = false;
checkTime(startTime, "startProcess: starting to update pids map");

synchronized (mPidsSelfLocked) {
ProcessRecord oldApp;
// 如果已经有一个app占用了这个尚未清理的pid
if ((oldApp = mPidsSelfLocked.get(startResult.pid)) != null && !app.isolated) {
// 清理与此pid相关联的内容
cleanUpApplicationRecordLocked(oldApp, false, false, -1,
true /*replacingPid*/);
}
//将新创建的进程添加到mPidsSelfLocked
this.mPidsSelfLocked.put(startResult.pid, app);
if (isActivityProcess) {
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg, startResult.usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
}
checkTime(startTime, "startProcess: done updating pids map");
} catch (RuntimeException e) {
// 创建进程失败了,一个常见的情况是由于主动升级导致包被冻结
forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false,
false, true, false, false, UserHandle.getUserId(app.userId), "start failure");
}
}

这个方法中最重要的就是通过Process.start来创建应用进程;原理是通过socket向Zygote进程发送创建新进程的请求;Zygote进程启动后有一个runSelectLoop循环,当收到客户端请求便会执行ZygoteConnection.runOnce()方法,再经过层层调用后fork出新的应用进程,创建新进程后将ActivityThread类加载到新进程,并调用ActivityThread.main()方法

Process.start

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//开启一个新的进程
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}

Process.startViaZygote

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//通过zygote机制启动新进程
private static ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
ArrayList<String> argsForZygote = new ArrayList<String>();

// 主要工作是生成argsForZygote数组,该数组保存了进程的uid、gid、groups、target-sdk、nice-name等一系列的参数
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
argsForZygote.add("--enable-jni-logging");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
argsForZygote.add("--enable-safemode");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
argsForZygote.add("--enable-debugger");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
argsForZygote.add("--enable-checkjni");
}
if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) {
argsForZygote.add("--generate-debug-info");
}
if ((debugFlags & Zygote.DEBUG_ALWAYS_JIT) != 0) {
argsForZygote.add("--always-jit");
}
if ((debugFlags & Zygote.DEBUG_NATIVE_DEBUGGABLE) != 0) {
argsForZygote.add("--native-debuggable");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
argsForZygote.add("--enable-assert");
}
if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
argsForZygote.add("--mount-external-default");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
argsForZygote.add("--mount-external-read");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
argsForZygote.add("--mount-external-write");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);

//TODO optionally enable debuger
//argsForZygote.add("--enable-debugger");

// --setgroups is a comma-separated list
if (gids != null && gids.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("--setgroups=");

int sz = gids.length;
for (int i = 0; i < sz; i++) {
if (i != 0) {
sb.append(',');
}
sb.append(gids[i]);
}

argsForZygote.add(sb.toString());
}

if (niceName != null) {
argsForZygote.add("--nice-name=" + niceName);
}

if (seInfo != null) {
argsForZygote.add("--seinfo=" + seInfo);
}

if (instructionSet != null) {
argsForZygote.add("--instruction-set=" + instructionSet);
}

if (appDataDir != null) {
argsForZygote.add("--app-data-dir=" + appDataDir);
}

argsForZygote.add(processClass);

if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}

return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}

Process.zygoteSendArgsAndGetResult

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
private static ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
// 如果参数格式错误,就尽早抛出异常.
int sz = args.size();
for (int i = 0; i < sz; i++) {
if (args.get(i).indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx("embedded newlines not allowed");
}
}

/**
* 这里就是通过输出流将参数列表写出去
* 获取输入流得到创建进程结果
*/
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;

writer.write(Integer.toString(args.size()));
writer.newLine();

for (int i = 0; i < sz; i++) {
String arg = args.get(i);
writer.write(arg);
writer.newLine();
}

writer.flush();

// 等待socket返回,这里是否需要设置超时时间,google也在考虑,但是暂时没有加
ProcessStartResult result = new ProcessStartResult();
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();

if (result.pid < 0) {
//创建进程失败,抛出异常
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}

这个方法作用就是通过Socket向zygote进程发送一个参数列表,然后就进入阻塞状态,直到远程Socket服务端返回新创建的进程pid

说到这里我们好像没有见到Socket的影子,只见到了ZygoteState这么一个东西,那它怎么来的呢,可以看见它是上一个方法startViaZygote调用zygoteSendArgsAndGetResult方法传过来的参数,就是这么一句话

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private static ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
......
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}

Process.openZygoteSocketIfNeeded

//如果zygote的socket没有打开,那就尝试打开,可能会阻塞或者重连

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
//向zygote进程发起连接
primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}
}

if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}

//当主zygote没能匹配成功,则采用第二个zygote,发起connect()操作
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
}
}

if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}

throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}

这个方法会根据当前的abi来选择与zygote还是zygote64进行通信,在init进程解析rc文件的时候,会根据abi型号创建两个zygote;该方法最终会返回一个ZygoteState,它是Process的静态内部类,具体连接实现在ZygoteState.connect方法中

Process.ZygoteState

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/**
* 与zygote进程通信的状态
*
* @hide 仅限内部使用
*/
public static class ZygoteState {
final LocalSocket socket;
final DataInputStream inputStream;
final BufferedWriter writer;
final List<String> abiList;

boolean mClosed;

private ZygoteState(LocalSocket socket, DataInputStream inputStream,
BufferedWriter writer, List<String> abiList) {
this.socket = socket;
this.inputStream = inputStream;
this.writer = writer;
this.abiList = abiList;
}

public static ZygoteState connect(String socketAddress) throws IOException {
DataInputStream zygoteInputStream = null;
BufferedWriter zygoteWriter = null;
final LocalSocket zygoteSocket = new LocalSocket();

try {
zygoteSocket.connect(new LocalSocketAddress(socketAddress,
LocalSocketAddress.Namespace.RESERVED));

zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());

zygoteWriter = new BufferedWriter(new OutputStreamWriter(
zygoteSocket.getOutputStream()), 256);
} catch (IOException ex) {
try {
zygoteSocket.close();
} catch (IOException ignore) {
}

throw ex;
}

String abiListString = getAbiList(zygoteWriter, zygoteInputStream);
Log.i("Zygote", "Process: zygote socket opened, supported ABIS: " + abiListString);

return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter,
Arrays.asList(abiListString.split(",")));
}

boolean matches(String abi) {
return abiList.contains(abi);
}

public void close() {
try {
socket.close();
} catch (IOException ex) {
Log.e(LOG_TAG,"I/O exception on routine close", ex);
}

mClosed = true;
}

boolean isClosed() {
return mClosed;
}
}

可以看到这里是通过LocalSocket进行进程间通信;这种通信的双方一般是Native层的server端,Framework层的Client端,中间涉及到jni调用。

说到LocalSocket,大家肯定会想到平时用到的Socket,Socket通常是为了方便两台不同的机器之间的通信,它封装了TCP/IP协议,向外提供一些API简化了网络通信过程,可以实现不同层面,不同应用,跨进程跨网络的通信;一般由Socket(client)和ServerSocket(Server)组成通信双方。

而Android中的LocalSocket是基于UNIX-domain Socket的,UNIX-domain Socket是在Socket的基础上衍生出来的一种IPC通信机制,因此LocalSocket解决的是同一台主机上不同进程间互相通信的问题。其相对于网络通信使用的socket不需要经过网络协议栈,不需要打包拆包、计算校验,自然的执行效率也高。与大名鼎鼎的binder机制作用一样,都在Android系统中作为IPC通信手段被广泛使用;一般由LocalSocket(Client)和LocalServerSocket(Server)组成通信双方。

那么在本文中AMS所在的system-server进程就充当了Client,zygote进程充当Server,因为zygote进程在创建的时候会在ZygoteInit.main方法中调用ZygoteInit.registerZygoteSocket方法,会实例化一个LocalServerSocket,并且在ZygoteInit.runSelectLoop方法中不停的获取客户端的请求

Zygote

ZygoteInit.main

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String argv[]) {
try {
registerZygoteSocket(socketName); //为Zygote注册socket
runSelectLoop(abiList); //进入循环模式,获取客户端连接并处理
....
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
closeServerSocket();
throw ex;
}
}

ZygoteInit.runSelectLoop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
//sServerSocket是socket通信中的服务端,即zygote进程。保存到fds[0]
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);

while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
//处理轮询状态,当pollFds有事件到来则往下执行,否则阻塞在这里
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
...
}

for (int i = pollFds.length - 1; i >= 0; --i) {
//采用I/O多路复用机制,当接收到客户端发出连接请求 或者数据处理请求到来,则往下执行;
// 否则进入continue,跳出本次循环。
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
//即fds[0],代表的是sServerSocket,则意味着有客户端连接请求;
// 则创建ZygoteConnection对象,并添加到fds。
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor()); //添加到fds.
} else {
//i>0,则代表通过socket接收来自对端的数据,并执行相应操作
boolean done = peers.get(i).runOnce();
if (done) {
peers.remove(i);
fds.remove(i); //处理完则从fds中移除该文件描述符
}
}
}
}
}

这里通过acceptCommandPeer方法获取连接过来的客户端,然后执行ZygoteConnection.runOnce方法处理请求

ZygoteConnection.runOnce

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
* 从socket读取一个启动命令;如果有就fork一个子进程
* 如果fork成功,就会抛出 ZygoteInit.MethodAndArgsCaller异常
*/
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;

try {
//读取socket客户端发送过来的参数列表
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
...
return true;
}
...

try {
//将binder客户端传递过来的参数,解析成Arguments对象格式
parsedArgs = new Arguments(args);
...
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
} catch (Exception e) {
...
}

try {
if (pid == 0) {
//子进程执行
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
//进入子进程流程
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
} else {
//父进程执行
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}

这里先解析客户端发送过来的参数列表,然后调用Zygote.forkAndSpecialize方法

Zygote.forkAndSpecialize

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
/**
* fork一个新的vm实例, 必须使用-Xzygote标志启动当前VM
* 新实例保留所有root功能
*/
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
String instructionSet, String appDataDir) {
VM_HOOKS.preFork();
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
instructionSet, appDataDir);

VM_HOOKS.postForkCommon();
return pid;
}

这里在fork新进程的时候会先调用 VM_HOOKS.preFork()

ZygoteHooks.preFork

1
2
3
4
5
public void preFork() {
Daemons.stop(); //停止4个Daemon子线程
waitUntilAllThreadsStopped(); //等待所有子线程结束
token = nativePreFork(); //完成gc堆的初始化工作
}

这个方法的主要目的是停止zygote进程的四个daemon子线程,分别是ReferenceQueueDaemon,FinalizerDaemon,FinalizerWatchdogDaemon,HeapTaskDaemon;直到zygote是是单线程,以便于提高fork效率;

fork新进程是调用native方法,经过jni调用

nativeForkAndSpecialize

com_android_internal_os_Zygote.nativeForkAndSpecialize

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
jint debug_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring se_name,
jintArray fdsToClose, jstring instructionSet, jstring appDataDir) {
// 将CAP_WAKE_ALARM赋予蓝牙进程
jlong capabilities = 0;
if (uid == AID_BLUETOOTH) {
capabilities |= (1LL << CAP_WAKE_ALARM);
}

return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
rlimits, capabilities, capabilities, mount_external, se_info,
se_name, false, fdsToClose, instructionSet, appDataDir);
}

com_android_internal_os_Zygote.ForkAndSpecializeCommon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
jint debug_flags, jobjectArray javaRlimits,
jlong permittedCapabilities, jlong effectiveCapabilities,
jint mount_external,
jstring java_se_info, jstring java_se_name,
bool is_system_server, jintArray fdsToClose,
jstring instructionSet, jstring dataDir) {
//设置子进程的signal信号处理函数
SetSigChldHandler();
//fork子进程
pid_t pid = fork();
if (pid == 0) { //进入子进程
DetachDescriptors(env, fdsToClose); //关闭并清除文件描述符

if (!is_system_server) {
//对于非system_server子进程,则创建进程组
int rc = createProcessGroup(uid, getpid());
}
SetGids(env, javaGids); //设置设置group
SetRLimits(env, javaRlimits); //设置资源limit

int rc = setresgid(gid, gid, gid);
rc = setresuid(uid, uid, uid);

SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
SetSchedulerPolicy(env); //设置调度策略

//selinux上下文
rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);

if (se_info_c_str == NULL && is_system_server) {
se_name_c_str = "system_server";
}
if (se_info_c_str != NULL) {
SetThreadName(se_name_c_str); //设置线程名为system_server,方便调试
}
//在Zygote子进程中,设置信号SIGCHLD的处理器恢复为默认行为
UnsetSigChldHandler();
//等价于调用zygote.callPostForkChildHooks()
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
is_system_server ? NULL : instructionSet);
...

} else if (pid > 0) {
//进入父进程,即Zygote进程
}
return pid;
}

这里会通过fork()方法创建进程

fork.fork

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int fork() {
__bionic_atfork_run_prepare(); // fork完成前,父进程回调方法

pthread_internal_t* self = __get_thread();

//fork期间,获取父进程pid,并使其缓存值无效
pid_t parent_pid = self->invalidate_cached_pid();
//系统调用
int result = syscall(__NR_clone, FORK_FLAGS, NULL, NULL, NULL, &(self->tid));
if (result == 0) {
self->set_cached_pid(gettid());
__bionic_atfork_run_child(); //fork完成执行子进程回调方法
} else {
self->set_cached_pid(parent_pid);
__bionic_atfork_run_parent(); //fork完成执行父进程回调方法
}
return result;
}

fork进程结束后会在ForkAndSpecializeCommon函数中调用CallStaticVoidMethod。这就是反射调用zygote.callPostForkChildHooks()

zygote.callPostForkChildHooks

1
2
3
4
private static void callPostForkChildHooks(int debugFlags, boolean isSystemServer,
String instructionSet) {
VM_HOOKS.postForkChild(debugFlags, isSystemServer, instructionSet);
}

ZygoteHooks.postForkChild

1
2
3
4
5
public void postForkChild(int debugFlags, String instructionSet) {
nativePostForkChild(token, debugFlags, instructionSet);
//将当前时间设置为新进程随机数种子
Math.setRandomSeedInternal(System.currentTimeMillis());
}

nativePostForkChild又通过jni调用如下函数

dalvik_system_ZygoteHooks.ZygoteHooks_nativePostForkChild

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static void ZygoteHooks_nativePostForkChild(JNIEnv* env, jclass, jlong token, jint debug_flags,
jstring instruction_set) {
//此处token是由nativePreFork()创建的,记录着当前线程
Thread* thread = reinterpret_cast<Thread*>(token);
//设置新进程的主线程id
thread->InitAfterFork();
..
if (instruction_set != nullptr) {
ScopedUtfChars isa_string(env, instruction_set);
InstructionSet isa = GetInstructionSetFromString(isa_string.c_str());
Runtime::NativeBridgeAction action = Runtime::NativeBridgeAction::kUnload;
if (isa != kNone && isa != kRuntimeISA) {
action = Runtime::NativeBridgeAction::kInitialize;
}

Runtime::Current()->DidForkFromZygote(env, action, isa_string.c_str());
} else {
Runtime::Current()->DidForkFromZygote(env, Runtime::NativeBridgeAction::kUnload, nullptr);
}
}

Runtime.DidForkFromZygote

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void Runtime::DidForkFromZygote(JNIEnv* env, NativeBridgeAction action, const char* isa) {
is_zygote_ = false;
if (is_native_bridge_loaded_) {
switch (action) {
case NativeBridgeAction::kUnload:
UnloadNativeBridge(); //卸载用于跨平台的桥连库
is_native_bridge_loaded_ = false;
break;
case NativeBridgeAction::kInitialize:
InitializeNativeBridge(env, isa);//初始化用于跨平台的桥连库
break;
}
}
//创建Java堆处理的线程池
heap_->CreateThreadPool();
//重置gc性能数据,以保证进程在创建之前的GCs不会计算到当前app上。
heap_->ResetGcPerformanceInfo();
if (jit_.get() == nullptr && jit_options_->UseJIT()) {
//当flag被设置,并且还没有创建JIT时,则创建JIT
CreateJit();
}
//设置信号处理函数
StartSignalCatcher();
//启动JDWP线程,当命令debuger的flags指定"suspend=y"时,则暂停runtime
Dbg::StartJdwp();
}

fork完成后继续Zygote.forkAndSpecialize方法第三步

ZygoteHooks.postForkCommon

1
2
3
4
5
6
7
8
9
10
public void postForkCommon() {
Daemons.start();
}

public static void start() {
ReferenceQueueDaemon.INSTANCE.start();
FinalizerDaemon.INSTANCE.start();
FinalizerWatchdogDaemon.INSTANCE.start();
HeapTaskDaemon.INSTANCE.start();
}

主要作用是在fork新进程后将之前停掉的四个Daemon线程启动起来

forkAndSpecialize 总结

  • preFork:停止4个Daemon子线程,初始化GC
    • nativeForkAndSpecialize:调用Linux的fork()子进程,设置新进程的主线程id,重置gc性能数据,设置信号处理函数等功能
  • postForkCommon:重新启动四个daemon子线程
  • forkAndSpecialize执行结束,即创建新进程后,会有两次返回,第一次回到ZygoteConnection.runOnce方法,执行子进程handleChildProc方法;第二次回到该方法,执行zygote进程的handleParentProc方法

回调子进程

ZygoteConnection.handleChildProc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* 处理子进程的post-fork设置,并根据需要关闭套接字,根据需要重新打开stdio,
* 如果成功则最终抛出MethodAndArgsCaller,如果失败则返回。
*/
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
/**
* 当执行到达这里时,native code关闭了两个实际的Zygote socket连接,
* 并在它们的位置替换了/ dev / null。 LocalSocket对象仍需要正确关闭。
*/

closeSocket();
ZygoteInit.closeServerSocket();

if (descriptors != null) {
try {
Os.dup2(descriptors[0], STDIN_FILENO);
Os.dup2(descriptors[1], STDOUT_FILENO);
Os.dup2(descriptors[2], STDERR_FILENO);

for (FileDescriptor fd: descriptors) {
IoUtils.closeQuietly(fd);
}
newStderr = System.err;
} catch (ErrnoException ex) {
Log.e(TAG, "Error reopening stdio", ex);
}
}

//设置进程名
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}


if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.remainingArgs);
} else {
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
}

RuntimeInit.zygoteInit

1
2
3
4
5
6
7
8
9
10
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
redirectLogStreams(); //重定向log输出

commonInit(); // 通用的一些初始化
nativeZygoteInit(); // zygote初始化
applicationInit(targetSdkVersion, argv, classLoader); // 应用初始化
}

RuntimeInit.commonInit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private static final void commonInit() {
// 设置默认的未捕捉异常处理方法
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());

// 设置市区,中国时区为"Asia/Shanghai"
TimezoneGetter.setInstance(new TimezoneGetter() {
@Override
public String getId() {
return SystemProperties.get("persist.sys.timezone");
}
});
TimeZone.setDefault(null);

//重置log配置
LogManager.getLogManager().reset();
new AndroidConfig();

// 设置默认的HTTP User-agent格式( "Dalvik/1.1.0 (Linux; U; Android 6.0.1;LenovoX3c70 Build/LMY47V)"),用于 HttpURLConnection
String userAgent = getDefaultUserAgent();
System.setProperty("http.agent", userAgent);

// 设置socket的tag,用于网络流量统计
NetworkManagementSocketTagger.install();
}

RuntimeInit.nativeZygoteInit

nativeZygoteInit()所对应的jni方法如下

1
2
3
4
5
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
//此处的gCurRuntime为AppRuntime,是在AndroidRuntime.cpp中定义的
gCurRuntime->onZygoteInit();
}

app_main.onZygoteInit

1
2
3
4
5
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool(); //启动新binder线程
}

ProcessState::self():主要工作是调用open()打开/dev/binder驱动设备,再利用mmap()映射内核的地址空间,将Binder驱动的fd赋值ProcessState对象中的变量mDriverFD,用于交互操作。startThreadPool()是创建一个新的binder线程,不断进行talkWithDriver(),与Binder驱动交流

继续执行zygoteInit方法中的最后一个方法

RuntimeInit.applicationInit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
//true代表应用程序退出时不调用AppRuntime.onExit(),否则会在退出前调用
nativeSetExitWithoutCleanup(true);

//设置虚拟机的内存利用率参数值为0.75
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

final Arguments args;
try {
args = new Arguments(argv); //解析参数
} catch (IllegalArgumentException ex) {
return;
}

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

//调用startClass的static方法 main() 此处args.startClass为”android.app.ActivityThread”
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}

RuntimeInit.invokeStaticMain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl = Class.forName(className, true, classLoader);
...

Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
...
} catch (SecurityException ex) {
...
}

//通过抛出异常,回到ZygoteInit.main()。这样做好处是能清空栈帧,提高栈帧利用率
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

重点看最后一个方法,通过反射获取ActivityThread类的main方法参数,然后抛出MethodAndArgsCaller异常,其中构造方法中m是指main方法,argv是AMS发送过来的参数列表;但是抛出异常后怎么弄呢,我们知道一个方法抛异常,会一直往上走到调用方法,直到一个方法捕获了异常。在这里就会一直抛到ZygoteInit.main方法才捕获了异常,然后去执行MethodAndArgsCaller.run方法

MethodAndArgsCaller.run

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public static class MethodAndArgsCaller extends Exception
implements Runnable {
/** 调用的方法 在上面的方法可知是main方法 */
private final Method mMethod;

/** 参数列表 */
private final String[] mArgs;

public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}

public void run() {
try {
//反射调用,由上面可知这里会调用到ActivityThread.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);
}
}
}

走到这里就要进入ActivityThread了,它管理着应用程序进程中主线程的执行,在ActivityManager请求时调度和执行Activity,Service,Broadcast和其它操作

ActivityThread.main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main(String[] args) {

......
//创建主线程的Looper
Looper.prepareMainLooper();
//关联AMS
ActivityThread thread = new ActivityThread();
thread.attach(false);

//初始化主线程Handler
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}

// 进行主线程消息循环
Looper.loop();

throw new RuntimeException("Main thread loop unexpectedly exited");
}

主要工作:设置进程名,打开binder驱动,启动新的binder线程;然后设置art虚拟机参数,再反射调用目标类的main()方法,即ActivityThread.main()方法

至此,进程创建完毕,并且也有了主线程,剩下的便是启动Activity和关联context等初始化操作了

回调zygote进程

子进程fork方法执行完成回调第一次给子进程后,还会回调一次给zygote进程

具体是在ZygoteConnection.runOnce中调用handleParentProc

ZygoteConnection.handleParentProc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private boolean handleParentProc(int pid,
FileDescriptor[] descriptors, FileDescriptor pipeFd, Arguments parsedArgs) {

if (pid > 0) {
setChildPgid(pid);
}
....
try {

mSocketOutStream.writeInt(pid);
mSocketOutStream.writeBoolean(usingWrapper);
} catch (IOException ex) {
Log.e(TAG, "Error writing to command socket", ex);
return true;
}

return false;
}

这个方法主要是为了通知system server进程,新进程已经创建完成

注意

  • APP或者桌面启动,需要使用Binder机制告诉AMS(因为启动方有自己的进程,AMS在system server进程),AMS请求zygote进程是通过Socket
  • Process.start方法是阻塞的,只有等进程创建完成才会返回
  • zygote进程fork进程一次,会有两次返回,在zygote进程和子进程分别返回一次,这样子线程就能执行ZygoteConnection.handleChildProc及以后的逻辑;zygote进程通过ZygoteConnection.handleParentProc通知system server进程新进程已经创建完成

fork解释

可能你会疑虑,明明是在zygote进程中的ZygoteConnection.runOnce方法中去执行fork操作,那么fork结束后返回不应该还是在zygote进程中吗?

这里需要了解下fork的逻辑:

fork()采用copy on write技术,这是linux创建进程的标准方法,调用一次,返回两次。当父子进程任一方修改内存数据时(这是on-write时机),才发生缺页中断,从而分配新的物理内存(这是copy操作)。
copy-on-write原理:写时拷贝是指子进程与父进程的页表都所指向同一个块物理内存,fork过程只拷贝父进程的页表,并标记这些页表是只读的。父子进程共用同一份物理内存,如果父子进程任一方想要修改这块物理内存,那么会触发缺页异常(page fault),Linux收到该中断便会创建新的物理内存,并将两个物理内存标记设置为可写状态,从而父子进程都有各自独立的物理内存。

其实就是fork之后,操作系统会复制一个与父进程完全相同的子进程,虽说是父子关系,但是在操作系统看来,他们更像兄弟关系,这2个进程共享代码空间,但是数据空间是互相独立的,子进程数据空间中的内容是父进程的完整拷贝,指令指针也完全相同,子进程拥有父进程当前运行到的位置(两进程的程序计数器pc值相同,也就是说,子进程是从fork返回处开始执行的)

可以这样想象,子进程就是把zygote进程复制了一遍,两个进程都阻塞在这里;但在fork之后,他们就开始分别作不同的工作,正如fork原意【分支】一样,在zygote进程的ZygoteConnection.runOnce方法中,fork返回子进程id,然后执行ZygoteConnection.handleParentProc;但是在子进程的ZygoteConnection.runOnce方法中,fork返回是0,就会去执行ZygoteConnection.handleChildProc;这样父子进程从此分家

from

https://blog.csdn.net/qq_30993595/article/details/82747738


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 wilber_bai@hotmail.com

文章标题:从源码解析-Android中Zygote进程是如何fork一个APP进程的

文章字数:8,161

本文作者:风沉殇史

发布时间:2017-12-12, 12:12:12

最后更新:2020-01-03, 16:01:13

原始链接:http://wilber.win/posts/bc9cecf3/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏