Android bootコードフロー1
39712 ワード
以前のこの編では、androidの起動プロセス全体が全体的に示されていたが、androidの起動がコードレベルでどのように呼び出されたのかを明らかにするために、ソースコードの観点から分析され、他のすべてのコードはandroid 4.0 source treeに基づいている.
all story begin with the init process startupストーリーinitプロセス開始から
Init運転、コード:system/core/init、入口:system/core/init.c main関数:
解析init.rcファイル、主に/system/core/init/init_parser.cで完了し、initを切り取る.rcの一部の内容は以下の通りです:(具体的なinit.rcファイル仕様、参照:/system/core/init/readme.txt)
init.rcはandroid init language仕様を使用しており、4つの文、Actions、Commands、Services、Optionsをサポートしています. Action定義方式: Commandは、export、hostname、mkdir、mountなど、システムがサポートする一連のコマンドです.その一部はlinuxコマンドで、androidが追加したものもあります.class_start:サービス開始、class_stop:サービスを閉じるなど. Service定義: Optionは、サービスのオプションです.たとえば、
はい、そうです.rcとinit.$hardware.rc 2ファイルはandroid init language仕様に従って解析が完了すると、実行するコマンドはすべて大きなaction_に配置されます.Listでは、initファイルの下を解析します.
Action_からlistで作成トリガを見つけ、トリガが実行するコマンドをaction_に追加します.Queueでは、最後にaction_を順番に実行します.queueのコマンドは初期化を完了し、いくつかの環境変数を設定したりフォルダを作成したりする以外は初期化を完了します.
もっと多いのはサービスの起動に関心を持って、initファイルの中のサービスは2種類あって、1種類はclass coreで、1種類はclass mainで、init.rcのサービスはclassによって以下のように分類される.
Serviceueventd:読み込み/ueventd.rcおよび/ueventd.$hadrware.rcファイル、解析とinit.rc解析は同様で、主にファイルシステムの権限とユーザーを設定します:(コード:system/core/init/ueventd.c)
class coreサービスが起動した後、class mainが起動し始め、service zygoteはandroidに入る最も重要なサービスであり、サービス名zygoteは、実際に起動したのはapp_である.process,(コード:frameworks/base/cmds/app_process/app_main.cpp)
入力パラメータが検出され、次のように呼び出されます.
runtimeのコード:frameworks/base/core/jni/Android Runtime.cpp,start関数は仮想マシンを起動しcomを実行する.android.internal.os.ZygoteInitクラスのmain関数で、パラメータ:start-system-server:
ZygoteInitクラスmain関数:
ではstartSystemServerはいったい何をしているのか、そして最後のシステムはどのようにACTIONを発行しているのか.BOOT_COMPLETEDが放送されていて、次回の分解を聞いています.-):
all story begin with the init process startupストーリーinitプロセス開始から
Init運転、コード:system/core/init、入口:system/core/init.c main関数:
1 int main(int argc, char **argv){
2
3 ...
4 //
5 mkdir("/dev", 0755);
6 mkdir("/proc", 0755);
7 mkdir("/sys", 0755);
8
9 mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
10 mkdir("/dev/pts", 0755);
11 mkdir("/dev/socket", 0755);
12 mount("devpts", "/dev/pts", "devpts", 0, NULL);
13 mount("proc", "/proc", "proc", 0, NULL);
14 mount("sysfs", "/sys", "sysfs", 0, NULL);
15
16 ...
17 // /init.rc /init.$hardware.rc , $hardware /proc/cpuinfo , goldfish
18 INFO("reading config file
");
19 init_parse_config_file("/init.rc");
20
21 /* pull the kernel commandline and ramdisk properties file in */
22 import_kernel_cmdline(0, import_kernel_nv);
23 /* don't expose the raw commandline to nonpriv processes */
24 chmod("/proc/cmdline", 0440);
25 get_hardware_name(hardware, &revision);
26 snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
27 init_parse_config_file(tmp);
28
29 ...
30 }
解析init.rcファイル、主に/system/core/init/init_parser.cで完了し、initを切り取る.rcの一部の内容は以下の通りです:(具体的なinit.rcファイル仕様、参照:/system/core/init/readme.txt)
on early-init
start ueventd
# create mountpoints
mkdir /mnt 0775 root system
# setup the global environment
export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
# Create cgroup mount points for process groups
mkdir /dev/cpuctl
mount cgroup none /dev/cpuctl cpu
chown system system /dev/cpuctl
chown system system /dev/cpuctl/tasks
chmod 0777 /dev/cpuctl/tasks
write /dev/cpuctl/cpu.shares 1024
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
init.rcはandroid init language仕様を使用しており、4つの文、Actions、Commands、Services、Optionsをサポートしています.
on <trigger> # on , , 3 :
<command> #1. , : on early-init;
<command> #2.name=value , :on property:vold.decrypt=trigger_reset_main;
<command> #3. , :device-added-<path>,device-removed-<path>,service-exited-<name>
<command> # , :start...,mkdir,...
service <name> <pathname> [ <argument> ]*
<option>
<option>
...
# : android zygote
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
setenv <name> <value>
user <username>
oneshot ,
class <classname> ,
socket <name> <type> <perm> [ <user> [ <group> ] ] <name> socket, socket
onrestart <command> <command>
はい、そうです.rcとinit.$hardware.rc 2ファイルはandroid init language仕様に従って解析が完了すると、実行するコマンドはすべて大きなaction_に配置されます.Listでは、initファイルの下を解析します.
// early-init , action_queue
action_for_each_trigger("early-init", action_add_queue_tail);
//
queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
queue_builtin_action(property_init_action, "property_init");
queue_builtin_action(keychord_init_action, "keychord_init");
queue_builtin_action(console_init_action, "console_init");
queue_builtin_action(set_init_properties_action, "set_init_properties");
/* execute all the boot actions to get us started */
action_for_each_trigger("init", action_add_queue_tail);
/* skip mounting filesystems in charger mode */
if (strcmp(bootmode, "charger") != 0) {
action_for_each_trigger("early-fs", action_add_queue_tail);
action_for_each_trigger("fs", action_add_queue_tail);
action_for_each_trigger("post-fs", action_add_queue_tail);
action_for_each_trigger("post-fs-data", action_add_queue_tail);
}
queue_builtin_action(property_service_init_action, "property_service_init");
queue_builtin_action(signal_init_action, "signal_init");
queue_builtin_action(check_startup_action, "check_startup");
if (!strcmp(bootmode, "charger")) {
action_for_each_trigger("charger", action_add_queue_tail);
} else {
action_for_each_trigger("early-boot", action_add_queue_tail);
action_for_each_trigger("boot", action_add_queue_tail);
}
/* run all property triggers based on current state of the properties */
queue_builtin_action(queue_property_triggers_action, "queue_propety_triggers");
...
// action_queue
for(;;) {
int nr, i, timeout = -1;
execute_one_command();
restart_processes();
...
}
Action_からlistで作成トリガを見つけ、トリガが実行するコマンドをaction_に追加します.Queueでは、最後にaction_を順番に実行します.queueのコマンドは初期化を完了し、いくつかの環境変数を設定したりフォルダを作成したりする以外は初期化を完了します.
もっと多いのはサービスの起動に関心を持って、initファイルの中のサービスは2種類あって、1種類はclass coreで、1種類はclass mainで、init.rcのサービスはclass
class core:
service ueventd /sbin/ueventd
service console /system/bin/sh
service adbd /sbin/adbd
service servicemanager /system/bin/servicemanager
service vold /system/bin/vold
class main:
service netd /system/bin/netd
service debuggerd /system/bin/debuggerd
service ril-daemon /system/bin/rild
service surfaceflinger /system/bin/surfaceflinger
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
service drm /system/bin/drmserver
service media /system/bin/mediaserver
service bootanim /system/bin/bootanimation
service dbus /system/bin/dbus-daemon --system --nofork
service bluetoothd /system/bin/bluetoothd -n
service installd /system/bin/installd
service flash_recovery /system/etc/install-recovery.sh
service racoon /system/bin/racoon
service mtpd /system/bin/mtpd
service keystore /system/bin/keystore /data/misc/keystore
service dumpstate /system/bin/dumpstate -s
Serviceueventd:読み込み/ueventd.rcおよび/ueventd.$hadrware.rcファイル、解析とinit.rc解析は同様で、主にファイルシステムの権限とユーザーを設定します:(コード:system/core/init/ueventd.c)
# user group
/dev/null 0666 root root
/dev/zero 0666 root root
class coreサービスが起動した後、class mainが起動し始め、service zygoteはandroidに入る最も重要なサービスであり、サービス名zygoteは、実際に起動したのはapp_である.process,(コード:frameworks/base/cmds/app_process/app_main.cpp)
int main(int argc, const char* const argv[])
{
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
// , init.rc : -Xzygote /system/bin --zygote --start-system-server for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--;
AppRuntime runtime;
const char* argv0 = argv[0]; //-Xzygote
// Process command line arguments
// ignore argv[0]
argc--; // 4, 3
argv++; //argv argv[1]
// Everything up to '--' or first non '-' arg goes to the vm
// i = 0, :frameworks/base/core/jni/AndroidRuntime.cpp
int i = runtime.addVmArguments(argc, argv);
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
const char* parentDir = NULL;
const char* niceName = NULL;
const char* className = NULL;
while (i < argc) {
const char* arg = argv[i++];
if (!parentDir) {
parentDir = arg; //parentDir = /system/bin
} else if (strcmp(arg, "--zygote") == 0) { // i = 2,arg = argv[1] , :--zygote
zygote = true;
niceName = "zygote";
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName = arg + 12;
} else {
className = arg;
break;
}
}
if (niceName && *niceName) {
setArgv0(argv0, niceName);
set_process_name(niceName);
}
runtime.mParentDir = parentDir;
if (zygote) {
// zygote = true, com.android.internal.os.ZygoteInit, :startSystemServer
runtime.start("com.android.internal.os.ZygoteInit",startSystemServer ? "start-system-server" : "");
} else if (className) {
// Remainder of args get passed to startup class main()
runtime.mClassName = className;
runtime.mArgC = argc - i;
runtime.mArgV = argv + i;
runtime.start("com.android.internal.os.RuntimeInit",
application ? "application" : "tool");
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.
");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
入力パラメータが検出され、次のように呼び出されます.
runtime.start("com.android.internal.os.ZygoteInit",startSystemServer ? "start-system-server" : "");
runtimeのコード:frameworks/base/core/jni/Android Runtime.cpp,start関数は仮想マシンを起動しcomを実行する.android.internal.os.ZygoteInitクラスのmain関数で、パラメータ:start-system-server:
void AndroidRuntime::start(const char* className, const char* options)
{
LOGD("
>>>>>> AndroidRuntime START %s <<<<<<
",
className != NULL ? className : "(unknown)");
...
/* start the virtual machine */
// dalvik ,
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) {
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) {
LOGE("Unable to register all android natives
");
return;
}
...
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
// com.xxx.xxx com/xxx/xxx
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
LOGE("JavaVM unable to locate class '%s'
", slashClassName);
/* keep going */
} else {
// jni java , class, main
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
LOGE("JavaVM unable to find main() in '%s'
", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
free(slashClassName);
LOGD("Shutting down VM
");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
LOGW("Warning: unable to detach main thread
");
if (mJavaVM->DestroyJavaVM() != 0)
LOGW("Warning: VM did not shut down cleanly
");
}
ZygoteInitクラスmain関数:
public static void main(String argv[]) {
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
// socket server
registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
// , preloadClasses() preloadResources(), /system/etc/event-log-tags
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.length != 2) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
if (argv[1].equals("start-system-server")) {
// Zygote main , start-system-server, startSystemServer()
startSystemServer();
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
if (ZYGOTE_FORK_MODE) {
runForkMode();
} else {
// registerZygoteSocket() server scocket, , Zygote
runSelectLoopMode();
}
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
ではstartSystemServerはいったい何をしているのか、そして最後のシステムはどのようにACTIONを発行しているのか.BOOT_COMPLETEDが放送されていて、次回の分解を聞いています.-):