Android2.2 boot process details
[正文开始]
启动第一步--CPU固件启动
对于桌面PC来说,存在bios和mbr(master boot record)。而多数移动设备不存在bios,CPU上电reset后从固件mbr开始执行必要的初始动作,然后就是load Boot程序。
启动第二步--Boot Loader
Boot Loader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核做好一切准备。
常见BootLoader有U-boot,x-boot。以我参考平台君正JZ4770(mips)x-boot为例:
1. 链接文件x-boot.lds指名boot入口函数ENTRY(_start)
2. Boot/init/init.S跳转到C函数boot_main
3. 初始化板极gpio,ldo
4. Lcd init,显示开机logo
5. nand_boot(NORMAL_BOOT)
6. Load kernel和ramdisk img到内存
7. 通过制定kernel image起始地址跳转到kernel,
kernel=(void(*)(int,char**,char*))CFG_KERNEL_DST;
(*kernel)(2, (char **)(PARAM_BASE + 16), (char *)PARAM_BASE);
启动第三步--加载内核
1. 链接文件vmlinux.lds指定kernel入口函数ENTRY(kernel_entry)
2. 跳转到C函数start_kernel
3. 内存,中断,时钟,控制台等初始化
4. 最后rest_init中do_basic_setup,do_initcalls开始进行外设的挂载,外设的挂载过程后面再详述
5. 至此Linux内核已经建立起来了,基于Linux的程序应该可以正常运行了
6. init_post启动了第一个程序run_init_process("/init")
启动第四步--用户层init
内核被加载后,最开始运行的程序便是/init,并依据此文件来进行初始化工作。
源代码位置:/system/core/init,其作用:
http://bbs.hiapk.com/thread-6388-1-1.html 这篇帖子大致说明了init程序作用,最主要的就是:
1. 解析/init.rc文件。/system/core/init/readme.txt是对init.rc文件的编写说明,主要由四大类声明组成:行为类(Actions),命令类(Commands),服务类(Services),选项类(Options)
2. 解析文件/init.goldfish.rc(平台名称),parse_config_file将action和service保存在两个链表action_list与service_list中
3. 显示开机log图片,如果失败显示ANDROID字符
4. 最后进入主程序循环:
nr = poll(ufds, fd_count, timeout);
if (ufds[0].revents == POLLIN)
handle_device_fd(device_fd);
if (ufds[1].revents == POLLIN)
handle_property_set_fd(property_set_fd);
if (ufds[3].revents == POLLIN)
handle_keychord(keychord_fd);
主循环主要是监听两个localSocket和"/dev/keychord"文件:
device_fd是基于getpid的localSocket,用于监听设备plugin,plugout事件,handle_device_fd负责设备挂载移除;
property_set_fd是localSocket "property_service"的fd,负责监听是否有property属性改变。终端模式下我们可以通过执行命令 setprop改变属性,工具源代码所在文件:/system/core/toolbox。所以如果在终端下输入:setprop property:persist.service.adb.enable 1或者0,那么将会开启或者关闭adbd 程序。
keychord_fd是文件"/dev/keychord"句柄,感觉是debug模式下用来重新service_start(svc, NULL)的接口
启动第五步--关键服务zygote
Init.rc启动了一个关键服务zygote,源代码位置:/framework/base/cmds/app_process。
AndroidRuntime::start方法启动虚拟机并调用”className”的”static void main(String[] args)”方法。利用JNIEnv,C++方法调用JAVA class的案例,具体没研究。
Runtime.start(“com.android.internal.os.ZygoteInit”,startSystemServer)调用ZygoteInit.main()
Zygote 是android 系统中最重要的一个服务,它将一步一步完成下面的任务:
1. 创建JAVA 虚拟机
2. 为JAVA 虚拟机注册android 本地函数
3. 调用 com.android.internal.os.ZygoteInit 类中的main函数
装载ZygoteInit类
注册registerZygoteSocket();
装载preloadClasses();
装载preloadResources();
4.调用 Zygote::forkSystemServer (源代码位置:/dalvik/vm/native/dalvik_system_Zygote.c)来fork一个新的进程,在新进程中调用 com.android.server.SystemServer 的main函数。
装载 libandroid_servers.so库
5.调用native init1:/frameworks/base/services/jni/com_android_server_SystemServer.cpp.
初始化SurfaceFlinger::instantiate();
初始化AudioFlinger::instantiate();
初始化MediaPlayerService::instantiate();
初始化CameraService::instantiate();
初始化AudioPolicyService::instantiate();
补充:模拟器上后面四个service是由system_server启动的,deivce上这四个service是由mediaserver启动的,专门为多媒体起了一个进程。
6.Callback回调runtime->callStatic("com/android/server/SystemServer", "init2");
SystemServer::init2 将会启动一个新的线程"android.server.ServerThread"来启动下面的所有JAVA服务:
Core 服务:
Starting Power Manager(电源管理)
Creating Activity Manager(活动服务)
Starting Telephony Registry(电话注册服务)
Starting Package Manager(包管理器)
Set Activity Manager Service as System Process
Starting Context Manager
Starting System Context Providers
Starting Battery Service(电池服务)
Starting Lights Service(Lights服务)
Starting Vibrator Service(振动器服务)
Starting Alarm Manager(闹钟服务)
Starting Watchdog Service (看门狗服务)
Starting Sensor Service
Starting Window Manager(启动窗口管理器)
Starting Bluetooth Service(蓝牙服务)
Starting Mount Service
其他services:
Starting Status Bar Service(状态服务)
Starting Hardware Service(硬件服务)
Starting NetStat Service(网络状态服务)
Starting Connectivity Service
Starting Notification Manager
Starting DeviceStorageMonitor Service
Starting Location Manager
Starting Search Service(查询服务)
Starting Clipboard Service
Starting Checkin Service
Starting Wallpaper Service
Starting Audio Service
Starting HeadsetObserver
Starting AdbSettingsObserver
补充:Init.rc中列出的service是指需要fork()得到子进程,而init2中starting service只是添加一个binder给ServiceManager,给其他进程提供服务。
7.android.server.ServerThread最后通知activity manager开始launching init applications
((ActivityManagerService)ActivityManagerNative.getDefault()).systemReady
ActivityManagerService.resumeTopActivityLocked(null); 通过发送Intent.CATEGORY_HOME intent来启动第一个 activity,至此我们就看到了熟悉的launcher界面。
在背后,还有复杂的底层函数调用与实现,本文仅供大家参考学习,如有错误请不吝指正!
本文参考了如下文章,荟萃而成:
http://roclinux.cn/?p=1301
http://blog.chinaunix.net/uid-2630593-id-2955923.html
http://bbs.hiapk.com/thread-6388-1-1.html
http://blog.chinaunix.net/uid-27025492-id-3280767.html
感谢上述文章作者:)