这是“一起学源码”系列的第一篇文章,坚持就是胜利,共勉。
引导程序
引导程序是Android系统运行前的小程序,并不是Android操作系统的一部分,它需要针对特定主板和芯片。引导程序是OEM厂商或运行商进行加锁、限制的地方。
内核启动
Android内核启动方式类似桌面linux,主要步骤见下:
- 设置缓存
- 被保护存储器
- 计划列表
- 加载驱动
init.rc
init是Android系统的第一个进程(PID = 0),它通过解析init.rc脚本来启动其他系统服务进程,如 Zygote,SystemService,ServiceManager。
我们说的 init.rc 是一个脚本文件,它有着自己的一系列语法规则,本文不做细究, 规范可参考:/system/core/init/Readme.txt,栗子可参考下文的init.zygote64.rc文件。
Zygote
Zygote是由init解析init.rc脚本时启动的。Android系统可根据 ro.zygote 的具体值,按需加载32位或64位机器的描述Zygote.rc。
# system/core/rootdir/init.rc
import /init.${ro.zygote}.rc
复制代码
其中init.zygote64.rc 见下:
#name 此service名称:zygote
#pathname service所在路径:/system/bin/app_process64
#argument 启动service所带参数:-Xzygote /system/bin --zygote --start-system-server
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
#所属class为main,而非core
class main
priority -20
#在启动服务前,将服务切换至root,默认情况用户都是root
user root
group root readproc reserved_disk
#创建一个/dev/socket/zygote的socket,并将它的fd值传递给启动它的init进程
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
#当此服务重启时,执行如下指令
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
复制代码
从zygote的path可以看出,zygote所在的程序叫app_process64。
app_process
app_process 的源码路径在 /frameworks/base/cmds/app_pocess 中,主函数 app_main.cpp 部分代码见下:
#if defined(__LP64__)
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
static const char ZYGOTE_NICE_NAME[] = "zygote64";
int main(int argc, char* const argv[])
{
...
#argv[]就是init传进的-Xzygote /system/bin --zygote --start-system-server
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
argv++;
...
#a参数解析
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i;
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
#b当前进程用来承载zygote
zygote = true;
#c更改进程别名为: zygote64
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
#d启动system server
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
#e启动进入独立的程序模式
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
...
if (zygote) {
#runtime启动ZygoteInit
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
...
}
}
复制代码
这里的runtime是AppRuntime对象,详见下:
AppRuntime
源码位于 /frameworks/base/core/jni/AndroidRuntime.cpp ,部分代码见下:
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
#a启动虚拟机,并根据Android属性来设置虚拟机的参数
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
#b虚拟机启动后回调
onVmCreated(env);
#c JNI方法注册
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
...
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
...
#d 这里className即在app_process传入的“com.android.internal.os.ZygoteInit”
#e 将className转换为"com/android/internal/os/ZygoteInit"
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName);
#f 判空
...
#g 反射调用ZygoteInit的main方法,之后ZygoteInit会运行在虚拟机上
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#h 释放相应对象的内存空间
free(slashClassName);
...
}
复制代码
ZygoteInit
源码位于 /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java , 部分代码见下:
public static void main(String argv[]) {
...
try {
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
// 需要启动system server
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
// 延迟加载资源
enableLazyPreload = 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)) {
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
if (!enableLazyPreload) {
...
// 如果app_process的调用参数argv[]不带有“–enable-lazy-preload”
// 则会通此方法直接预加载虚拟机运行时所需要的各类资源
preload(bootTimingsTraceLog);
...
} else {
Zygote.resetNicePriority();
}
...
// GC操作
bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
gcAndFinalize();
...
// 创建一个Socket接口,Socket接口是通过文件描述符控制的
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
// 创建一个新的进程来启动各种系统服务
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
r.run();
return;
}
}
Log.i(TAG, "Accepting command socket connections");
// 这是一个while死循环,作为zygote的守护体存在
caller = zygoteServer.runSelectLoop(abiList);
}
...
}
复制代码
forkSystemServer 方法会创建一个新的进程来启动各种系统服务,此方法稍后再说。我们先来看下另一个核心方法runSelectLoop,这是一个while死循环,除非Zygote退出或者出现异常,否则不会跳出循环。部分代码见下:
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
// 获取上面Socket的文件描述符,并添加到ArrayList<FileDescriptor>的集合里
socketFDs.add(mZygoteSocket.getFileDescriptor());
// 添加null是为了保持fds和peers的一致性,对应的是Zygote Server Socket这个监听者
peers.add(null);
while (true) {
...
boolean usapPoolFDRead = false;
while (--pollIndex >= 0) {
// 当接收到客户端发出连接请求 或数据处理请求到来,则往下执行;
// 否则进入continue,跳出本次循环。
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
if (pollIndex == 0) {
// 有新的请求连接,通过此方法产生一个新的ZygoteConnection;
// 然后分别更新peers和fds
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
// 已建立的连接中,有客户端发送过来的数据需要处理
try {
ZygoteConnection connection = peers.get(pollIndex);
// 见下文
final Runnable command = connection.processOneCommand(this);
...
}
...
}
...
}
}
复制代码
核心方法processOneCommand,通过方法内部的forkAndSpecialize方法,为每个新启动的应用程序生成自己独立的进程,并在handleChildProc方法中运行应用程序本身的代码:
Runnable processOneCommand(ZygoteServer zygoteServer) {
...
// zygote为每个新启动的应用程序生成自己独立的进程
pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);
try {
if (pid == 0) {
// in child
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
// 进入子进程流程,通过此方法运行应用程序本身的代码
return handleChildProc(parsedArgs, descriptors, childPipeFd,
parsedArgs.mStartChildZygote);
} else {
// 父进程中,pid<0表示故障
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
handleParentProc(pid, descriptors, serverPipeFd);
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
复制代码
再回到 ZygoteInit main 主函数代码。在 forkSystemServer 方法内通过 forkSystemServer 方法创建了一个新的进程,其中 “–setuid=1000” 代表进程 ID,“–nice-name=system_server”代表进程名称。而这个进程接下来会执行 handleSystemServerProcess 方法,来启动支撑系统运行的 System Server。
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
...
/* 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,1021,1023,"
+ "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
ZygoteArguments parsedArgs = null;
int pid;
try {
// 用于解析参数,生成目标格式
parsedArgs = new ZygoteArguments(args);
Zygote.applyDebuggerSystemProperty(parsedArgs);
Zygote.applyInvokeWithSystemProperty(parsedArgs);
boolean profileSystemServer = SystemProperties.getBoolean(
"dalvik.vm.profilesystemserver", false);
if (profileSystemServer) {
parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}
// fork子进程,用于运行system_server
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
// 关闭zygote原有的socket
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
复制代码
在 handleSystemServerProcess 方法内,当 parsedArgs.mInvokeWith == null 时,会执行 ZygoteInit.zygoteInit 方法。
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
...
if (parsedArgs.mInvokeWith != null) {
String[] args = parsedArgs.mRemainingArgs;
...
WrapperInit.execApplication(parsedArgs.mInvokeWith,
parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
VMRuntime.getCurrentInstructionSet(), null, args);
throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
} else {
createSystemServerClassLoader();
ClassLoader cl = sCachedSystemServerClassLoader;
if (cl != null) {
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
*/
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, cl);
}
/* should never reach here */
}
复制代码
这是 zygoteInit 的逻辑,redirectLogStreams 关闭 system.out 和 system.err ,并重定向到 android log。commonInit 处理了通用部分的初始化操作,nativeZygoteInit 是本地初始化函数,负责本地系统服务的启动,而在 JNI 机制中, Native 函数在 Java 层会有一个声明,然后在本地层得到真正的实现。可见下文的 SystemServer().run() 方法内的 System.loadLibrary(“android_servers”) :
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
复制代码
在applicationInit方法中args.startClass即上文说的forkSystemServer创建服务进程时的args内的 “com.android.server.SystemServer”,findStaticMain方法将会反射调用 args.startClass的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);
}
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
return new MethodAndArgsCaller(m, argv);
}
复制代码
这是 SystemServer 的 main 主函数,也就是 applicationInit 反射调用的方法,它又会直接调用 SystemServer().run() 方法来实现 java 层系统服务的启动。
public static void main(String[] args) {
new SystemServer().run();
}
复制代码
在 run 方法中,准备主循环体,加载本地服务库到内存,并初始化本地服务,启动各种类型的 system server,通过 Looper.loop 进入长循环中,并依托 nativeZygoteInit 启动的 Binder 服务接受和处理外界请求。
private void run() {
try {
...
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
...
Looper.prepareMainLooper();
Looper.getMainLooper().setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
// Initialize native services.
System.loadLibrary("android_servers");
...
// Initialize the system context.
createSystemContext();
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
}
...
// Start services.
try {
traceBeginAndSlog("StartServices");
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
}
...
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
复制代码
总结
看着时序图脑海里重新回顾一下吧,意图是串联,而不是死磕细节:
好了,本文到这里就结束了。如果本文对你有用,来点个赞吧,大家的肯定也是阿呆i坚持写作的动力。