編輯:關於Android編程
看了很多相關博客,今天也來自己梳理以下~~~
Android從Linux系統啟動
init進程啟動
Native服務啟動
System Server, Android 服務啟動
Home啟動
總體啟動框架:
Init進程啟動<喎?/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPjwvcD4NCjxibG9ja3F1b3RlPg0KCTxwPsrXz8h1Ym9vdNL9tbxMaW51eMTausvG9Lavo6zIu7rz1NrTw7unv9W85NbQxvS2r2luaXS9+LPMo6zU2cb0tq/G5Mv7z7XNs734s8yho9Taz7XNs8b0tq/N6rPJzeqzybrzo6xpbml0vaux5M6qyti7pL34s8y84MrTz7XNs8bky/u9+LPMoaM8YSBocmVmPQ=="http://lib.csdn.net/base/15">Android是基於Linux的操作系統,所以init也是Android系統中用戶空間的第一個進程,它的進程號是1。
Init的主要職責是:
作為守護進程
解析核執行init.rc文件
生成設備節點
屬性服務
源碼在/system/core/init/init.c
int main(int argc, char **argv) {
//啟動uevent守護進程
if (!strcmp(basename(argv[0]), "ueventd"))
return ueventd_main(argc, argv);
//啟動看門狗守護進程
if (!strcmp(basename(argv[0]), "watchdogd"))
return watchdogd_main(argc, argv);
umask(0);
//創建並掛在啟動所需的文件目錄
mkdir("/dev", 0755);
mkdir("/proc", 0755);
mkdir("/sys", 0755);
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
mount("proc", "/proc", "proc", 0, NULL);
mount("sysfs", "/sys", "sysfs", 0, NULL);
close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000));
//重定向標准輸入/輸出/錯誤輸出到/dev/_null_
open_devnull_stdio();
klog_init();//log初始化
property_init();//屬性服務初始化
//從/proc/cpuinfo中讀取Hardware名,在後面的mix_hwrng_into_linux_rng_action函 數中會將hardware的值設置給屬性ro.hardware
get_hardware_name(hardware, &revision);
//導入並設置內核變量
process_kernel_cmdline();
......
INFO("property init\n");
if (!is_charger)
property_load_boot_defaults();
INFO("reading config file\n");
init_parse_config_file("/init.rc");//解析init.rc配置文件
/*
* 解析完init.rc後會得到一系列的action等,下面的代碼將執行處於early-init階段的 action。
* init將action按照執行時間段的不同分為early-init、init、early-boot、boot。
* 進行這樣的劃分是由於有些動作之間具有依賴關系,某些動作只有在其他動作完成後才能執行,所以就有了先後的區別。
* 具體哪些動作屬於哪個階段是在init.rc中的配置決定的
*/
action_for_each_trigger("early-init", action_add_queue_tail);
......
for(;;) {//init進入無限循環
......
execute_one_command();
restart_processes();//重啟已經死去的進程
......
nr = poll(ufds, fd_count, timeout); //等待事件發生
if (nr <= 0)
continue;
for (i = 0; i < fd_count; i++) {
if (ufds[i].revents == POLLIN) {
if (ufds[i].fd == get_property_set_fd())//處理屬性服務事件
handle_property_set_fd();
else if (ufds[i].fd == get_keychord_fd())//處理keychord事件
handle_keychord();
else if (ufds[i].fd == get_signal_fd())
handle_signal();//處理SIGCHLD信號事件
}
}
}
return 0;
}
看看init.rc腳本
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
ps:(1)這裡描述了孵化器zygote的啟動(init是zygote的父進程,而系統服務進程system_server和其他所有的com.xxx結尾的應用程序都是從zygote fork 而來)。
(2)前面的關鍵字service告訴init進程創建一個名為”zygote”的進程,這個zygote進程要執行的程序是/system/bin/app_process,後面是要傳給app_process的參數。最後的一系列onrestart關鍵字表示這個zygote進程重啟時需要執行的命令。
了解了這個信息之後,我們就知道Zygote進程要執行的程序便是system/bin/app_process了,它的源代碼位於frameworks/base/cmds/app_process/app_main.cpp文件中,入口函數是main。
int main(int argc, char* const argv[])
{
......
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i
main函數的主要作用就是創建一個AppRuntime變量,然後調用它的start函數。它的定義也在同一文件app_main.cpp下面class AppRuntime : public AndroidRuntime
(AndroidRuntime的源碼在/frameworks/base/core/jni下,它是抽象基類);
在AndroidRuntime.h中定義了4種啟動模式
enum StartMode {
Zygote,//啟動Zygote
SystemServer,//啟動系統服務
Application,//啟動應用程序
Tool,//
};
再看看具體的start函數做了什麼
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*
* Passes the main function two arguments, the class name and the specified
* options string.
*/
//上面的解釋是開始android運行時環境。將開始虛擬機,然後用類似反射的機制去調用類名為參數className的main()方法!
void AndroidRuntime::start(const char* className, const char* options)
{
if (strcmp(options, "start-system-server") == 0) {
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
return;
}
setenv("ANDROID_ROOT", rootDir, 1);
}
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) {//開啟虛擬機
return;
}
onVmCreated(env);
/*
* Register android functions. 注冊本地native函數
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring optionsStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(2, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
optionsStr = env->NewStringUTF(options);
env->SetObjectArrayElement(strArray, 1, optionsStr);
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
//激活虛擬機,當前線程變成虛擬機下的主線程。
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
}
通過源代碼的分析知道,其實上面主要是給一個應用程序分配一個虛擬機環境(虛擬機拷貝),然後通過JNI的方式去調java裡某個className類的main()方法。
還記得runtime.start(“com.android.internal.os.ZygoteInit”, startSystemServer ? “start-system-server” : “”);
實際執行com.android.internal.os.ZygoteInit類的main()(源碼地址frameworks/base/core/java/com/android/internal/os/ZygoteInit.java):
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[1].equals("start-system-server")) {
startSystemServer();//啟動system_server進程
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
......
runSelectLoop();
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
......
}
}
它主要作了三件事情:
1、調用registerZygoteSocket函數創建了一個socket接口,用來和ActivityManagerService通訊;
2、調用startSystemServer函數來啟動SystemServer組件;
3、調用runSelectLoopMode函數進入一個無限循環在前面創建的socket接口上等待ActivityManagerService請求創建新的應用程序進程。
這裡Zygote進程初始化完畢,開始大循環了~~~
仔細分析下第二步startSystemServer啟動系統服務組件
/**
* Prepare the arguments and fork for the system server process.
*/
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,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
......
/* 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) {
......
}
/* For child process */
if (pid == 0) {//pid==0說明是子進程,父進程為Zygote
handleSystemServerProcess(parsedArgs);
}
return true;
}
在startSystemServer中先設置了Zygote.forkSystemServer所需的參數,然後通過forkSystemServer方法fork出SystemServer進程,最後通過handleSystemServerProcess處理新進程中的瑣事。
首先看一下參數:
1、setuid=1000,這裡1000代表SYSTEM_UID,即系統進程,關於進程ID的說明可以參見:/frameworks/base/core/java/android/os/Process.java。
2、nice-name=system_server表示制定進程的名字為“system_server”
3、com.android.server.SystemServer表示SystemServer類的位置。
接下來看一下forkSystemServer的實現:
libcore/dalvik/src/main/java/dalvik/system/Zygote.java
/**
* Special method to start the system server process. In addition to the
* common actions performed in forkAndSpecialize, the pid of the child
* process is recorded such that the death of the child process will cause
* zygote to exit.
* 注意由zygote fork 出的system_service進程如果死了,則zygote進程也退出
*/
public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
preFork();
int pid = nativeForkSystemServer(
uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
postFork();
return pid;
}
native public static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
forkSystemServer最後調nativeForkSystemServer,而它是通過JNI實現,源碼:/dalvik/vm/native/dalvik_system_Zygote.cpp:
static void Dalvik_dalvik_system_Zygote_forkSystemServer(
const u4* args, JValue* pResult)
{
pid_t pid;
pid = forkAndSpecializeCommon(args, true);
/* The zygote process checks whether the child process has died or not. */
if (pid > 0) {//pid大於0,說明是在父進程中,Zygote進程往下執行
int status;
gDvm.systemServerPid = pid;
/* There is a slight window that the system server process has crashed
* but it went unnoticed because we haven't published its pid yet. So
* we recheck here just to make sure that all is well.
*/
if (waitpid(pid, &status, WNOHANG) == pid) {
ALOGE("System server process %d has died. Restarting Zygote!", pid);
kill(getpid(), SIGKILL);//一旦上面的等待返回,說明進程pid(system_server)已終止,此時Zygote殺死自己
}
}
RETURN_INT(pid);
}
//native函數注冊
const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {
{ "nativeFork", "()I",
Dalvik_dalvik_system_Zygote_fork },
{ "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;)I",
Dalvik_dalvik_system_Zygote_forkAndSpecialize },
{ "nativeForkSystemServer", "(II[II[[IJJ)I",
Dalvik_dalvik_system_Zygote_forkSystemServer },
{ NULL, NULL, NULL },
};
SystemServer創建之後交給handleSystemServerProcess處理!
回到 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
/**
* Finish remaining work for the newly forked system server process.
* 完成新建的system server進程的剩余工作
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket();//關閉從Zygote復制過來的socket
// set umask to 0077 so new files and directories will default to owner-only permissions.
Libcore.os.umask(S_IRWXG | S_IRWXO);//設置文件的默認權限,去除文件所有者之外的權限
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
null, parsedArgs.remainingArgs);
} else {
/*
* Pass the remaining arguments to SystemServer.傳遞剩下的參數給SystemServer
*/
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
}
/* should never reach here */
}
最後將參數往下傳給RuntimeInit.zygoteInit(,)
源碼:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
/**
* The main function called when started through the zygote process. This
* could be unified with main(), if the native code in nativeFinishInit()
* were rationalized with Zygote startup.
*/
public static final void zygoteInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
redirectLogStreams();//將System.out 和 System.err 輸出重定向到Android 的Log系統
/*
* 初始化了一些系統屬性,其中最重要的一點就是設置了一個未捕捉異常的handler,
* 當代碼有任何未知異常,就會執行它,
* 調試過Android代碼的同學經常看到的"*** FATAL EXCEPTION IN SYSTEM PROCESS" 打印就出自這裡
*/
commonInit();
/*
* 最終會調用app_main的onZygoteInit函數
* 這裡的作用是在新進程中引入Binder,也就說通過nativeZygoteInit以後,新的進程就可以使用Binder進程通信了
*/
nativeZygoteInit();
applicationInit(targetSdkVersion, argv);//應用初始化
}
private static void applicationInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
// Android runtime shutdown hooks close the Binder driver, which can cause
// leftover running threads to crash before the process actually exits.
nativeSetExitWithoutCleanup(true);
// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
try {
args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
Slog.e(TAG, ex.getMessage());
// let the process exit
return;
}
// Remaining arguments are passed to the start class's static main
invokeStaticMain(args.startClass, args.startArgs);
}
這裡invokeStaticMain的args.startClass的值為com.android.server.SystemServer。接下來SystemServer類的main函數將會被調用,我太機智了^~^。
源碼:frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
/*
* In case the runtime switched since last boot (such as when
* the old runtime was removed in an OTA), set the system
* property so that it is in sync.
*/
SystemProperties.set("persist.sys.dalvik.vm.lib",
VMRuntime.getRuntime().vmLibrary());
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {//調整時間
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
......
// 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);
Environment.setUserRequired(true);
System.loadLibrary("android_servers");
Slog.i(TAG, "Entered the Android system server!");
// Initialize native services.
nativeInit();//初始化本地所以服務 > SensorService
// This used to be its own separate thread, but now it is
// just the loop we run on the main thread.
ServerThread thr = new ServerThread();
thr.initAndLoop();
}
在main中會加載libandroid_servers.so庫,然後調用nativeInit初始化native層的Service。
ServerThread初始化一堆android服務。
小結一下:
Linux的init在啟動若干守護進程之後,就啟動了Android的runtime和zygote,Zygote進程負責後續Android應用程序框架層的其它進程的創建和啟動工作。
Zygote進程會首先創建一個SystemServer進程,SystemServer進程負責啟動系統的關鍵服務,如包管理服務PackageManagerService和應用程序組件管理服務ActivityManagerService。
當我們需要啟動一個Android應用程序時,ActivityManagerService會通過Socket進程間通信機制,通知Zygote進程為這個應用程序創建一個新的進程。
Activity在inflate layout時,通過DataBindingUtil來生成綁定,從代碼看,是遍歷contentView得到View數組對象,然後通過數據綁
244.http請求的url含有中字符時,需要Uri編碼。Uri.encoder()245.使用androidstudio時,不知道什麼原因svn不見了Android S
本文實例講述了Android中ImageView使用網絡圖片資源的方法。分享給大家供大家參考。具體如下:很多時候我們不想把東西都放在APK裡面,或者是不能放進去,這時候我
首先上效果圖,類似於360檢測到騷擾電話頁面:布局很簡單,上面是一個RelativeLayout,下面一個Button.功能:(1)彈幕生成後自動從右側往左側滾動(Tra
1.錯誤描述今天在Android4.4 的小米4手機上運行我的程序的時候