Android的启动过程

Passion注:本篇文章描述的是Android的启动过程,不包括Linux的启动过程

分别来自

http://dingpwen.spaces.live.com/blog/cns!4CADD02D22459860!208.entry?fl=cat

http://www.eepw.com.cn/article/89567.htm

http://blog.csdn.net/guiterb/archive/2009/04/03/4047369.aspx

#####################################################

1. Boot 系统初始化, 具体过程参见 (system/core/init/Init.c) 中的 main 函数,这时候,手机或者模拟器出现的画面是一个 console ,显示 “ANDROID”msg

 

2. 初始化成功后,就开始 mounting 系统,具体参见 (system/core/mountd/Mountd.c)  中的 main 函数。

 

3 .接下来运行 ndroidRuntime ,并开始启动 java 虚拟机 dalvikvm

 

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++ 代码为

(frameworks/base/cmds/system_server/library/ System_init.cpp)   中的 system_init ()函数。

 

5. system_init 调用 SurfaceFlinger SurfaceFlinger readyToRun() 函数用 BootAnimation 来实现开机动画,这时候手机或者模拟器显示是一副背景图加一个动态的小机器人。

 

6. 系统初始化的第二步,将启动 ServerThread 进程,参见 SystemServer.init2() ServerThread 将启动各种系统服务,如 Power Manager Activity Manager 等等,具体参见 ServerThread run 函数, ServerThread 同在 SystemServer.java 中。

 

7. 这之后的事,应该就是进入系统了。(这部分没有调查过)。


#####################################################

对于关注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 < list

  当前目录下生成的lk.img就是我们的新镜像了。使用自己的镜像启动emulator;

  emulator -console -ramdisk lk.img

  如果我们注释的是zygote,那么在#后输入

  app_process -Xzygote /system/bin –zygote

  手工启动,命令行中输出的信息是

  Prepping: /system/app/AlarmProvider.apk:/system/app/Browser.apk:/system/app/
Calendar.apk:/system/app/Camera.apk:/system/app/Contacts.apk:

  /system/app/Development.apk:/system/app/GDataFeedsProvider.apk:/system/app/
Gmail.apk:/system/app/GmailProvider.apk:/system/app/GoogleApps.apk:

  /system/app/GoogleAppsProvider.apk:/system/app/Home.apk:/system/app/ImProvider.apk:
/system/app/Maps.apk:/system/app/MediaPickerActivity.apk:

  /system/app/MediaProvider.apk:/system/app/Phone.apk:/system/app/PimProvider.apk:/system/
app/ApiDemos.apk:/system/app/SettingsProvider.apk:

  /system/app/Sms.apk:/system/app/SyncProvider.apk:/system/app/TelephonyProvider.apk:
/system/app/XmppService.apk:/system/app/YouTube.apk

  File not found: /system/app/AlarmProvider.apk

  File not found: /system/app/Calendar.apk

  File not found: /system/app/Camera.apk

  File not found: /system/app/GDataFeedsProvider.apk

  File not found: /system/app/Gmail.apk

  File not found: /system/app/GmailProvider.apk

  File not found: /system/app/MediaPickerActivity.apk

  File not found: /system/app/PimProvider.apk

  File not found: /system/app/ApiDemos.apk

  File not found: /system/app/Sms.apk

  File not found: /system/app/SyncProvider.apk

  File not found: /system/app/YouTube.apk

  Prep complete

  嘿嘿,从File not found的信息中可以看到一些Google可能会即将推出的应用,比如Gmail什么的。当然,这些都是Java框架的启动信息,我们以后还要借助其他工具来进行进一步探索。

  如果我们注释的是runtime,那么输出信息是:

  +++ post-zygote

  老实说,没有明白这是啥意思,呵呵,吃饭时间到了,懒得看了。

  好了,今天就说到这,基本的方法就是这样,有兴趣的朋友可以进一步深入研究。我们下一篇文章见。

 

#####################################################

[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 <trigger>

   <command>

   <command>

   <command>

...

 

Services

--------

Services are programs which init launches and (optionally) restarts when they exit.  Services take the form of:

service <name> <pathname> [ <argument> ]*

   <option>

   <option>

   ...

 

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.

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/243167.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算节点宕机了怎么办?- 每天5分钟玩转 OpenStack(43)

Rebuild 可以恢复损坏的 instance。 那如果是宿主机坏了怎么办呢&#xff1f; 比如硬件故障或者断电造成整台计算节点无法工作&#xff0c;该节点上运行的 instance 如何恢复呢&#xff1f; 用 Shelve 或者 Migrate 可不可以&#xff1f; 很不幸&#xff0c;这两个操作都要求 i…

Eclipse最新版 Neon已发布

今天&#xff0c;Eclipse基金会宣布发布Eclipse Neon&#xff0c;这个版本的IDE支持Java、JavaScript、C/C、PHP和Fortran等多种编程语言。这一次的发布集成了779个开发者&#xff08;其中有331人提交了代码&#xff09;的工作成果&#xff0c;包含了6900万行代码&#xff0c;是…

eclipse 全屏插件

eclipse-fullscreen 插件下载链接&#xff1a; http://code.google.com/p/eclipse-fullscreen/&#xff0c; 安装方式&#xff1a;将下载下来的压缩文件解压&#xff0c;将里边的jar包放到eclipse目录下的plugin文件夹中&#xff0c;重启eclipse即可。 在Fedora & Windows …

使用子模块实现三输入数的大小比较

使用子模块实现三输入数的大小比较 题目描述 在数字芯片设计中&#xff0c;通常把完成特定功能且相对独立的代码编写成子模块。在需要的时候再在主模块中例化使用&#xff0c;以提高代码的可复用性和设计的层次性&#xff0c;方便后续的修改。 请编写一个子模块&#xff0c;将…

Android中Log信息的输出方法

共两篇文章&#xff0c;第一篇讲述了如何在程序中输出Log信息&#xff0c;第二篇详细的分析了Log信息的输出机制。 下面是第一篇&#xff08;转自&#xff1a;http://blog.163.com/binghaitao126/blog/static/3383532520099309366435/&#xff09; 1&#xff1a;在编译so文件的…

寻求神谕的词语:谈海日寒诗集《空山集》

诗人杨炼曾用两个“他者”概括了当代中国诗歌所面对的两个检验体系&#xff1a;“背后是中文古典诗歌杰作”&#xff0c;“面前是古今世界文学精品”1。他提出&#xff1a;“全球化语境中&#xff0c;我们能否找到——创造一种更深也更新的标准来判断作品&#xff1f;去建立那个…

批量给Linux服务器推送文件、执行指令的工具推荐 - wgcloud-bach-agent

wgcloud-bach-agent是wgcloud官方开发的一个工具&#xff0c;具有批量给Linux主机上传文件&#xff0c;执行指令的功能 当我们有一个文件&#xff0c;需要上传到很多主机&#xff0c;或需要在很多主机执行同一条指令的时候&#xff0c;这个工具就非常实用了&#xff0c;可以极…

verilog中assign语句

/************************************** * Module: assign * Date:2014-08-10 * Author: hemmingway163.com * * Description: verilog中的assign语句的用法 ***************************************//* 一、引入语法的概念1、只有寄存器类型的信号才可以在always和initi…

Neutron Router 工作原理 - 每天5分钟玩转 OpenStack(142)

上一节我们创建了 router 连通了 vlan100 和 vlan101&#xff0c; 今天分析router是如何工作的。 首先查看控制节点的网络结构发生了什么变化&#xff1a; br-int 上多了两个 port: 1. qr-d295b258-45&#xff0c;从命名上可以推断该 interface 对应 router_100_101 的 interf…

android linux kernel VS standard linux kernel

在kernel子目录下存放的就是Android的Linux Kernel了, 通过和标准的Linux 2.6.25 Kernel的对比,我们可以发现,其主要增加了以下的内容: 1. 基于ARM架构增加Gold-Fish平台,相应增加的目录如下: kernel/arch/arm/mach-goldfish kernel/include/asm-arm/arch-go…

访问 Neutron 外部网络 - 每天5分钟玩转 OpenStack(143)

前面我们学习了位于不同 Neutron subnet 的 instance 可以通过 router 通信&#xff0c;今天开始讨论 instance 如何访问外部网络。 这里的外部网络是指的租户网络以外的网络。租户网络是由 Neutron 创建和维护的网络。 外部网络不由 Neutron 创建。如果是私有云&#xff0c;外…

使用函数实现数据大小端转换

使用函数实现数据大小端转换 题目描述 在数字芯片设计中&#xff0c;经常把实现特定功能的模块编写成函数&#xff0c;在需要的时候再在主模块中调用&#xff0c;以提高代码的复用性和提高设计的层次&#xff0c;分别后续的修改。 请用函数实现一个4bit数据大小端转换的功能。…

ISE报错问题集锦(转载)

1、XST - "ERROR:Xst:902 - .v, line xx: Unexpected event in always block sensitivity list." 解决方法&#xff1a;Resolution 1 XST does not currently support logical operators in the sensitivity list. Because these logical operators are not evaluate…

创建 OVS 外部网络 ext_net - 每天5分钟玩转 OpenStack(144)

上一节完成连接外网的配置准备工作&#xff0c;今天就来创建 OVS 外部网络 ext_net。 进入 Admin -> Networks 菜单&#xff0c;点击 “Create Network” 按钮。 显示创建页面。 Provider Network Type 选择 “Flat”。 Network 填写 “external”&#xff0c;与 ml2_conf.…

Linux学习之zImage内核镜像解压过程详解

zImage内核镜像解压过程详解 收藏 zImage内核镜像解压过程详解 作者&#xff1a; 刘洪涛&#xff0c;华清远见嵌入式培训中心 讲师。 本文以linux-2.6.14内核在S3C2410平台上运行为例&#xff0c;讲解内核的解压过程。 内核编译完成后会生成zImage内核镜像文件。关于…

4位数值比较器电路

4位数值比较器电路 题目描述&#xff1a;使用门级描述方式&#xff0c;实现4位数值比较器 某4位数值比较器的功能如下表 timescale 1ns/1nsmodule comparator_4(input [3:0] A ,input [3:0] B ,output wire Y2 , //A>Boutput wire Y1 …

将 ext_net 连接到 router - 每天5分钟玩转 OpenStack(145)

上一节完我们创建了外部网络 ext_net&#xff0c;接下来需要将其连接到 Neutron 的虚拟路由器&#xff0c;这样 instance 才能访问外网。 点击菜单 Project -> Network -> Routers 进入 router 列表。 点击 router_100_101 的 “Set Gateway” 按钮。 在 “External Netw…

Xilinx_ISE和ModelSim的联合使用方法 / 从Xilinx ISE 14.7启动ModelSim时遇到的问题

解决方法&#xff1a; 前提是安装了 xilinx ise14.7 和modelsim se 10.1a 1〉从Windows的Start Menu开始&#xff0c;Xilinx ISE Design Suite 14.7 —〉EDK —〉Tools —〉Compile Simulation Libraries 按照提示编译好library&#xff0c;编译的library输出目录是&#xff…

ML2 配置 OVS VxLAN - 每天5分钟玩转 OpenStack(146)

今天我们开始学习 OVS 如何实现 Neutron VxLAN&#xff0c;关于 VxLAN 的概念以及 Linux Bridge 实现&#xff0c;大家可以参考前面相关章节。 Open vSwitch 支持 VXLAN 和 GRE 这两种 overlay network。因为 OpenStack 对于 VXLAN 与 GRE 配置和实现差别不大&#xff0c;这里只…

4bit超前进位加法器电路

4bit超前进位加法器电路 题目描述 采用门级描述方式&#xff0c;实现此4bit超前进位加法器&#xff0c;接口电路如下&#xff1a; timescale 1ns/1nsmodule lca_4(input [3:0] A_in ,input [3:0] B_in ,input C_1 ,output wire CO …