Linux内核启动
- 电源按下,当CPU最后完成复位后,CPU执行第一条指令,从一个固定地址中执行
引导程序(BootLoader)
. BootLoader
作用是装在内核程序进行初始化并运行.- 内核完成设置,启动init进程.
init进程主要工作
- 初始化和启动属性服务
- 启动Zygote进程
- 挂载一些系统文件
init进程的启动
- 内核启动
init
进程会首先寻找init.rc
,然后启动init
进程.init
进程入口函数main()
init.rc
由Android初始化语言编写的脚本(Android Init Language
),init
进程解析该脚本就能启动Zygote进程
Zygote概述
- Dalvik虚拟机与ART,应用程序进程,SystemServer进程都是由Zygote进程来创建.
- Zygote进程启动时会创建Dalvik虚拟机或者ART进程.
- Zygote通过fork(复制进程)的形式来创建APP进程,SystemServer进程.所以SystemServer进程或者APP进程中可以获取Dalvik虚拟机或者ART进程.
- Zygote进程起初名为
app_process
,这个名称是在Android.mk中定义的,Linux系统下的pctrl系统会调用app_process
,将其进程名称换为zygote
.
Zygote进程启动
Zygote
进程对应的源文件为app_main.cpp
- Zygote进程是通过fork自身来创建子进程,所以像SystemServer进程和App进程都能走到main()中来
int main(int argc, char* const argv[])
{
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
...
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
...
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
}
...
}
...
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
...
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
...
jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
env->CallStaticVoidMethod(startClass, startMeth, strArray);
...
}
- 在
Native
层调用ZygoteInit.main()
后,逻辑就到java层了.
public static void main(String argv[]) {
try {
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());
} 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]);
}
}
...
registerZygoteSocket(socketName);
preload();
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
runSelectLoop(abiList);
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
closeServerSocket();
throw ex;
}
}
public class ZygoteInit {
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
}
...
try {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
sServerSocket = new LocalServerSocket(fd);
}
}
}
}
- 当
SystemServer
进程创建好了之后,AMS服务也就准备好了, 然后服务端Socket就可以监听AMS发送过来的创建APP进程的消息了.
public class ZygoteInit {
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
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 {
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done = peers.get(i).runOnce();
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
private static ZygoteConnection acceptCommandPeer(String abiList) {
try {
return new ZygoteConnection(sServerSocket.accept(), abiList);
} catch (IOException ex) {
throw new RuntimeException(
"IOException during accept()", ex);
}
}
}
- 看看
ZygoteConnection.runOnce()
class ZygoteConnection {
ZygoteConnection(LocalSocket socket, String abiList) throws IOException {
mSocket = socket;
this.abiList = abiList;
mSocketOutStream = new DataOutputStream(socket.getOutputStream());
mSocketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()), 256);
mSocket.setSoTimeout(CONNECTION_TIMEOUT_MILLIS);
try {
peer = mSocket.getPeerCredentials();
} catch (IOException ex) {
Log.e(TAG, "Cannot read peer credentials", ex);
throw ex;
}
}
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
...
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
if (pid == 0) {
...
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
} else {
...
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
}
}