Android系統程序Zygote啟動過程的原始碼分析
在Android系統中,所有的應用程式程序以及系統服務程序SystemServer都是由Zygote程序孕育(fork)出來的,這也許就是為什麼要把它稱為Zygote(受精卵)的原因吧。由於Zygote程序在Android系統中有著如此重要的地位,本文將詳細分析它的啟動過程。
《Android系統原始碼情景分析》一書正在進擊的程式設計師網(http://0xcc0xcd.com)中連載,點選進入!
在前面一篇文章Android應用程式程序啟動過程的原始碼分析中,我們看到了,當ActivityManagerService啟動一個應用程式的時候,就會通過Socket與Zygote程序進行通訊,請求它fork一個子程序出來作為這個即將要啟動的應用程式的程序;在前面兩篇文章
我們知道,Android系統是基於Linux核心的,而在Linux系統中,所有的程序都是init程序的子孫程序,也就是說,所有的程序都是直接或者間接地由init程序fork出來的。Zygote程序也不例外,它是在系統啟動的過程,由init程序建立的。在系統啟動指令碼system/core/rootdir/init.rc檔案中,我們可以看到啟動Zygote程序的指令碼命令:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
前面的關鍵字service告訴init程序建立一個名為"zygote"的程序,這個zygote程序要執行的程式是/system/bin/app_process,後面是要傳給app_process的引數。 接下來的socket關鍵字表示這個zygote程序需要一個名稱為"zygote"的socket資源,這樣,系統啟動後,我們就可以在/dev/socket目錄下看到有一個名為zygote的檔案。這裡定義的socket的型別為unix domain socket,它是用來作本地程序間通訊用的,具體可以參考前面一篇文章
最後的一系列onrestart關鍵字表示這個zygote程序重啟時需要執行的命令。
關於init.rc檔案的更多資訊,請參考system/core/init/readme.txt檔案。
瞭解了這個資訊之後,我們就知道Zygote程序要執行的程式便是system/bin/app_process了,它的原始碼位於frameworks/base/cmds/app_process/app_main.cpp檔案中,入口函式是main。在繼續分析Zygote程序啟動的過程之前,我們先來看看它的啟動序列圖:
下面我們就詳細分析每一個步驟。
Step 1. app_process.main
這個函式定義在frameworks/base/cmds/app_process/app_main.cpp檔案中:
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 *arg;
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);
// Next arg is parent directory
if (i < argc) {
runtime.mParentDir = argv[i++];
}
// Next arg is startup classname or "--zygote"
if (i < argc) {
arg = argv[i++];
if (0 == strcmp("--zygote", arg)) {
bool startSystemServer = (i < argc) ?
strcmp(argv[i], "--start-system-server") == 0 : false;
setArgv0(argv0, "zygote");
set_process_name("zygote");
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer);
} else {
set_process_name(argv0);
runtime.mClassName = arg;
// Remainder of args get passed to startup class main()
runtime.mArgC = argc-i;
runtime.mArgV = argv+i;
LOGV("App process is starting with pid=%d, class=%s.\n",
getpid(), runtime.getClassName());
runtime.start();
}
} else {
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
return 10;
}
}
這個函式的主要作用就是建立一個AppRuntime變數,然後呼叫它的start成員函式。AppRuntime這個類我們在Android應用程式程序啟動過程的原始碼分析一文中已經有過介紹了,它同樣是在frameworks/base/cmds/app_process/app_main.cpp檔案中定義:class AppRuntime : public AndroidRuntime
{
......
};
它約繼承於AndroidRuntime類, AndroidRuntime類定義在frameworks/base/core/jni/AndroidRuntime.cpp檔案中:......
static AndroidRuntime* gCurRuntime = NULL;
......
AndroidRuntime::AndroidRuntime()
{
......
assert(gCurRuntime == NULL); // one per process
gCurRuntime = this;
}
當AppRuntime物件建立時,會呼叫其父類AndroidRuntime的建構函式,而在AndroidRuntime類的建構函式裡面,會將this指標儲存在靜態全域性變數gCurRuntime中,這樣,當其它地方需要使用這個AppRuntime物件時,就可以通過同一個檔案中的這個函式來獲取這個物件的指標:AndroidRuntime* AndroidRuntime::getRuntime()
{
return gCurRuntime;
}
回到上面的main函式中,由於我們在init.rc檔案中,設定了app_process啟動引數--zygote和--start-system-server,因此,在main函式裡面,最終會執行下面語句: runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer);
這裡的引數startSystemServer為true,表示要啟動SystemServer元件。由於AppRuntime沒有實現自己的start函式,它繼承了父類AndroidRuntime的start函式,因此,下面會執行AndroidRuntime類的start函式。Step 2. AndroidRuntime.start
這個函式定義在frameworks/base/core/jni/AndroidRuntime.cpp檔案中:
/*
* 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".
*/
void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
......
char* slashClassName = NULL;
char* cp;
JNIEnv* env;
......
/* start the virtual machine */
if (startVm(&mJavaVM, &env) != 0)
goto bail;
/*
* Register android functions.
*/
if (startReg(env) < 0) {
LOGE("Unable to register all android natives\n");
goto bail;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we only have one argument, the class name. Create an
* array to hold it.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring startSystemServerStr;
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);
startSystemServerStr = env->NewStringUTF(startSystemServer ?
"true" : "false");
env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
jclass startClass;
jmethodID startMeth;
slashClassName = strdup(className);
for (cp = slashClassName; *cp != '\0'; cp++)
if (*cp == '.')
*cp = '/';
startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
......
} else {
startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
......
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
......
}
}
......
}
這個函式的作用是啟動Android系統執行時庫,它主要做了三件事情,一是呼叫函式startVM啟動虛擬機器,二是呼叫函式startReg註冊JNI方法,三是呼叫了com.android.internal.os.ZygoteInit類的main函式。
Step 3. ZygoteInit.main
這個函式定義在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java檔案中:
public class ZygoteInit {
......
public static void main(String argv[]) {
try {
......
registerZygoteSocket();
......
......
if (argv[1].equals("true")) {
startSystemServer();
} else if (!argv[1].equals("false")) {
......
}
......
if (ZYGOTE_FORK_MODE) {
......
} else {
runSelectLoopMode();
}
......
} catch (MethodAndArgsCaller caller) {
......
} catch (RuntimeException ex) {
......
}
}
......
}
它主要作了三件事情,一個呼叫registerZygoteSocket函式建立了一個socket介面,用來和ActivityManagerService通訊,二是呼叫startSystemServer函式來啟動SystemServer元件,三是呼叫runSelectLoopMode函式進入一個無限迴圈在前面建立的socket介面上等待ActivityManagerService請求建立新的應用程式程序。Step 4. ZygoteInit.registerZygoteSocket
這個函式定義在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java檔案中:
public class ZygoteInit {
......
/**
* Registers a server socket for zygote command connections
*
* @throws RuntimeException when open fails
*/
private static void registerZygoteSocket() {
if (sServerSocket == null) {
int fileDesc;
try {
String env = System.getenv(ANDROID_SOCKET_ENV);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
......
}
try {
sServerSocket = new LocalServerSocket(
createFileDescriptor(fileDesc));
} catch (IOException ex) {
.......
}
}
}
......
}
這個socket介面是通過檔案描述符來建立的,這個檔案描符代表的就是我們前面說的/dev/socket/zygote檔案了。這個檔案描述符是通過環境變數ANDROID_SOCKET_ENV得到的,它定義為:public class ZygoteInit {
......
private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";
......
}
那麼,這個環境變數的值又是由誰來設定的呢?我們知道,系統啟動指令碼檔案system/core/rootdir/init.rc是由init程序來解釋執行的,而init程序的原始碼位於system/core/init目錄中,在init.c檔案中,是由service_start函式來解釋init.rc檔案中的service命令的:void service_start(struct service *svc, const char *dynamic_args)
{
......
pid_t pid;
......
pid = fork();
if (pid == 0) {
struct socketinfo *si;
......
for (si = svc->sockets; si; si = si->next) {
int socket_type = (
!strcmp(si->type, "stream") ? SOCK_STREAM :
(!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));
int s = create_socket(si->name, socket_type,
si->perm, si->uid, si->gid);
if (s >= 0) {
publish_socket(si->name, s);
}
}
......
}
......
}
每一個service命令都會促使init程序呼叫fork函式來建立一個新的程序,在新的程序裡面,會分析裡面的socket選項,對於每一個socket選項,都會通過create_socket函式來在/dev/socket目錄下建立一個檔案,在這個場景中,這個檔案便是zygote了,然後得到的檔案描述符通過publish_socket函式寫入到環境變數中去:static void publish_socket(const char *name, int fd)
{
char key[64] = ANDROID_SOCKET_ENV_PREFIX;
char val[64];
strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
name,
sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
snprintf(val, sizeof(val), "%d", fd);
add_environment(key, val);
/* make sure we don't close-on-exec */
fcntl(fd, F_SETFD, 0);
}
這裡傳進來的引數name值為"zygote",而ANDROID_SOCKET_ENV_PREFIX在system/core/include/cutils/sockets.h定義為:#define ANDROID_SOCKET_ENV_PREFIX "ANDROID_SOCKET_"
因此,這裡就把上面得到的檔案描述符寫入到以"ANDROID_SOCKET_zygote"為key值的環境變數中。又因為上面的ZygoteInit.registerZygoteSocket函式與這裡建立socket檔案的create_socket函式是執行在同一個程序中,因此,上面的ZygoteInit.registerZygoteSocket函式可以直接使用這個檔案描述符來建立一個Java層的LocalServerSocket物件。如果其它程序也需要開啟這個/dev/socket/zygote檔案來和Zygote程序進行通訊,那就必須要通過檔名來連線這個LocalServerSocket了,參考Android應用程式程序啟動過程的原始碼分析一文中的Step 4,ActivityManagerService是通過Process.start函式來建立一個新的程序的,而Process.start函式會首先通過Socket連線到Zygote程序中,最終由Zygote程序來完成建立新的應用程式程序,而Process類是通過openZygoteSocketIfNeeded函式來連線到Zygote程序中的Socket的:public class Process {
......
private static void openZygoteSocketIfNeeded()
throws ZygoteStartFailedEx {
......
for (int retry = 0
; (sZygoteSocket == null) && (retry < (retryCount + 1))
; retry++ ) {
......
try {
sZygoteSocket = new LocalSocket();
sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,
LocalSocketAddress.Namespace.RESERVED));
sZygoteInputStream
= new DataInputStream(sZygoteSocket.getInputStream());
sZygoteWriter =
new BufferedWriter(
new OutputStreamWriter(
sZygoteSocket.getOutputStream()),
256);
......
} catch (IOException ex) {
......
}
}
......
}
......
}
這裡的ZYGOTE_SOCKET定義為:public class Process {
......
private static final String ZYGOTE_SOCKET = "zygote";
......
}
它剛好就是對應/dev/socket目錄下的zygote檔案了。Android系統中的socket機制和binder機制一樣,都是可以用來進行程序間通訊,讀者可以自己對比一下這兩者的不同之處,Binder程序間通訊機制可以參考Android程序間通訊(IPC)機制Binder簡要介紹和學習計劃一文。
Socket物件建立完成之後,回到Step 3中的ZygoteInit.main函式中,startSystemServer函式來啟動SystemServer元件。
Step 5. ZygoteInit.startSystemServer
這個函式定義在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java檔案中:
public class ZygoteInit {
......
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",
"--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);
......
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, debugFlags, null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
......
}
/* For child process */
if (pid == 0) {
handleSystemServerProcess(parsedArgs);
}
return true;
}
......
}
這裡我們可以看到,Zygote程序通過Zygote.forkSystemServer函式來建立一個新的程序來啟動SystemServer元件,返回值pid等0的地方就是新的程序要執行的路徑,即新建立的程序會執行handleSystemServerProcess函式。 Step 6. ZygoteInit.handleSystemServerProcess
這個函式定義在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java檔案中:
public class ZygoteInit {
......
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket();
/*
* Pass the remaining arguments to SystemServer.
* "--nice-name=system_server com.android.server.SystemServer"
*/
RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
/* should never reach here */
}
......
}
由於由Zygote程序建立的子程序會繼承Zygote程序在前面Step 4中建立的Socket檔案描述符,而這裡的子程序又不會用到它,因此,這裡就呼叫closeServerSocket函式來關閉它。這個函式接著呼叫RuntimeInit.zygoteInit函式來進一步執行啟動SystemServer元件的操作。Step 7. RuntimeInit.zygoteInit
這個函式定義在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java檔案中:
public class RuntimeInit {
......
public static final void zygoteInit(String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
......
zygoteInitNative();
......
// Remaining arguments are passed to the start class's static main
String startClass = argv[curArg++];
String[] startArgs = new String[argv.length - curArg];
System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
invokeStaticMain(startClass, startArgs);
}
......
}
這個函式會執行兩個操作,一個是呼叫zygoteInitNative函式來執行一個Binder程序間通訊機制的初始化工作,這個工作完成之後,這個程序中的Binder物件就可以方便地進行程序間通訊了,另一個是呼叫上面Step 5傳進來的com.android.server.SystemServer類的main函式。Step 8. RuntimeInit.zygoteInitNative
這個函式定義在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java檔案中:
public class RuntimeInit {
......
public static final native void zygoteInitNative();
......
}
這裡可以看出,函式zygoteInitNative是一個Native函式,實現在frameworks/base/core/jni/AndroidRuntime.cpp檔案中,這裡我們就不再細看了,具體可以參考Android應用程式程序啟動過程的原始碼分析一文的Step 9,完成這一步後,這個程序的Binder程序間通訊機制基礎設施就準備好了。回到Step 7中的RuntimeInit.zygoteInitNative函式,下一步它就要執行com.android.server.SystemServer類的main函數了。
Step 9. SystemServer.main
這個函式定義在frameworks/base/services/java/com/android/server/SystemServer.java檔案中:
public class SystemServer
{
......
native public static void init1(String[] args);
......
public static void main(String[] args) {
......
init1(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();
}
......
}
這裡的main函式首先會執行JNI方法init1,然後init1會呼叫這裡的init2函式,在init2函式裡面,會建立一個ServerThread執行緒物件來執行一些系統關鍵服務的啟動操作,例如我們在前面兩篇文章Android應用程式安裝過程原始碼分析和Android系統預設Home應用程式(Launcher)的啟動過程原始碼分析中提到的PackageManagerService和ActivityManagerService。這一步的具體執行過程可以參考Android應用程式安裝過程原始碼分析一文,這裡就不再詳述了。
這裡執行完成後,層層返回,最後回到上面的Step 3中的ZygoteInit.main函式中,接下來它就要呼叫runSelectLoopMode函式進入一個無限迴圈在前面Step 4中建立的socket介面上等待ActivityManagerService請求建立新的應用程式程序了。
Step 10. ZygoteInit.runSelectLoopMode
這個函式定義在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java檔案中:
public class ZygoteInit {
......
private static void runSelectLoopMode() throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList();
ArrayList<ZygoteConnection> peers = new ArrayList();
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
int loopCount = GC_LOOP_COUNT;
while (true) {
int index;
......
try {
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done;
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
......
}
這個函式我們已經在Android應用程式程序啟動過程的原始碼分析一文的Step 5中分析過了,這就是在等待ActivityManagerService來連線這個Socket,然後呼叫ZygoteConnection.runOnce函式來建立新的應用程式,有興趣的讀者可以參考Android應用程式程序啟動過程的原始碼分析這篇文章,這裡就不再詳述了。 這樣,Zygote程序就啟動完成了,學習到這裡,我們終於都對Android系統中的程序有了一個深刻的認識了,這裡總結一下:
1. 系統啟動時init程序會建立Zygote程序,Zygote程序負責後續Android應用程式框架層的其它程序的建立和啟動工作。
2. Zygote程序會首先建立一個SystemServer程序,SystemServer程序負責啟動系統的關鍵服務,如包管理服務PackageManagerService和應用程式元件管理服務ActivityManagerService。
3. 當我們需要啟動一個Android應用程式時,ActivityManagerService會通過Socket程序間通訊機制,通知Zygote程序為這個應用程式建立一個新的程序。
相關推薦
Android系統程序Zygote啟動過程的原始碼分析
在Android系統中,所有的應用程式程序以及系統服務程序SystemServer都是由Zygote程序孕育(fork)出來的,這也許就是為什麼要把它稱為Zygote(受精卵)的原因吧。由於Zygote程序在Android系統中有著如此重要的地位,本文將詳細分
Android系統程序間通訊 IPC 機制Binder中的Server啟動過程原始碼分析
在前面一篇文章中,介紹了在Android系統中Binder程序間通訊機制中的Server角色是如何獲得Service Manager遠端介面的,即defaultServiceManager函式的實現。Server獲得了Service Manager遠端介面之後,
Android 8.0系統原始碼分析--openCamera(HAL)啟動過程原始碼分析
前面我們詳細分析了從應用層呼叫CameraManager的openCamera的方法來開啟相機的邏輯,上次的分析我們來到了CameraServer程序當中,但是還沒有真正看到open操作裝置節點來實現真正開啟的邏輯,遺留的問題也就是從frameworks\av\se
Android 8.0系統原始碼分析--startService啟動過程原始碼分析
作過android應用開發的同事都非常清楚,android提供了四個元件Activity、Service、BroastcastReceiver、ContentProvider,分別都有不同的作用,這也給我們的應用開發提供了非常大的幫助,因為這四大元件本身就已經處理了很
Android 8.0系統原始碼分析--openCamera啟動過程原始碼分析
說起Android相機的東西,從應用層的角度來看,基本就是四個重要的節點了:openCamera、createCaptureSession、preview、capture,最複雜的就是preview了,要理解preview,那麼就要求大家對And
Android應用程式啟動過程原始碼分析(2)
Step 9. ActivityStack.startActivityUncheckedLocked 這個函式定義在frameworks/base/services/java/com/android/server/am/ActivityStack.java檔案中: view plain pu
Android應用程式啟動過程原始碼分析
前文簡要介紹了Android應用程式的Activity的啟動過程。在Android系統中,應用程式是由Activity組成的,因此,應用程式的啟動過程實際上就是應用程式中的預設Activity的啟動過程,本文將詳細分析應用程式框架層的原始碼,瞭解Android
Activity啟動過程原始碼分析(Android 8.0)
Activity啟動過程原始碼分析 本文來Activity的啟動流程,一般我們都是通過startActivity或startActivityForResult來啟動目標activity,那麼我們就由此出發探究系統是如何實現目標activity的啟動的。 startActivity(new Intent(con
Netty NioEventLoop 啟動過程原始碼分析
原文連結:https://wangwei.one/posts/netty-nioeventloop-analyse-for-startup.html 前面 ,我們分析了NioEventLoop的建立過程,接下來我們開始分析NioEventLoop的啟動和執行邏輯。
Netty(五)服務端啟動過程原始碼分析——好文摘抄
下面先來一段 Netty 服務端的程式碼: public class NettyServer { public void bind(int port){ // 建立EventLoopGroup EventLoopGroup bossGroup = new
Uboot啟動過程原始碼分析之第二階段
UBoot的最終目標是啟動核心 1.從Flash中讀出核心 2.啟動核心 通過呼叫lib_arm/board.c中的start_armboot函式進入uboot第二階段 第二階段總結圖 typedef struct global_data { bd_t *bd; unsigned
Uboot啟動過程原始碼分析之第一階段(硬體相關)
從上一個部落格知道uboot的入口點在 cpu/arm920t/start.s 開啟cpu/arm920t/start.s 跳轉到reset reset: /* * set the cpu to SVC32 mode// CUP設定為管理模式 */ mrs r0,cps
Android 資料Parcel序列化過程原始碼分析
在Android系統中,所有的服務都必須註冊到ServiceManger中,當客戶程序需要請求某一服務時,首先從服務管家ServiceManger中查找出該服務,然後通過RPC遠端呼叫的方式使用該服務。服務在註冊到ServiceManager時,需要將該服務物件傳送到Ser
U-Boot啟動過程原始碼分析(2)-第二階段
先總述:第一階段cpu/arm920t/start.S和board/smdk2410/lowlevel_init.S進行初始化,再跳到第二階段的入口點lib_arm/board.c中的start_armboot函式。 第二階段start_armboot函式需
Netty入門一:服務端應用搭建 & 啟動過程原始碼分析
最近週末也沒啥事就學學Netty,同時打算寫一些部落格記錄一下(寫的過程理解更加深刻了) 本文主要從三個方法來呈現:Netty核心元件簡介、Netty服務端建立、Netty啟動過程原始碼分析 如果你對Netty有一定的瞭解, 那閱讀起來應該會比較愉快 ## Netty核心元件簡介 ### ByteBu
Android 8.0系統原始碼分析--Activity的視窗Window物件新增過程原始碼分析
這節我們來看一下Activity的視窗Window物件的建立過程,Activity作為Android提供的四大元件之首,我們之所以能非常簡單的使用它,就是因為它的建立過程中,framework為我們作了大量的初始化工作,包括它的視窗Window、視訊記憶體Surf
Android Framework學習——Launcher啟動應用程式過程原始碼分析
ActivityInfo aInfo = r.activityInfo; if (r.packageInfo == null) { r.packageInfo = getPackageInfo(aInfo.applicationInfo,
Android 8.0系統原始碼分析--相機createCaptureSession建立過程原始碼分析
上一次我們詳細分析了openCamera啟動過程的原始碼,從CameraServer程序建立了很多物件,比如CameraDeviceClient、Camera3Device、FrameProcessorBase,而真正開啟相機還是在驅動層中上電後才完成的,有時候真想
linux系統的啟動過程簡要分析
com bubuko 加載內核 ice func auth 變量 number 啟動過程 接觸linux系統運維已經好幾年了,常常被問到linux系統啟動流程問題,剛好今天有空來梳理下這個過程:一般來說,所有的操作系統的啟動流程基本就是: 總的來說,linux系統啟動
Android進階3:Activity原始碼分析(2) —— Activity啟動和銷燬流程(8.0)
上篇文章講述了app從啟動建立Activity呼叫onCreate,onStart, onResume方法,這篇文章講述一下Activity啟動的另一個切入點:startActivity方法,啟動Activity。 通過上一篇文章,我們總結一下: 1:A