Android7.0 系統啟動流程---system_server


今天主要分析Android啟動流程,重點是system_server相關知識。

一、Android系統啟動流程

Android正常啟動流程如下:
Step1 系統加電,執行bootloader。Bootloader負責初始化軟件運行所需要的最小硬件環境,最后加載內核到內存。
Step2 內核加載進內存后,將首先進入內核引導階段,在內核引導階段的最后,調用start_kenel進入內核啟動階段。start_kenel最終啟動用戶空間的init程序。
Step3 init程序負責解析init.rc配置文件,開啟系統守護進程。兩個最重要的守護進程是zygote進程和ServiceManager,zygote是Android啟動的第一個Dalvik虛擬機,ServiceManager是Binder通訊的基礎。
Step4 zygote虛擬機啟動子進程system_server,在system_server中開啟了核心系統服務,並將系統服務添加到ServiceManager中,然后系統進入SystemReady狀態。
Step5 在SystemReady狀態,ActivityManagerService與zygote中的socket通信,通過zygote啟動home應用,進入系統桌面。

從Step3開始,init啟動后,上層的實現。
Step1 init啟動的核心Daemon服務包括Android的第一個Dalvik虛擬機zygote。
Step2 zygote定義一個socket,用於接受ActivityManagerService啟動應用的請求。
Step3 zygote通過fork系統調用創建system_server進程
Step4 在system_server進程中,將會啟動系統核心服務以及其他服務。
Step5 系統服務啟動后會注冊到ServiceManager中,用於Binder通信。
Step6 ActivityManagerService進入systemReady狀態。
Step7 在systemReady狀態,ActivityManagerService會與zygote的Socket通信,請求啟動Home。
Step8 zygote收到AMS的連接請求后,執行runSelectLoopMode處理請求。
Step9 zygote處理請求會通過forkAndSpecialize啟動新的應用進程,並最終啟動Home。

二、system_server啟動過程

在Step3,系統會創建system_server,下面開始分析system_server創建過程。
系統在預加載了共享資源后,編開始啟動system_server進程,system_server是理解framework層的基礎。Android中所有的系統服務都由它啟動,它的異常會導致zygote的自殺重啟,這樣整個java就崩潰了。
System_server的啟動入口是startSystemServer方法,位於frameworks/base/core/java/com/android/internal/os/ZygoteInit.java。
在ZygoteInit的main函數,調用了方法startSystemServer。

  public static void main(String argv[]) {
...
String socketName = "zygote";
...
try {
...
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
....

分析startSystemServer方法:

 /**
* Prepare the arguments and fork for the system server process.
*/

private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_IPC_LOCK,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
OsConstants.CAP_NET_BROADCAST,
OsConstants.CAP_NET_RAW,
OsConstants.CAP_SYS_MODULE,
OsConstants.CAP_SYS_NICE,
OsConstants.CAP_SYS_RESOURCE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG
);
/* Containers run without this capability, so avoid setting it in that case */
if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
}
/* Hardcoded command line to start the system server */
/* 設置啟動system_server的命令行參數 */
String args[] = {
"--setuid=1000", //設置用戶的ID為1000,這個UID代表系統權限
"--setgid=1000",
/// M: ANR mechanism for system_server add shell(2000) group to access
/// /sys/kernel/debug/tracing/tracing_on
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,2000," +
"3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server", //設置進程名
"--runtime-args",
"com.android.server.SystemServer", //設置要啟動的類名
};
ZygoteConnection.Arguments parsedArgs = null;

int pid;

try {
//將數組分解成Arguments類型的對象,過程很簡單
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

/* Request to fork the system server process */
//調用系統fork函數創建子進程,這個子進程就是sysytem_server
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 */
//pid為0說明在子進程system_server中
if (pid == 0) {

if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
//在子進程system_server中調用了handleSystemServerProcess方法
handleSystemServerProcess(parsedArgs);
}
//在父進程中返回
return true;
}

到這里,zygote做了第一次分裂,forck出系統服務的總管system_server進程,這個過程分為以下兩個重要的步驟:
1)、通過forkSystemServer創建system_server子進程。
2)、在子進程中調用handleSystemServerProcess方法。

2.1 通過forkSystemServer創建system_server子進程
啟動system_server的第一步便是調用zygote的system_server方法,在該方法內部將調用Native方法nativeForkSystemServer,來完成啟動system_server進程的任務。nativeForkSystemServer的JNI層實現方法位於frameworks/base/core/jni/com_android_internal_os_Zygote.cpp中,方法名為com_android_internal_os_Zygote_nativeForkSystemServer()。

static jint com_android_internal_os_Zygote_nativeForkSystemServer(
JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
jlong effectiveCapabilities) {
//間接調用了ForkAndSpecializeCommom() 函數
pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
debug_flags, rlimits,
permittedCapabilities, effectiveCapabilities,
MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
NULL, NULL);
if (pid > 0) {//pid>0,則是在system_server的父進程zygote中
// The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid);
gSystemServerPid = pid;//在虛擬機中記錄system_server的進程ID
// 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.
int status;
//退出前,重新檢查sysem_server進程是否有異常,如果異常退出,
//則zygote直接自殺,因為在zygote的服務項中配置了onrestart這個*option,
//所以zogote自殺后,init進程會重新啟動它
if (waitpid(pid, &status, WNOHANG) == pid) {
ALOGE("System server process %d has died. Restarting Zygote!", pid);
RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
}
}
return pid;
}

在這里,系統會檢查system_server進程是否啟動成功,如果啟動失敗,將導致zygote重啟。system_server負責構建系統服務,如果啟動失敗,Android系統也就無法啟動,所以必須重啟zygote、因此Dalvik_dalvik_system_Zygote_forkSystemServer方法的功能分成兩部分:
1)啟動system_server進程。
2)監控system_server進程的啟動結果。

2.1.1 啟動system_server進程
這部分功能由ForkAndSpecializeCommon()函數實現,位於本類中,

static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
jint debug_flags, jobjectArray javaRlimits,
jlong permittedCapabilities, jlong effectiveCapabilities,
jint mount_external,
jstring java_se_info, jstring java_se_name,
bool is_system_server, jintArray fdsToClose,
jstring instructionSet, jstring dataDir){
......//省略
//設置信號處理函數
SetSigChldHandler();
//調用fork()函數
pid_t pid = fork();
if (pid == 0){
......//子進程
}else if(pid > 0) {
......//父進程處理
}
return pid;
}

ForkAndSpecializeCommon函數通過fork()系統函數創建子進程system_server,並在創建system_server前做了重要工作:注冊信號處理函數。該信號處理函數的作用就是代表子線程退出的信號。在setSigChldHandler()函數:

// Configures the SIGCHLD handler for the zygote process. This is configured
// very late, because earlier in the runtime we may fork() and exec()
// other processes, and we want to waitpid() for those rather than
// have them be harvested immediately.
//
// This ends up being called repeatedly before each fork(), but there's
// no real harm in that.
static void SetSigChldHandler() {
//這里是非常通用的Linux注冊信號處理函數的流程,調用系統函數sigaction()處理
//SIGCHLD信號,具體的處理函數是SigChldHandler。SIGCHLD信號是子進程退出信號
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SigChldHandler;

int err = sigaction(SIGCHLD, &sa, NULL);
if (err < 0) {
ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
}
}

SetSigChldHandler注冊了信號處理函數sigChldHandler,處理的信號便是SIGCHLD,代表子進程退出信號。

2.1.2 監控system_server進程的啟動結果
當子進程退出時,由SigChldHandler處理該信號,接下來分析sigchldHandler處理SIGCHLD信號。

// This signal handler is for zygote mode, since the zygote must reap its children
static void SigChldHandler(int /*signal_number*/) {
pid_t pid;
int status;

// It's necessary to save and restore the errno during this function.
// Since errno is stored per thread, changing it here modifies the errno
// on the thread on which this signal handler executes. If a signal occurs
// between a call and an errno check, it's possible to get the errno set
// here.
// See b/23572286 for extra information.
int saved_errno = errno;
//調用系統函數waitpid等待子進程退出
//第一個參數-1表示等待任何子進程
//第二個參數status用於收集子進程退出時的狀態
//第三個參數WNOHANG表示如果沒有子進程退出,不需要阻塞
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
// Log process-death status that we care about. In general it is
// not safe to call LOG(...) from a signal handler because of
// possible reentrancy. However, we know a priori that the
// current implementation of LOG() is safe to call from a SIGCHLD
// handler in the zygote process. If the LOG() implementation
// changes its locking strategy or its use of syscalls within the
// lazy-init critical section, its use here may become unsafe.
if (WIFEXITED(status)) {
if (WEXITSTATUS(status)) {
ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
}
} else if (WIFSIGNALED(status)) {
if (WTERMSIG(status) != SIGKILL) {
ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
}
if (WCOREDUMP(status)) {
ALOGI("Process %d dumped core.", pid);
}
}

// If the just-crashed process is the system_server, bring down zygote
// so that it is restarted by init and system server will be restarted
// from there.
if (pid == gSystemServerPid) {
ALOGE("Exit zygote because system server (%d) has terminated", pid);
//如果退出的是system_server進程,zygote重啟,SIGKILL是自殺信號。
//雖然zygote自殺了,但是init進程會負責救活它。
kill(getpid(), SIGKILL);
}
}

從forkSystemServer函數的執行過程可以看出:zygote創建system_server進程是十分謹慎的,不但在創建之初判斷system_server是否退出,在創建后還專門注冊信號處理函數監控system_server的運行狀態。如果system_server出現意外,zygote也會自殺,導致整個java世界崩潰。
接下來分析fork出system_server后的處理。

2.2 在子進程中調用handleSystemServerProcess方法
system_server進程啟動之后,便開始調用handleSystemServerProcess方法,該方法位於ZygoteInit.java中,代碼如下:

    /**
* Finish remaining work for the newly forked system server process.
*/

private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {

// 關閉之前fork操作時,從zygote繼承下來的socket
closeServerSocket();

// set umask to 0077 so new files and directories will default to owner-only permissions.
Os.umask(S_IRWXG | S_IRWXO);

if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}

final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
performSystemServerDexOpt(systemServerClasspath);
}

// 根據invokeWith參數,執行一個shell命令
if (parsedArgs.invokeWith != null) {
String[] args = parsedArgs.remainingArgs;
// If we have a non-null system server class path, we'll have to duplicate the
// existing arguments and append the classpath to it. ART will handle the classpath
// correctly when we exec a new process.
if (systemServerClasspath != null) {
String[] amendedArgs = new String[args.length + 2];
amendedArgs[0] = "-cp";
amendedArgs[1] = systemServerClasspath;
System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
}

WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(), null, args);
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = createSystemServerClassLoader(systemServerClasspath,
parsedArgs.targetSdkVersion);

Thread.currentThread().setContextClassLoader(cl);
}

/*
* Pass the remaining arguments to SystemServer.
*/

//調用zygoteInit方法,傳入參數
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}

/* should never reach here */
}

system_server生成之后,迅速進入工作狀態,執行handleSystemServerProcess。在該方法中,首先做了一些清理和初始化工作,接着調用RuntimeInit.zygoteInit()方法。
RuntimeInit.java位於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.<p>
*
* Current recognized args:
* <ul>
* <li> <code> [--] &lt;start class name&gt; &lt;args&gt;
* </ul>
*
* @param targetSdkVersion target SDK version
* @param argv arg strings
*/

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
redirectLogStreams();

commonInit();
nativeZygoteInit();
applicationInit(targetSdkVersion, argv, classLoader);
}

zygoteInit封裝了對四個方法的調用,對應四個步驟試下 不同的初始化操作,接下來分析四步。

2.2.1 redirectLogStrreams() 方法重定向標准I/O操作
redirectLogStreams()方法重定向Java標准I/O操作到Android日志系統。

   /**
* Redirect System.out and System.err to the Android log.
*/

public static void redirectLogStreams() {
System.out.close();
System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
System.err.close();
System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
}

2.2.2 commonInit() 方法初始化通用設置

    private static final void commonInit() {
if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");

/* set default handler; this applies to all threads in the VM */
//設置未不會異常的默認處理函數
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());

/*
* Install a TimezoneGetter subclass for ZoneInfo.db
*/
//獲取persist.sys.timezone 屬性
TimezoneGetter.setInstance(new TimezoneGetter() {
@Override
public String getId() {
return SystemProperties.get("persist.sys.timezone");
}
});
TimeZone.setDefault(null);

/*
* Sets handler for java.util.logging to use Android log facilities.
* The odd "new instance-and-then-throw-away" is a mirror of how
* the "java.util.logging.config.class" system property works. We
* can't use the system property here since the logger has almost
* certainly already been initialized.
*/
//Android Log配置
LogManager.getLogManager().reset();
new AndroidConfig();

/*
* Sets the default HTTP User-Agent used by HttpURLConnection.
*/
//默認的HTTP User-Agent,用於HTTP連接
String userAgent = getDefaultUserAgent();
System.setProperty("http.agent", userAgent);

/*
* Wire socket tagging to traffic stats.
*/
NetworkManagementSocketTagger.install();//網絡相關

/*
* If we're running in an emulator launched with "-trace", put the
* VM into emulator trace profiling mode so that the user can hit
* F9/F10 at any time to capture traces. This has performance
* consequences, so it's not something you want to do always.
*/
//模擬器上面的trace調試
String trace = SystemProperties.get("ro.kernel.android.tracing");
if (trace.equals("1")) {
Slog.i(TAG, "NOTE: emulator trace profiling enabled");
Debug.enableEmulatorTraceOutput();
}

2.2.3 onZygoteInit 方法開啟Binder通信
nativeZygoteInit是一個Native方法,其JNI實現方法位於frameworks\base\core\jni\AndroidRuntime.cpp,方法名為com_android_internal_os_RuntimeInit_nativeZygoteInit,具體代碼:

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}

onZygoteInit開啟了sysytem_serve的Binder通道。

2.2.4 invokeStaticMain方法拋出異常

這樣,system_server進程已經基本啟動完成,之后system_server進程會啟動系統核心服務,以及其他服務。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com