免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3168 | 回复: 0
打印 上一主题 下一主题

Android 启动过程总结-有3篇 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-11-01 13:32 |只看该作者 |倒序浏览

                [color="#000000"]分别来自

[color="#000000"]http://dingpwen.spaces.live.com/blog/cns!4CADD02D22459860!208.entry?fl=cat
[color="#000000"]http://www.eepw.com.cn/article/89567.htm
[color="#000000"]http://blog.csdn.net/guiterb/archive/2009/04/03/4047369.aspx
[color="#000000"]#####################################################

[color="#000000"]1. Boot系统初始化, 具体过程参见(system\core\init\Init.c)中的main函数,这时候,手机或者模拟器出现的画面是一个console,显示“ANDROID”msg。
[color="#000000"]
[color="#000000"]2. 初始化成功后,就开始mounting系统,具体参见(system\core\mountd\Mountd.c)  中的main函数。
[color="#000000"]
[color="#000000"]3.接下来运行ndroidRuntime,并开始启动java虚拟机dalvikvm。
[color="#000000"]
[color="#000000"]4. Java虚拟机启动成功后,开始系统初始化。系统初始的第一步是用JNI方式实现的,对应java代码为(frameworks\base\services\java\com\android\server\SystemServer.java) init1(Native)函数,对应的JNI C++代码为(frameworks\base\core\jni\server\com_android_server_SystemServer.cpp),而实现的C++代码为
[color="#000000"](frameworks\base\cmds\system_server\library\ System_init.cpp)   中的system_init()函数。
[color="#000000"]
[color="#000000"]5. system_init调用SurfaceFlinger,SurfaceFlinger的readyToRun()函数用BootAnimation来实现开机动画,这时候手机或者模拟器显示是一副背景图加一个动态的小机器人。
[color="#000000"]
[color="#000000"]6. 系统初始化的第二步,将启动ServerThread进程,参见SystemServer.init2()。ServerThread将启动各种系统服务,如Power Manager、Activity Manager等等,具体参见ServerThread的run函数,ServerThread同在SystemServer.java中。
[color="#000000"]
[color="#000000"]7.这之后的事,应该就是进入系统了。(这部分没有调查过)。
[color="#000000"]
#####################################################
对于关注
Android
底层的朋友来说,其具体的启动过程应该是比较吸引我们的。但是很多启动文件什么的,都得adb push到host上来看,挺不方便的,都怪
Android
自带的Toolbox太简略了。所以在深入了解
Android
的启动流程之前,我们来把Busybox安装到
Android
上去,这样,就有很多工具供我们使用了。
  首先去busybox主页 下载最新版本的源代码,然后用arm的交叉编译器编译出busybox的可执行程序,编译的时候需要注意一些设置选项,例如
  Build Options —>
  Build BusyBox as a static binary (no shared libs) 这个要选上,因上这样子编译出来的busyBox才是可以独立运行的。
  │Do you want to build BusyBox with a Cross Compiler? │ │
  │ │(/HOME/toolchains/gcc-4.0.2-glibc-2.3.5/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu│ 这是交叉编译器的路径,要根据具体的情况来设置。
  Installation Options —>
  Don’t use /usr
  这样子编译出来的busybox才不会安装到你主机的/usr目录下。一定要选上。
  busybox的功能选项根据需要自选,但是不要太贪心.
  OK,这里就不纠缠于编译busybox的东西了,网上资料无数。接下来,我们把busybox安装到模拟器上去。先在模拟器上随便建一个busybox的文件夹,然后进入busybox可执行文件目录,使用命令
  adb push busybox.asc /data/busybox/busybox
  然后进入adb shell,chmod 777
./busybox,就可以直接使用了。但现在还是不方便,总不能每用一个命令就输一次busybox吧?所以,我们可以先用./busybox
--install将程序都安装到当前目录下,然后把当前目录添加到PATH变量中即可。暂时使用export来添加吧,如果想永久添加,往下看。
  好了,准备工作完成,开始研究的工作了。既然是研究启动过程,那当然是先看看init.rc文件。去etc目录打开它,分析一下内容,首先是对
env的定义,也就是全局环境变量的定义,接下来的建立和初始化里面的内容目前还不清楚什么意思,紧接着就是系统启动时运行的初始进程信息,这个比较有意
思,包括了usbd-config和qemu,qemu自不用说,而usbd-config作为初始启动的进程,应该就是和上一篇文章猜的一样,用来调试
或者usb通信的。往下看,是在初始启动进程完成之后开始启动的服务进程,这些进程如果因故退出,会自动重启。这里面包括了console控制
台,adbd监护进程,usbd监护进程,debuggerd监护进程等.除去这些守护进程,能引起我们注意的,是runtime和zygote。这两个
进程似乎掌管着其他进程以及应用程序的启动。
  现在,来让我们做一个实验吧,将自动调用的启动过程变成手动,看看启动流程具体是什么样的。想达到这个目的,首先就是要修改init.rc文
件,当然不是在模拟器的console中改,一是不能改,二是你改了也没用,下次加载就会给你覆盖了。所以,我们要从原始镜像ramdisk.img入手
了。从2.6标准Linux内核开始,initrd.img都采用cpio压缩,猜测ramdisk.img也一样,需要使用gunzip解压缩,然后再
使用cpio解包。好,进入tools/lib/images目录下,先用file命令看看ramdisk.img的类型,没错,系统提示
  ramdisk.img: gzip compressed data, from Unix
  很好,然后将ramdisk.img复制一份到任何其他目录下,将其名称改为ramdisk.img.gz,并使用命令
  gunzip ramdisk.img.gz
  然后新建一个文件夹,叫ramdisk吧,进入,输入命令
  cpio -i -F ../ramdisk.img
  这下,你就能看见并操作ramdisk里面的内容了。当然你也可以直接在外面进行操作,但是还是建议把cpio解压缩出来的内容全部集中在一个文件夹里面,因为一会我们还要将其压缩成新的ramdisk.img。
  OK,现在开始修改步骤吧。用任何一款编辑器打开init.rc,首先在PATH那里加上你的Busybox安装路径,然后注释内容,我们要手工启动他们。
  # zygote {
  # exec /system/bin/app_process
  # args {
  # 0 -Xzygote
  # 1 /system/bin
  # 2 –zygote
  # }
  # autostart 1
  # }# runtime {
  # exec /system/bin/runtime
  # autostart 1
  # }
  在这里需要注意,不要同时把两者都注释了,注释某一个,再试验手工启动它,如果两者同时注释我这里有问题,无法启动。
  好,接下来,使用下列命令重新打包成镜像
  cpio -i -t -F ../ramdisk.img > list
  cpio -o -H newc -O lk.img #####################################################
                                       
                                       
                               
                               
                                       
                                       
                                       
[First written by Steve Guo, please keep the mark if forwarding.].


init
is the first process after kernel started. The corresponding source
code lies in: device/system/init. It does the following tasks step by
step:
1.       Initialize log system.
2.       Parse /init.rc and /init.%hardware%.rc.
3.       Execute early-init action in the two files parsed in step 2.
4.       Device specific initialize. For example, make all device node in /dev and download firmwares.
5.       Initialize
property system. Actually the property system is working as a share
memory. Logically it looks like a registry under Windows system.
6.       Execute init action in the two files parsed in step 2.
7.       Start property service.
8.       Execute early-boot and boot actions in the two files parsed in step 2.
9.       Execute property action in the two files parsed in step 2.
10.   Enter
into an indefinite loop to wait for device/property set/child process
exit events. For example, if an SD card is plugined, init will receive
a device add event, so it can make node for the device. Most of the
important process is forked in init, so if any of them crashed, init
will receive a SIGCHLD then translate it into a child process exit
event, so in the loop init can handle the process exit event and
execute the commands defined in *.rc(it will run command onrestart).
  
The
.rc file is a script file defined by Android. The default is
device/system/rootdir/init.rc. We can take a loot at the file
format(device/system/init/readme.txt is a good overall introduction of
the script). Basically the script file contains actions and services.
  
Actions
-------
Actions are named sequences of commands. Actions have a trigger which is used to determine when the action should occur.  When
an event occurs which matches an action's trigger, that action is added
to the tail of a to-be-executed queue (unless it is already on the
queue).
Each action in the queue is dequeued in sequence and each command in that action is executed in sequence.  Init
handles other activities (device creation/destruction, property
setting, process restarting) "between" the execution of the commands in
activities.
Actions take the form of:
on  
   
   
   
...
  
Services
--------
Services are programs which init launches and (optionally) restarts when they exit.  Services take the form of:
service   [  ]*
   
   
   ...
  
Options
-------
Options are modifiers to services.  They affect how and when init runs the service.
  
Triggers
--------
Triggers are strings which can be used to match certain kinds of events and used to cause an action to occur.
  
The
builtin supported commands are defined in
device/system/init/keywords.h. Commands are implementd in
device/system/init/bultins.c.
  
The
init program only executes five kinds of triggers: “early-init”,
“init”, “early-boot”, “boot”, “property:*”. Take a look at the
following line in default init.rc.
class_start default
This
line is a command for the action corresponding to “boot” trigger. It
will start all services whose class name equals to “default”. By
default, if no class option is defined for a service, the service’s
class name is “default”. So this line will start all the services in
the order of position in the file by default. (BTW, you can start any
service using start commands, if you like.) Any service is run as a
forked process of init, take a look at the source code of service_start
in device/system/init.c.
  
So according to the default init.rc, the following services will be executed step by step:
console: star a shell. The source is in device/system/bin/ash.
adbd: start adb daemon. The source is in device/tools/adbd. By default is disabled.
servicemanager: start binder system. The source is in device/commands/binder.
mountd:
mount all fs defined in /system/etc/mountd.conf if started, receive
commands through local socket to mount any fs. The source is in
device/system/bin/mountd.
debuggerd: start debug system. The source is in device/system/bin/debuggerd.
rild: start radio interface layer daemon. The source is in device/commands/rind.
zygote: start Android Java Runtime and start system server. It’s the most important service. The source is in device/servers/app.
media: start AudioFlinger, MediaPlayerService and CameraService. The source is in device/commands/mediaserver.
bootsound: play the default boot sound /system/media/audio/ui/boot.mp3. The source is in device/commands/playmp3.
dbus: start dbus daemon, it’s only used by BlueZ. The source is in device/system/Bluetooth/dbus-daemon.
hcid:
redirect hcid’s stdout and stderr to the Android logging system. The
source is in device/system/bin/logwrapper. By default is disabled.
hfag:
start Bluetooth handsfree audio gateway, it’s only used by BlueZ. The
source is in device/system/Bluetooth/bluez-utils. By default is
disabled.
hsag:
start Bluetooth headset audio gateway, it’s only used by BlueZ. The
source is in device/system/Bluetooth/bluez-utils. By default is
disabled.
installd: start install package daemon. The source is in device/servers/installd.
flash_recovery: load /system/recovery.img. The source is in device/commands/recovery/mtdutils.
  
Zygote service does the following tasks step by step:
1.       Create JAVA VM.
2.       Register android native function for JAVA VM.
3.       Call
the main function in the JAVA class named
com.android.internal.os.ZygoteInit whose source is
device/java/android/com/android/internal/os/ZygoteInit.java.
a)         Load ZygoteInit class
b)        Register zygote socket
c)        Load preload classes(the default file is device/java/android/preloaded-classes)
d)        Load preload resources
e)         Call
Zygote::forkSystemServer (implemented in
device/dalvik/vm/InternalNative.c) to fork a new process. In the new
process, call the main function in the JAVA class named
com.android.server.SystemServer, whose source is in
device/java/services/com/android/server.
                         i.              Load libandroid_servers.so
                       ii.              Call
JNI native init1 function implemented in
device/libs/android_servers/com_android_server_SystemServers. It only
calls system_init implemented in
device/servers/system/library/system_init.cpp.
l         If running on simulator, instantiate AudioFlinger, MediaPlayerService and CameraService here.
l         Call
init2 function in JAVA class named com.android.server.SystemServer,
whose source is in device/java/services/com/android/server. This
function is very critical for Android because it start all of Android
JAVA services.
l         If not running on simulator, call IPCThreadState::self()->joinThreadPool() to enter into service dispatcher.
  
SystemServer::init2 will start a new thread to start all JAVA services as follows:
Core Services:
1.       Starting Power Manager
2.       Creating Activity Manager
3.       Starting Telephony Registry
4.       Starting Package Manager
5.       Set Activity Manager Service as System Process
6.       Starting Context Manager
7.       Starting System Context Providers
8.       Starting Battery Service
9.       Starting Alarm Manager
10.   Starting Sensor Service
11.   Starting Window Manager
12.   Starting Bluetooth Service
13.   Starting Mount Service
Other services
1.       Starting Status Bar Service
2.       Starting Hardware Service
3.       Starting NetStat Service
4.       Starting Connectivity Service
5.       Starting Notification Manager
6.       Starting DeviceStorageMonitor Service
7.       Starting Location Manager
8.       Starting Search Service
9.       Starting Clipboard Service
10.   Starting Checkin Service
11.   Starting Wallpaper Service
12.   Starting Audio Service
13.   Starting HeadsetObserver
14.   Starting AdbSettingsObserver
Finally
SystemServer::init2 will call ActivityManagerService.systemReady to
launch the first activity by senting Intent.CATEGORY_HOME intent.
  
There
is another way to start system server, which is through a program named
system_server whose source is device/servers/system/system_main.cpp. It
also calls system_init to start system services. So there is a
question: why does Android have two methods to start system services?
My guess is that directly start system_server may have synchronous
problem with zygote because system_server will call JNI to start
SystemServer::init2, while at that time zygote may not start JAVA VM
yet. So Android uses another method. After zynote is initialized, fork
a new process to start system services.
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/93670/showart_2083902.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP