一、应用进程的启动原理
1.1 什么时候触发应用进程的启动?谁发起的
是在应用组建启动的过程中触发的,比如启动Activity的时候,先判断进程是否启动,没有启动就先去启动进程。它是由AMS向Zygote发送socket请求发起的。
1.2 进程是谁启动的?怎么启动的?
1.2.1 步骤一AMS向Zygote发送请求
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
//获取要创建应用程序进程的uid
int uid = app.uid;
int[] gids = null;
//应用进程的主线程名称
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
//启动应用程序进程
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, entryPointArgs);
@GuardedBy("mLock")
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
try {
primaryZygoteState = ZygoteState.connect(mSocket);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}
}
}
//创建socket 并且去连接zygote的server socket
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) {
}
return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter,
Arrays.asList(abiListString.split(",")));
}
连接上服务端后,就有请求发过去,之前讲的服务端有个runSelectLoop,一直阻塞等待AMS的请求到达,这不就是到了嘛,进入zygote服务端的创建进程的逻辑。
1.2.2 zygote接收请求并创建应用程序进程
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
//启动Binder进程
ZygoteInit.nativeZygoteInit();
//启动ActivityThread
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
使用反射的方式去调用main函数,比如之前的SystemServer中的main ,这里是ActivityThread中的main
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
// Remaining arguments are passed to the start class's static main
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
private static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
// className 为ActivityThread
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
m = cl.getMethod("main", new Class[] { String[].class });
return new MethodAndArgsCaller(m, argv);
}
ActivityThread # main()
public static void main(String[] args) {
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
//
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
这里我重点说说attach(),它的作用是向AMS做汇报,这一步完成后,就标识着应用程序进程创建完毕。
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
使用IActivityManager将ApplicationThread传递过去,AMS正好是继承IActivityManager.stub
在AMS中启动应用组建的时候都会做如下判断
if (r != null && r.app != null && r.app.thread != null) {
try {
r.app.thread.scheduleEnterAnimationComplete(r.appToken);
} catch (RemoteException e) {
}
}
==r.app != null 表示该应用程序进程已经存在,r.app.thread != null则表示该应用程序进程的主线程已经准备就绪== 这就是attach打报告的结果
1.2 应用是怎么启用Binder机制的
- 什么时候启动Bider
在Zygote创建应用程序进程后进行初始化的时候 启动binder,因为后序应用程序要和AMS进行通行,所以要提前创建。
- 怎么启动Binder
1. 打开Binder驱动 2.映射内存,分配缓冲区 3.注册binder线程 4 bind loop