Android OS Startup
OS puts emphases on how to provide interfaces to user's APPs
for using hardware device
in the convenient and efficient way.
Everything has its own logic of running and must be done step by step,no shortcut.
Take a look at Android OS Framework
Now, how to make the above OS run and every component of OS work to provide the service for user APP. Take a look at the process of startup as following picture
Step1: Startup from power on, Linux start up
- System boot:bootloader @bootable/bootloader/*
- Comera+Power--->fastboot,
- Home+Power--->load recovery.img
- Power--->load boot.img
- bootloader loads linux kernel
- linux kernel initialize: @kernel/*
Step2: Android startup
- kernel loads init-process: @ system/core/init/*
- read config file: @system/rootdir/init.rc to start android service and start other commands and service(adbd for adb service, vold for SD mount)
- Start native service, and other services such as ServiceManager,Zygote,media service.
- Init read init process to start ril-daemon, media, bootsound, bootanim, servicemanager......
init:@System/Core/Init
Init.c: parse_config_file(Init.rc) @parse_config_file(Init.marvel.rc)
解析脚本文件:Init.rc和Init.xxxx.rc(硬件平台相关)
Init.rc是Android自己规定的初始化脚本(Android Init Language, System/Core/Init/readme.txt)
该脚本包含四个类型的声明: Actions, Commands, Services, Options.
1.2 服务启动机制,我们来看看Init是这样解析.rc文件开启服务的。
()打开.rc文件,解析文件内容 @system/core/init/init.c
将service信息放置到service_list中。@system/core/init/parser.c
()restart_service() @system/core/init/init.c
service_start
execve(…).建立service进程。 export PATH /sbin:/system/sbin:/system/bin
export LD_LIBRARY_PATH /system/lib
mkdir /dev
mkdir /proc
mkdir /sys
mount tmpfs tmpfs /dev
mkdir /dev/pts
mkdir /dev/socket
mount devpts devpts /dev/pts
mount proc proc /proc
mount sysfs sysfs /sys
write /proc/cpu/alignment
ifup lo
hostname localhost
domainname localhost
mount yaffs2 mtd@system /system
mount yaffs2 mtd@userdata /data
import /system/etc/init.conf
class_start default
service adbd /sbin/adbd
user adb
group adb
service usbd /system/bin/usbd -r
user usbd
group usbd
socket usbd
service zygote /system/bin/app_process -Xzygote /system/bin --zygote
socket zygote
service runtime /system/bin/runtime
user system
group system
on device-added-/dev/compass
start akmd
on device-removed-/dev/compass
stop akmd
service akmd /sbin/akmd
disabled
user akmd
group akmd
Zygote // @system\core\rootdir\init.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
Step3: Zygote Startup
- In init.rc: service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
/**
* Main entry of app process.
*
* Starts the interpreted runtime, then starts up the application.
*
*/ #define LOG_TAG "appproc" #include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <utils/Log.h>
#include <cutils/process_name.h>
#include <cutils/memory.h>
#include <android_runtime/AndroidRuntime.h> #include <stdio.h>
#include <unistd.h> namespace android { void app_usage()
{
fprintf(stderr,
"Usage: app_process [java-options] cmd-dir start-class-name [options]\n");
} class AppRuntime : public AndroidRuntime
{
public:
AppRuntime()
: mParentDir(NULL)
, mClassName(NULL)
, mClass(NULL)
, mArgC(0)
, mArgV(NULL)
{
} #if 0
// this appears to be unused
const char* getParentDir() const
{
return mParentDir;
}
#endif const char* getClassName() const
{
return mClassName;
} virtual void onVmCreated(JNIEnv* env)
{
if (mClassName == NULL) {
return; // Zygote. Nothing to do here.
} /**
* This is a little awkward because the JNI FindClass call uses the
* class loader associated with the native method we're executing in.
* If called in onStarted (from RuntimeInit.finishInit because we're
* launching "am", for example), FindClass would see that we're calling
* from a boot class' native method, and so wouldn't look for the class
* we're trying to look up in CLASSPATH. Unfortunately it needs to,
* because the "am" classes are not boot classes.
*
* The easiest fix is to call FindClass here, early on before we start
* executing boot class Java code and thereby deny ourselves access to
* non-boot classes.
*/
char* slashClassName = toSlashClassName(mClassName);
mClass = env->FindClass(slashClassName);
if (mClass == NULL) {
LOGE("ERROR: could not find class '%s'\n", mClassName);
}
free(slashClassName); mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass));
} virtual void onStarted()
{
sp<ProcessState> proc = ProcessState::self();
LOGV("App process: starting thread pool.\n");
proc->startThreadPool(); AndroidRuntime* ar = AndroidRuntime::getRuntime();
ar->callMain(mClassName, mClass, mArgC, mArgV); IPCThreadState::self()->stopProcess();
} virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
LOGV("App process: starting thread pool.\n");
proc->startThreadPool();
} virtual void onExit(int code)
{
if (mClassName == NULL) {
// if zygote
IPCThreadState::self()->stopProcess();
} AndroidRuntime::onExit(code);
} const char* mParentDir;
const char* mClassName;
jclass mClass;
int mArgC;
const char* const* mArgV;
}; } using namespace android; /**
* sets argv0 to as much of newArgv0 as will fit
*/
static void setArgv0(const char *argv0, const char *newArgv0)
{
strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
} int main(int argc, const char* const argv[])
{
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv; mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--; AppRuntime runtime;
const char* argv0 = argv[0]; // Process command line arguments
// ignore argv[0]
argc--;
argv++; // Everything up to '--' or first non '-' arg goes to the vm 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;
} else if (strcmp(arg, "--zygote") == 0) {
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) {
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.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
app_main
// @system\core\rootdir\init.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
- Zygote start up from main(…) of app_process //@frameworks/base/cmds/app_main.cpp。
- Create Java Runtime: runtime.start("com.android.internal.os.ZygoteInit.java", startSystemServer); //@AndroidRuntime.cpp
- Make Zygote run:com.android.internal.os.ZygoteInit:main() //@com.android.internal.os.ZygoteInit
- registerZygoteSocket();
- startSystemServer();com.android.internal.os.ZygoteInit:startSystemServer() //@com.android.internal.os.ZygoteInit.
- Now the Zygote service framework is built, and accept the requet from ActivityManagerService via Socket to fork APP.
- Zygote.forkSystemServer(@dalvik.system.Zygote.java) is mapped to the process of linux with pid.
public static void main(String argv[])
{
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,SystemClock.uptimeMillis());
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")) {
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 {
runSelectLoopMode();
}
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
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",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid; try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
}
catch (IllegalArgumentException ex)
{
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
handleSystemServerProcess(parsedArgs);
}
return true;
}
//@dalvik.system.Zygote.java
public static int forkSystemServer(int uid, int gid, int[] gids,int debugFlags, int[][] rlimits,long permittedCapabilities, long effectiveCapabilities)
{
preFork();
//call native method to fork a process of system server which is mappged to linux process
int pid = nativeForkSystemServer(uid, gid, gids, debugFlags, rlimits,
permittedCapabilities,
effectiveCapabilities);
postFork();
return pid;
}
Step3:SystemServer Startup
- Zygote fork a process of SystemServer: forkSystemServer() //@dalvik.system.Zygote.java
- Zygote.nativeForkSystemServer() //@dalvik/vm/native/dalvik_system_Zygote.c
- SystemServer is created and running.
- com.android.server.SystemServer:init1(): The native method start all system native service.
- com.android.server.SystemServer:init2(): Create a ServerThread to add just created native service by init1() to service list and finally loop.
com.android.server.SystemServer:main()//@com.android.server.SystemServer.java
public static void main(String[] args)
{
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
// If a device's clock is before 1970 (before 0), a lot of
// APIs crash dealing with negative numbers, notably
// java.io.File#setLastModified, so instead we fake it and
// hope that time from cell towers or NTP fixes it
// shortly.
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
if (SamplingProfilerIntegration.isEnabled()) {
SamplingProfilerIntegration.start();
timer = new Timer();
timer.schedule(new TimerTask()
{
@Override
public void run() {
SamplingProfilerIntegration.writeSnapshot("system_server", null);
}
}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
}
// Mmmmmm... more memory!
dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
// The system server has to run all of the time, so it needs to be
// as efficient as possible with its memory usage.
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
System.loadLibrary("android_servers");//load android_servers.so
init1(args);
}
/***
* This method is called from Zygote to initialize the system. This will cause the native
* services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back
* up into init2() to start the Android services.
*/
native public static void init1(String[] args); public static final void init2() {
Slog.i(TAG, "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
//@com.android.server.SystemService
class ServerThread extends Thread
{
......
@Override
public void run()
{
...............................
Looper.prepare();
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);
BinderInternal.disableBackgroundScheduling(true);
android.os.Process.setCanSelfBackground(false);
// Check whether we failed to shut down last time we tried.
{
....................
}
String factoryTestStr = SystemProperties.get("ro.factorytest");
int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF
: Integer.parseInt(factoryTestStr);
.......//declare all native service object.
// Critical services...add all service into list of service manager
try {
Slog.i(TAG, "Entropy Service");
ServiceManager.addService("entropy", new EntropyService());
power = new PowerManagerService();
ServiceManager.addService(Context.POWER_SERVICE, power);
context = ActivityManagerService.main(factoryTest);
ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));
AttributeCache.init(context);
........................
alarm = new AlarmManagerService(context);
ServiceManager.addService(Context.ALARM_SERVICE, alarm);
Watchdog.getInstance().init(context, battery, power, alarm,ActivityManagerService.self());
Slog.i(TAG, "Window Manager");
wm = WindowManagerService.main(context, power,factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,!firstBoot);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ActivityManagerService.self().setWindowManager(wm);
....................... } catch (RuntimeException e) {
}
.............................
// Bring up services needed for UI.
if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL)
{
try {
Slog.i(TAG, "Input Method Service");
imm = new InputMethodManagerService(context);
ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm);
} catch (Throwable e) {
reportWtf("starting Input Manager Service", e);
}
.......................
} try {
wm.displayReady();
} catch (Throwable e) {
reportWtf("making display ready", e);
} try {
pm.performBootDexOpt();
} catch (Throwable e) {
reportWtf("performing boot dexopt", e);
} try {
ActivityManagerNative.getDefault().showBootMessage(context.getResources().getText(
com.android.internal.R.string.android_upgrading_starting_apps),
false);
} catch (RemoteException e) {
}
if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
try {
Slog.i(TAG, "Device Policy");
devicePolicy = new DevicePolicyManagerService(context);
ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy);
} catch (Throwable e) {
reportWtf("starting DevicePolicyService", e);
}
....................
try {
Slog.i(TAG, "Wi-Fi Service");
wifi = new WifiService(context);
ServiceManager.addService(Context.WIFI_SERVICE, wifi);
} catch (Throwable e) {
reportWtf("starting Wi-Fi Service", e);
}
....................
try {
Slog.i(TAG, "NetworkTimeUpdateService");
networkTimeUpdater = new NetworkTimeUpdateService(context);
} catch (Throwable e) {
reportWtf("starting NetworkTimeUpdate service", e);
}
}
// Before things start rolling, be sure we have decided whether
// we are in safe mode.
final boolean safeMode = wm.detectSafeMode();
if (safeMode) {
ActivityManagerService.self().enterSafeMode();
// Post the safe mode state in the Zygote class
Zygote.systemInSafeMode = true;
// Disable the JIT for the system_server process
VMRuntime.getRuntime().disableJitCompilation();
} else {
// Enable the JIT for the system_server process
VMRuntime.getRuntime().startJitCompilation();
}
// It is now time to start up the app processes...
if (devicePolicy != null) {
try {
devicePolicy.systemReady();
} catch (Throwable e) {
reportWtf("making Device Policy Service ready", e);
}
}
if (notification != null) {
try {
notification.systemReady();
} catch (Throwable e) {
reportWtf("making Notification Service ready", e);
}
}
try {
wm.systemReady();
} catch (Throwable e) {
reportWtf("making Window Manager Service ready", e);
}
if (safeMode) {
ActivityManagerService.self().showSafeModeOverlay();
}
// Update the configuration for this context by hand, because we're going
// to start using it before the config change done in wm.systemReady() will
// propagate to it.
..................................
power.systemReady();
try {
pm.systemReady();
} catch (Throwable e) {
reportWtf("making Package Manager Service ready", e);
} // These are needed to propagate to the runnable below.
final Context contextF = context;
final BatteryService batteryF = battery;
.........................
// We now tell the activity manager it is okay to run third party
// code. It will call back into us once it has gotten to the state
// where third party code can really run (but before it has actually
// started launching the initial applications), for us to complete our
// initialization.
ActivityManagerService.self().systemReady(new Runnable() {
public void run() {
Slog.i(TAG, "Making services ready");
startSystemUi(contextF);
try {
if (batteryF != null) batteryF.systemReady();
} catch (Throwable e) {
reportWtf("making Battery Service ready", e);
}
.....................
try {
if (textServiceManagerServiceF != null) textServiceManagerServiceF.systemReady();
} catch (Throwable e) {
reportWtf("making Text Services Manager Service ready", e);
}
}
}); // For debug builds, log event loop stalls to dropbox for analysis.
if (StrictMode.conditionallyEnableDebugLogging()) {
Slog.i(TAG, "Enabled StrictMode for system server main thread.");
}
Looper.loop();
Slog.d(TAG, "System ServerThread is exiting!");
}
static final void startSystemUi(Context context) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
Slog.d(TAG, "Starting service: " + intent);
context.startService(intent);
}
}
Step4:Home luncher Startup
http://blog.csdn.net/maxleng/article/details/5508372
http://wenku.baidu.com/view/fc7729375a8102d276a22f13.html
http://wenku.baidu.com/view/42ebf459be23482fb4da4c33.html
http://www.cnblogs.com/linucos/archive/2012/05/22/2513760.html
Android's Process & Thread
Android OS Startup的更多相关文章
- android.os.NetworkOnMainThreadException异常
在android4.0以前,访问网络的代码可以写在UI主线程,但是在android4.0以上就不能在ui主线程中访问网络了,会出现android.os.NetworkOnMainThreadExcep ...
- Xamarin Android.Views.WindowManagerBadTokenException: Unable to add window -- token android.os.BinderProxy
Android.Views.WindowManagerBadTokenException: Unable to add window -- token android.os.BinderProxy@ ...
- Android.os.NetworkOnMainThreadException
出现Android.os.NetworkOnMainThreadException错误提示的原因原因:不允许在主线程中进行网络访问解决办法:将网络访问的操作单独放到一个线程中
- android aidl 进程间通信需要注意的地方(android.os.TransactionTooLargeException)
转自:http://blog.sina.com.cn/s/blog_4e1e357d0102wau9.html 1.bus工程实现通过service实现aidl实体类 2.actor工程通过发起bin ...
- android-解决 Android N 上 报错:android.os.FileUriExposedException
解决 Android N 上 安装Apk时报错:android.os.FileUriExposedException: file:///storage/emulated/0/Download/appN ...
- Android内核开发:系统启动速度优化-Android OS启动优化(转)
Android系统的启动优化主要分为三大部分: (1) Bootloader优化 (2) Linux Kernel的剪裁与优化 (3) Android OS部分的剪裁与优化 本文重点关注Android ...
- android.os.BadParcelableException: ClassNotFoundException when unmarshalling:解决办法
例如在用AlarmManager的时候 AlarmManager alarmMgr = (AlarmManager) mContext .getSystemService(Context.ALARM_ ...
- 主线程中一定不能放耗时操作,必须要开子线程,比如下载文件,不然会不让你拿到输入流--报错显示android.os.NetworkOnMainThreadException
1.必须要开子线程来操作耗时操作,android.os.NetworkOnMainThreadException new Thread(new Runnable() { @Override publi ...
- android.os.NetworkOnMainThreadException解决
很早就知道Android4.0以后,要把耗时的网络操作放在多线程中,处理方法有: 1) setContentView(R.layout.activity_main)下面加上如下代码 if (andro ...
随机推荐
- web flash推流录制测试研究
用flash as3写了一段推流测试demo,参考srs_publisher和simplest_as3_rtmp_streamer.推流到srs2服务器,录制为flv文件.测试一轮结果如下: Web ...
- php 多维数组按键值分类
背景:现在有一个多维数组,该数组里面的部分一维数组key值是完全一样的,现将一样的数组提取出来,用于做列表展示. 封装方法: function arrClassify($arr){ $data = a ...
- [ZJOI2009]假期的宿舍 BZOJ 1433 二分图匹配
题目描述 学校放假了 · · · · · · 有些同学回家了,而有些同学则有以前的好朋友来探访,那么住宿就是一个问题.比如 A 和 B 都是学校的学生,A 要回家,而 C 来看B,C 与 A 不认识. ...
- kuangbin专题十二 HDU1176 免费馅饼 (dp)
免费馅饼 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- 04->python字典
字典dict 1.数据类型分类(按可变和不可变) 不可变数据类型:数字.bool.str.tuple 可变数据类型:list.dict.set 2.dict的组成 key:va ...
- 图像标注工具labelImg安装记录
这里仅记载下labelImg的安装过程,因为有坑. 我的安装方式是从源码编译,环境ubuntu16.04,一开始是使用python2安装,从github上下载好源码,然后执行安装命令 sudo apt ...
- matplotlib学习笔记(四)
利用matplotlib可以显示图像 imread()和imshow()提供了简单的图像载入和显示功能. img = plt.imread("xxx.jpg") imread()可 ...
- DropDownList年份的添加
http://blog.sina.com.cn/s/blog_4b9e030e01007sc3.html
- day25 网络编程之socket sc架构
1. 为什么要学习socket? socket就是网络通信的工具,任何一门语言都有socket,他不是任何一个语言的专有名词,而是大家通过自己的程序与其他电脑进行网络通信的时候都用它. 2. 客户 ...
- uva 442
#include<iostream>#include<stack>#include<map>using namespace std;struct node{ int ...