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的更多相关文章

  1. android.os.NetworkOnMainThreadException异常

    在android4.0以前,访问网络的代码可以写在UI主线程,但是在android4.0以上就不能在ui主线程中访问网络了,会出现android.os.NetworkOnMainThreadExcep ...

  2. Xamarin Android.Views.WindowManagerBadTokenException: Unable to add window -- token android.os.BinderProxy

    Android.Views.WindowManagerBadTokenException: Unable to add window -- token android.os.BinderProxy@ ...

  3. Android.os.NetworkOnMainThreadException

    出现Android.os.NetworkOnMainThreadException错误提示的原因原因:不允许在主线程中进行网络访问解决办法:将网络访问的操作单独放到一个线程中

  4. android aidl 进程间通信需要注意的地方(android.os.TransactionTooLargeException)

    转自:http://blog.sina.com.cn/s/blog_4e1e357d0102wau9.html 1.bus工程实现通过service实现aidl实体类 2.actor工程通过发起bin ...

  5. android-解决 Android N 上 报错:android.os.FileUriExposedException

    解决 Android N 上 安装Apk时报错:android.os.FileUriExposedException: file:///storage/emulated/0/Download/appN ...

  6. Android内核开发:系统启动速度优化-Android OS启动优化(转)

    Android系统的启动优化主要分为三大部分: (1) Bootloader优化 (2) Linux Kernel的剪裁与优化 (3) Android OS部分的剪裁与优化 本文重点关注Android ...

  7. android.os.BadParcelableException: ClassNotFoundException when unmarshalling:解决办法

    例如在用AlarmManager的时候 AlarmManager alarmMgr = (AlarmManager) mContext .getSystemService(Context.ALARM_ ...

  8. 主线程中一定不能放耗时操作,必须要开子线程,比如下载文件,不然会不让你拿到输入流--报错显示android.os.NetworkOnMainThreadException

    1.必须要开子线程来操作耗时操作,android.os.NetworkOnMainThreadException new Thread(new Runnable() { @Override publi ...

  9. android.os.NetworkOnMainThreadException解决

    很早就知道Android4.0以后,要把耗时的网络操作放在多线程中,处理方法有: 1) setContentView(R.layout.activity_main)下面加上如下代码 if (andro ...

随机推荐

  1. oracle小知识

    设置显示执行时间 set timing on; 不显示:off 最简单的块: begin dbms_output.put_line('Hello,World'); end; 执行结果出现这种情况(执行 ...

  2. kuangbin专题十六 KMP&&扩展KMP HDU1238 Substrings

    You are given a number of case-sensitive strings of alphabetic characters, find the largest string X ...

  3. (16)break和continue

    #(1)这里顺带说下pass # pass 过 的意思,防止代码报错,就是个占位的, if True: # 不允许代码块里面的内容为空,用pass占位 pass #(2)break (只能用在循环当中 ...

  4. main.obj:-1: error: LNK2001: 无法解析的外部符号 "public: virtual struct QMetaObject const * __thiscall CustomButton::metaObject(void)const " (?metaObject@CustomButton@@UBEPBUQMetaObject@@XZ)

    QTCreator 运行时报错 main.obj:-1: error: LNK2001: 无法解析的外部符号 "public: virtual struct QMetaObject cons ...

  5. python内存相关问题

    想要弄清楚内存相关的问题,就要理清楚:变量.内存地址.值之间的关系:1.程序里什么时候分配新的内存地址?答:1.定义一个变量,内存就开辟一个内存空间,分配一个内存地址. 特殊: 如:a=687 a=1 ...

  6. windwos-sshfs

    从 http://www.jianshu.com/p/d79901794e3d 转载 目的 最近因为需要在linux虚拟机里进行开发程序,虽然在linux里有超强的编辑器vim,但vim开发html前 ...

  7. C# repeater控件序号绑定

    做项目列表经常会需要列表有一个序号列,根据控件自身的属性就可以很方便的实现这个功能,如下图 这个不能用翻页功能,如果翻页重新刷新控件的话,序号会又重新开始!

  8. Linux系统结构及常用命令

    一.系统结构 Linux是一个倒树形结构,最大的目录名叫“/”(根目录) 根目录之下有许多的二级目录,这些目录在系统中都拥有自己不同的功能,如图: 以后的诸多命令的执行和操作都与这些目录相关,现在了解 ...

  9. Java 类型转换(int->String)

    1 如何将字串 String 转换成整数 int? A. 有两个方法: 1). int i = Integer.parseInt([String]); 或 i = Integer.parseInt([ ...

  10. 使用vlookup函数下拉全部相同解决

    菜单“公式”-“计算选项”改为自动 ref: https://zhidao.baidu.com/question/561971299094821004.html