一个android系统的设备开机过程总的可以分成三部分:bootloader,kernel,android。网上有张图片做的很好
对于前两个网上有太多的说明和教程,本人也没有太多的时间去研究,因此暂且搁置了,以后如果有时间的话会再补上。我们重点来开android启动的过程。 上图
1. 当linux kernel启动后,运行的第一个用户空间进程是init,,大家在设备上运行ps命令,查看这个进程的pid为1来验证这一点。这个进程是系统运行过程中一直存在的。它的代码是“\android\system\core\init\init.c”,这是一个标准的linux应用程序。它启动了系统运行做了很多初始化, 下面我们来看init的main函数
int main(int argc, char **argv)
{
int fd_count = 0;
struct pollfd ufds[4];
char *tmpdev;
char* debuggable;
char tmp[32];
int property_set_fd_init = 0;
int signal_fd_init = 0;
int keychord_fd_init = 0;
//参数argv[0]是内核传过来的ueventd的路径名,如果在路径中找到"ueventd"这个文件那
//么就执行ueventd_main(argc, argv);这个程序,否则就执行自己的代码
if (!strcmp(basename(argv[0]),"ueventd"))
return ueventd_main(argc, argv);
/* clear the umask */
umask(0);
/* Get the basic filesystem setup weneed put
* together in the initramdisk on / andthen we'll
* let the rc file figure out the rest.
*/
//创建一些文件系统的目录
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);
/* indicate that booting is in progressto background fw loaders, etc */
close(open("/dev/.booting",O_WRONLY | O_CREAT, 0000));
/* We must have some place other than /to create the
* device nodes for kmsg and null,otherwise we won't
* be able to remount / read-only lateron.
* Now that tmpfs is mounted on /dev,we can actually
* talk to the outside world.
*/
open_devnull_stdio(); //创建和打开"/dev/__null__" 虚拟设备(类似于 Linux //系统中的 /dev/null 设备)并将stdin/stdout/stderr 三//个文件重定向到 "/dev/__null__"
klog_init();//创建和打开"/dev/__kmsg__" 虚拟设备用于记录 log
INFO("reading config file\n");
init_parse_config_file("/init.rc"); //解析 并执行init.rc
/* pull the kernel commandline and ramdiskproperties file in */
import_kernel_cmdline(0, import_kernel_nv);//导入 内核的 commandline
/* don't expose the raw commandline tononpriv processes */
chmod("/proc/cmdline", 0440); //修改其权限
get_hardware_name(hardware, &revision);//得到硬件名称
snprintf(tmp, sizeof(tmp),"/init.%s.rc", hardware);//并整理好初始化这个硬件脚本名字
init_parse_config_file(tmp);//执行这个脚本
//初始化一些命令队列。向action_list队列里面添加各种命令
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 usstarted */
action_for_each_trigger("init",action_add_queue_tail);
/* skip mounting filesystems in chargermode */
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 oncurrent state of the properties */
queue_builtin_action(queue_property_triggers_action,"queue_propety_triggers");
#ifBOOTCHART
queue_builtin_action(bootchart_init_action,"bootchart_init");
#endif
for(;;) {
int nr, i, timeout = -1;
execute_one_command();//执行一条前面整理的命令
restart_processes();//如果某些服务需要重启的话,就重启他们
//注册三个文件描述符,并监听他们,如果收到相应的信号,就执行相应的处理函数
if (!property_set_fd_init &&get_property_set_fd() > 0) {
ufds[fd_count].fd =get_property_set_fd();
ufds[fd_count].events = POLLIN;
ufds[fd_count].revents = 0;
fd_count++;
property_set_fd_init = 1;
}
if (!signal_fd_init &&get_signal_fd() > 0) {
ufds[fd_count].fd =get_signal_fd();
ufds[fd_count].events = POLLIN;
ufds[fd_count].revents = 0;
fd_count++;
signal_fd_init = 1;
}
if (!keychord_fd_init &&get_keychord_fd() > 0) {
ufds[fd_count].fd =get_keychord_fd();
ufds[fd_count].events = POLLIN;
ufds[fd_count].revents = 0;
fd_count++;
keychord_fd_init = 1;
}
if (process_needs_restart) {
timeout = (process_needs_restart -gettime()) * 1000;
if (timeout < 0)
timeout = 0;
}
if (!action_queue_empty() ||cur_action)
timeout = 0;
#ifBOOTCHART
if (bootchart_count > 0) {
if (timeout < 0 || timeout >BOOTCHART_POLLING_MS)
timeout = BOOTCHART_POLLING_MS;
if (bootchart_step() < 0 ||--bootchart_count == 0) {
bootchart_finish();
bootchart_count = 0;
}
}
#endif
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())
handle_keychord();
else if (ufds[i].fd ==get_signal_fd())
handle_signal();
}
}
}
return 0;
}
分析上面函数,除了初始化,我们主要看它建立的服务,因为这才是系统启动下一步的关键。系统建立的服务主要在init.rc中,下面列出init.rc中所有启动的服务
## Daemonprocesses to be run by init.
##
serviceueventd /sbin/ueventd
class core
critical
serviceconsole /system/bin/sh
class core
console
disabled
user shell
group log
# adbd iscontrolled via property triggers in init.<platform>.usb.rc
service adbd /sbin/adbd
class core
disabled
serviceservicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm
servicevold /system/bin/vold
class core
socket vold stream 0660 root mount
ioprio be 2
servicenetd /system/bin/netd
class main
socket netd stream 0660 root system
socket dnsproxyd stream 0660 root inet
servicedebuggerd /system/bin/debuggerd
class main
serviceril-daemon /system/bin/rild
class main
socket rild stream 660 root radio
socket rild-debug stream 660 radio system
user root
group radio cache inet misc audio sdcard_rwlog
servicesurfaceflinger /system/bin/surfaceflinger
class main
user system
group graphics
onrestart restart zygote
servicezygote /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
servicedrm /system/bin/drmserver
class main
user drm
group system inet drmrpc
servicemedia /system/bin/mediaserver
class main
user media
group audio camera inet net_bt net_bt_adminnet_bw_acct drmrpc
ioprio rt 4
servicebootanim /system/bin/bootanimation
class main
user graphics
group graphics
disabled
oneshot
servicedbus /system/bin/dbus-daemon --system --nofork
class main
socket dbus stream 660 bluetooth bluetooth
user bluetooth
group bluetooth net_bt_admin
servicebluetoothd /system/bin/bluetoothd -n
class main
socket bluetooth stream 660 bluetoothbluetooth
socket dbus_bluetooth stream 660 bluetoothbluetooth
# init.rc does not yet support applyingcapabilities, so run as root and
# let bluetoothd drop uid to bluetooth withthe right linux capabilities
group bluetooth net_bt_admin misc
disabled
serviceinstalld /system/bin/installd
class main
socket installd stream 600 system system
serviceflash_recovery /system/etc/install-recovery.sh
class main
oneshot
serviceracoon /system/bin/racoon
class main
socket racoon stream 600 system system
# IKE uses UDP port 500. Racoon will setuidto vpn after binding the port.
group vpn net_admin inet
disabled
oneshot
servicemtpd /system/bin/mtpd
class main
socket mtpd stream 600 system system
user vpn
group vpn net_admin inet net_raw
disabled
oneshot
servicekeystore /system/bin/keystore /data/misc/keystore
class main
user keystore
group keystore
socket keystore stream 666
servicedumpstate /system/bin/dumpstate -s
class main
socket dumpstate stream 0660 shell log
disabled
oneshot
其中最重要的两个: servicemanager zygote
servicemanager:用来管理系统中所有的服务,不管是本地的c++实现的还是java语言实现的都需要这个进程来统一管理,最主要的管理就是,注册添加服务,获取服务。所有的Service使用前都必须先在servicemanager中进行注册。
Zygote:Zygote这个进程是非常重要的一个进程,Zygote进程的建立是真正的Android运行空间,在android运行空间上,系统又会启动很多服务属于android服务
对于android的服务可以分为三类:
参考:(http://blog.csdn.net/maxleng/article/details/5504485)
Native服务:是init.rc建立的服务,也就是我们上面列的所有都属于这个范畴
Android服务:是在java虚拟机上建立起来的服务 在Zygote之后
Init空间的服务:主要是属性设置。
2. Zygote
Zygote建立起了JVM(java虚拟机),也就建立了android运行空间。Zygote的代码在\frameworks\base\cmds\app_process\app_main.cpp中
int main(int argc, const char* const argv[])
{
AppRuntime runtime;
。。。。。。。。。
if (zygote){
runtime.start("com.android.internal.os.ZygoteInit", startSystemServer ?"start-system-server" : "");//
//建立虚拟机"com.android.internal.os.ZygoteInit",并运行
}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 --zygotesupplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygotesupplied.");
return 10;
}
runtime.start()是建立虚拟机的函数,相关代码在frameworks\base\core\jni\AndroidRuntime.cpp中,这里不做说明了。在虚拟机建立的过程中,系统注册了虚拟机建成后所运行的第一个进程即com.android.internal.os.ZygoteInit。这个进程是对android运行空间的一些初始化。所在代码
frameworks\base\core\java\com\android\internal\os\ZygoteInit.java。在代码中建立了一些socket,查了很多资料才弄明白是干什么用的。总的来讲Android系统中的socket机制是一种进程间通信的机制,在这里它用来和ActivityManagerService通讯,每当建立一个新的android应用程序是,它会通信一次。参考http://blog.csdn.net/luoshengyang/article/details/6768304
当socket建立完成后Zygote才算真正的建立完。
3. Android空间搭建过程中,在socket进入阻塞之前,调用了startSystemServer()这个函数 代码在:frameworks\base\core\java\com\android\internal\os\ZygoteInit.java中
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,3001,3002,3003,3006,3007",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
。。。。。。。
}
在这个函数中,建立了一个进程"com.android.server.SystemServer",用来执行systemserver, systemserver得到代码在frameworks\base\services\java\com\android\server\SystemServer.java中
public static void main(String[]args) {
。。。。。
。。。。。。。。。
。。。。。。。。
init1(args);
}
这里的init1(args);定义一定要仔细看
native public static voidinit1(String[] args);
前面有native关键字,这说明这个函数是在native空间实现的具体代码在
frameworks\base\services\jni\com_android_server_SystemServer.cpp中
static voidandroid_server_SystemServer_init1(JNIEnv* env, jobject clazz)
{
system_init();
}
/*
* JNI registration.
*/
static JNINativeMethod gMethods[]= {
/* name, signature, funcPtr */
{ "init1", "([Ljava/lang/String;)V", (void*)android_server_SystemServer_init1 },
};
intregister_android_server_SystemServer(JNIEnv* env)
{
return jniRegisterNativeMethods(env,"com/android/server/SystemServer",
gMethods, NELEM(gMethods));
}
上述函数中调用了system_init函数 这个函数在\frameworks\base\cmds\system_server\library\system_init.cpp中
extern "C" status_tsystem_init()
{
。。。。。。。
。。。。。。。。。。。。
jclass clazz = env->FindClass("com/android/server/SystemServer");
if (clazz == NULL) {
return UNKNOWN_ERROR;
}
jmethodID methodId = env->GetStaticMethodID(clazz, "init2","()V");
if (methodId == NULL) {
return UNKNOWN_ERROR;
}
env->CallStaticVoidMethod(clazz, methodId);
LOGI("System server: entering thread pool.\n");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
LOGI("System server: exiting thread pool.\n");
return NO_ERROR;
}
从这个函数中可以看到它调用了init2()这个函数,这个函数在刚才的frameworks\base\services\java\com\android\server\SystemServer.java文件中,建立了ServerThread,来为New Service和AddService来建立服务
建立完服务以后,我们看到ProcessState::self()->startThreadPool();进程在这里开始循环,也表示systemserver建立完成
4. Init2()函数中建立的心线程
class ServerThread extends Thread {
。。。。。。。
。。。。。。。
ActivityManagerService.self().systemReady(new Runnable()
。。。。。
。。。。。。。
。。。}
这里调用了ActivityManagerService.self().systemReady()函数 用来通知sevice已经建立完成系统可以正常运行了。我们来看这个函数
\frameworks\base\services\java\com\android\server\am\ ActivityManagerService.java中
public void systemReady(final RunnablegoingCallback) {
synchronized(this) {
if (mSystemReady) {
if (goingCallback != null)goingCallback.run();
return;
}
。。。。
。。。。
。。。
mMainStack.resumeTopActivityLocked(null);
}
resumeTopActivityLocked在\frameworks\base\services\java\com\android\server\am\
ActivityStack.java中
final booleanresumeTopActivityLocked(ActivityRecord prev) {
// Find the first activity that is not finishing.
ActivityRecord next = topRunningActivityLocked(null);
。。。。。。。
。。。。。。。。
。。。。。。。
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
if (mMainStack) {
returnmService.startHomeActivityLocked();//打开第一个应用程序 即桌面
}
}
。。。。。。。
。。。。。。
}
这样我们的开机过程才算真正完成
由于本人菜鸟参考了大量前辈们的资料,然后自己一点点看代码才写出来的。个人感觉水平非常一般,有很多概念没解释清楚,流程也比较乱,跟前辈们差距很大。在这里把他们的文章贴出来,大家共同学习,共同努力,争取有一天我也能写出那么深刻的文章。
参考资料:
http://blog.csdn.net/maxleng/article/details/5508372
http://blog.csdn.net/maxleng/article/details/5504485
http://blog.csdn.net/maxleng/article/details/5508488
http://www.cnblogs.com/bastard/archive/2012/08/28/2660389.html