看了很多相关博客,今天也来自己梳理以下~~~
Android从Linux系统启动
init进程启动
Native服务启动
System Server, Android 服务启动
Home启动
总体启动框架:
Init进程启动
首先uboot引导Linux内核启动,然后在用户空间中启动init进程,再启动其他系统进程。在系统启动完成完成后,init将变为守护进程监视系统其他进程。Android是基于Linux的操作系统,所以init也是Android系统中用户空间的第一个进程,它的进程号是1。
Init的主要职责是:
作为守护进程
解析核执行init.rc文件
生成设备节点
属性服务
源码在/system/core/init/init.c
int main(int argc, char **argv) {
//启动uevent守护进程
if (!strcmp(basename(argv[0]), "ueventd"))
return ueventd_main(argc, argv);
//启动看门狗守护进程
if (!strcmp(basename(argv[0]), "watchdogd"))
return watchdogd_main(argc, argv);
umask(0);
//创建并挂在启动所需的文件目录
mkdir("/dev", 0755);
mkdir("/proc", 0755);
mkdir("/sys", 0755);
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
mount("proc", "/proc", "proc", 0, NULL);
mount("sysfs", "/sys", "sysfs", 0, NULL);
close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000));
//重定向标准输入/输出/错误输出到/dev/_null_
open_devnull_stdio();
klog_init();//log初始化
property_init();//属性服务初始化
//从/proc/cpuinfo中读取Hardware名,在后面的mix_hwrng_into_linux_rng_action函 数中会将hardware的值设置给属性ro.hardware
get_hardware_name(hardware, &revision);
//导入并设置内核变量
process_kernel_cmdline();
......
INFO("property init\n");
if (!is_charger)
property_load_boot_defaults();
INFO("reading config file\n");
init_parse_config_file("/init.rc");//解析init.rc配置文件
/*
* 解析完init.rc后会得到一系列的action等,下面的代码将执行处于early-init阶段的 action。
* init将action按照执行时间段的不同分为early-init、init、early-boot、boot。
* 进行这样的划分是由于有些动作之间具有依赖关系,某些动作只有在其他动作完成后才能执行,所以就有了先后的区别。
* 具体哪些动作属于哪个阶段是在init.rc中的配置决定的
*/
action_for_each_trigger("early-init", action_add_queue_tail);
......
for(;;) {//init进入无限循环
......
execute_one_command();
restart_processes();//重启已经死去的进程
......
nr = poll(ufds, fd_count, timeout); //等待事件发生
if (nr <= 0)
continue;
for (i = 0; i < fd_count; i++) {
if (ufds[i].revents == POLLIN) {
if (ufds[i].fd == get_property_set_fd())//处理属性服务事件
handle_property_set_fd();
else if (ufds[i].fd == get_keychord_fd())//处理keychord事件
handle_keychord();
else if (ufds[i].fd == get_signal_fd())
handle_signal();//处理SIGCHLD信号事件
}
}
}
return 0;
}
看看init.rc脚本
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
ps:(1)这里描述了孵化器zygote的启动(init是zygote的父进程,而系统服务进程system_server和其他所有的com.xxx结尾的应用程序都是从zygote fork 而来)。
(2)前面的关键字service告诉init进程创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process,后面是要传给app_process的参数。最后的一系列onrestart关键字表示这个zygote进程重启时需要执行的命令。
了解了这个信息之后,我们就知道Zygote进程要执行的程序便是system/bin/app_process了,它的源代码位于frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。
int main(int argc, char* const argv[])
{
......
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i
main函数的主要作用就是创建一个AppRuntime变量,然后调用它的start函数。它的定义也在同一文件app_main.cpp下面class AppRuntime : public AndroidRuntime
(AndroidRuntime的源码在/frameworks/base/core/jni下,它是抽象基类);
在AndroidRuntime.h中定义了4种启动模式
enum StartMode {
Zygote,//启动Zygote
SystemServer,//启动系统服务
Application,//启动应用程序
Tool,//
};
再看看具体的start函数做了什么
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*
* Passes the main function two arguments, the class name and the specified
* options string.
*/
//上面的解释是开始android运行时环境。将开始虚拟机,然后用类似反射的机制去调用类名为参数className的main()方法!
void AndroidRuntime::start(const char* className, const char* options)
{
if (strcmp(options, "start-system-server") == 0) {
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
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, 1);
}
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) {//开启虚拟机
return;
}
onVmCreated(env);
/*
* Register android functions. 注册本地native函数
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring optionsStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(2, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
optionsStr = env->NewStringUTF(options);
env->SetObjectArrayElement(strArray, 1, 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);
} 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 {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
}
通过源代码的分析知道,其实上面主要是给一个应用程序分配一个虚拟机环境(虚拟机拷贝),然后通过JNI的方式去调java里某个className类的main()方法。
还记得runtime.start("com.android.internal.os.ZygoteInit", startSystemServer ? "start-system-server" : "");
实际执行com.android.internal.os.ZygoteInit类的main()(源码地址frameworks/base/core/java/com/android/internal/os/ZygoteInit.java):
public static void main(String argv[]) {
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
registerZygoteSocket();
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();
......
// If requested, start system server directly from Zygote
.......
if (argv[1].equals("start-system-server")) {
startSystemServer();//启动system_server进程
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
......
runSelectLoop();
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
......
}
}
它主要作了三件事情:
1、调用registerZygoteSocket函数创建了一个socket接口,用来和ActivityManagerService通讯;
2、调用startSystemServer函数来启动SystemServer组件;
3、调用runSelectLoopMode函数进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程。
这里Zygote进程初始化完毕,开始大循环了~~~
仔细分析下第二步startSystemServer启动系统服务组件
/**
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException {
/* 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);
......
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
......
}
/* For child process */
if (pid == 0) {//pid==0说明是子进程,父进程为Zygote
handleSystemServerProcess(parsedArgs);
}
return true;
}
在startSystemServer中先设置了Zygote.forkSystemServer所需的参数,然后通过forkSystemServer方法fork出SystemServer进程,最后通过handleSystemServerProcess处理新进程中的琐事。
首先看一下参数:
1、setuid=1000,这里1000代表SYSTEM_UID,即系统进程,关于进程ID的说明可以参见:/frameworks/base/core/java/android/os/Process.java。
2、nice-name=system_server表示制定进程的名字为“system_server”
3、com.android.server.SystemServer表示SystemServer类的位置。
接下来看一下forkSystemServer的实现:
libcore/dalvik/src/main/java/dalvik/system/Zygote.java
/**
* Special method to start the system server process. In addition to the
* common actions performed in forkAndSpecialize, the pid of the child
* process is recorded such that the death of the child process will cause
* zygote to exit.
* 注意由zygote fork 出的system_service进程如果死了,则zygote进程也退出
*/
public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
preFork();
int pid = nativeForkSystemServer(
uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
postFork();
return pid;
}
native public static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
forkSystemServer最后调nativeForkSystemServer,而它是通过JNI实现,源码:/dalvik/vm/native/dalvik_system_Zygote.cpp:
static void Dalvik_dalvik_system_Zygote_forkSystemServer(
const u4* args, JValue* pResult)
{
pid_t pid;
pid = forkAndSpecializeCommon(args, true);
/* The zygote process checks whether the child process has died or not. */
if (pid > 0) {//pid大于0,说明是在父进程中,Zygote进程往下执行
int status;
gDvm.systemServerPid = pid;
/* There is a slight window that the system server process has crashed
* but it went unnoticed because we haven't published its pid yet. So
* we recheck here just to make sure that all is well.
*/
if (waitpid(pid, &status, WNOHANG) == pid) {
ALOGE("System server process %d has died. Restarting Zygote!", pid);
kill(getpid(), SIGKILL);//一旦上面的等待返回,说明进程pid(system_server)已终止,此时Zygote杀死自己
}
}
RETURN_INT(pid);
}
//native函数注册
const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {
{ "nativeFork", "()I",
Dalvik_dalvik_system_Zygote_fork },
{ "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;)I",
Dalvik_dalvik_system_Zygote_forkAndSpecialize },
{ "nativeForkSystemServer", "(II[II[[IJJ)I",
Dalvik_dalvik_system_Zygote_forkSystemServer },
{ NULL, NULL, NULL },
};
SystemServer创建之后交给handleSystemServerProcess处理!
回到 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
/**
* Finish remaining work for the newly forked system server process.
* 完成新建的system server进程的剩余工作
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket();//关闭从Zygote复制过来的socket
// set umask to 0077 so new files and directories will default to owner-only permissions.
Libcore.os.umask(S_IRWXG | S_IRWXO);//设置文件的默认权限,去除文件所有者之外的权限
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
null, parsedArgs.remainingArgs);
} else {
/*
* Pass the remaining arguments to SystemServer.传递剩下的参数给SystemServer
*/
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
}
/* should never reach here */
}
最后将参数往下传给RuntimeInit.zygoteInit(,)
源码:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
/**
* The main function called when started through the zygote process. This
* could be unified with main(), if the native code in nativeFinishInit()
* were rationalized with Zygote startup.
*/
public static final void zygoteInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
redirectLogStreams();//将System.out 和 System.err 输出重定向到Android 的Log系统
/*
* 初始化了一些系统属性,其中最重要的一点就是设置了一个未捕捉异常的handler,
* 当代码有任何未知异常,就会执行它,
* 调试过Android代码的同学经常看到的"*** FATAL EXCEPTION IN SYSTEM PROCESS" 打印就出自这里
*/
commonInit();
/*
* 最终会调用app_main的onZygoteInit函数
* 这里的作用是在新进程中引入Binder,也就说通过nativeZygoteInit以后,新的进程就可以使用Binder进程通信了
*/
nativeZygoteInit();
applicationInit(targetSdkVersion, argv);//应用初始化
}
private static void applicationInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
// Android runtime shutdown hooks close the Binder driver, which can cause
// leftover running threads to crash before the process actually exits.
nativeSetExitWithoutCleanup(true);
// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
try {
args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
Slog.e(TAG, ex.getMessage());
// let the process exit
return;
}
// Remaining arguments are passed to the start class's static main
invokeStaticMain(args.startClass, args.startArgs);
}
这里invokeStaticMain的args.startClass的值为com.android.server.SystemServer。接下来SystemServer类的main函数将会被调用,我太机智了~。
源码:frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
/*
* In case the runtime switched since last boot (such as when
* the old runtime was removed in an OTA), set the system
* property so that it is in sync.
*/
SystemProperties.set("persist.sys.dalvik.vm.lib",
VMRuntime.getRuntime().vmLibrary());
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {//调整时间
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
......
// Mmmmmm... more memory!
dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
// The system server has to run all of the time, so it needs to be
// as efficient as possible with its memory usage.
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
Environment.setUserRequired(true);
System.loadLibrary("android_servers");
Slog.i(TAG, "Entered the Android system server!");
// Initialize native services.
nativeInit();//初始化本地所以服务 > SensorService
// This used to be its own separate thread, but now it is
// just the loop we run on the main thread.
ServerThread thr = new ServerThread();
thr.initAndLoop();
}
在main中会加载libandroid_servers.so库,然后调用nativeInit初始化native层的Service。
ServerThread初始化一堆android服务。
小结一下:
- Linux的init在启动若干守护进程之后,就启动了Android的runtime和zygote,Zygote进程负责后续Android应用程序框架层的其它进程的创建和启动工作。
- Zygote进程会首先创建一个SystemServer进程,SystemServer进程负责启动系统的关键服务,如包管理服务PackageManagerService和应用程序组件管理服务ActivityManagerService。
- 当我们需要启动一个Android应用程序时,ActivityManagerService会通过Socket进程间通信机制,通知Zygote进程为这个应用程序创建一个新的进程。