Android起動プロセスの詳細(4)-SystemServer
9539 ワード
前のブログではZygoteServiceの起動手順を紹介していましたが、Zygoteの起動後はまずSystemServerが起動するので、SystemServerはZygote嫡男と見ることができます.嫡男の長男になるには必然的に非常に重要な役割があります.確かに、Androidアプリケーションフレームワークのさまざまなサービス、例えばActivity Management Service、PacakgeManagerService、WindowManagerServiceなどの重要なシステムサービスはSystemServerで開始されています.このブログでは、SystemServerの起動手順を見てみましょう.
1.SystemServer起動
SystemServerはZygote.startSystemServerが起動するので、まず対応するコードを見てみましょう.その対応する実装はdalvik_にあります.system_Zygote.cではnative関数です.
上記のコードから、Zygoteはシステムサーバのホストとしてプロセスをforkし、具体的な操作は
最後にsetSignalHandler関数を見てみましょう.これは、forkサブプロセスの前にZygoteによって呼び出されます.コードは次のようになります.
この信号処理関数sigchldHandlerを直接見て
2.SystemServerの役割
次に、SystemServerが起動中に具体的に何をしたかを見てみましょう.
コードから分かるように、システムサーバがforkされると、handleSystemServer Processが呼び出され、自身の起動ロジックが処理されます.
よし、SSはRuntimeInitに着いた.そのコードはRuntimeInitにある.JAvaでは、以下のようになります.
上のコードには2つの点が重要です. zygoteInitNative,nativeレイヤの初期化 を実行する. invokeStaticMain(startClass,startArgs):SystemServerのmain関数を実行します.次に、以上の2点をそれぞれ説明します. 2.1
この関数は最終的にAppMainのonZygoteInit関数を呼び出します.
2.2 invokeStaticMain
この関数が奇妙な点は、
次にZygoteが起動した後に何をしたかを見てみましょう.まずmain関数を見てみましょう.
だから起動プロセスはinit 1関数に移行しました:init 1はnative関数で、com_android_server_SystemServer.cppで実装:
system_Initの実装はsystem_init.cppでは、そのコードを以下に示します.
Init 1関数はいくつかのシステムサービスを作成し,呼び出しスレッドをBinder通信に組み込む.しかしその間にJNIを介してcomが呼び出された.android.server.SystemServerクラスのinit 2関数ですが、このinit 2関数を見てみましょう.Init 2はJava層にあり、コードはSystemServerにある.JAva:
ServerThreadスレッドが起動しました.そのrun関数を直接見てください.この関数は長いので、何をしたか見てみましょう.
Init 2関数は比較的簡単で、システムの各サービスを開始するためにスレッドを個別に作成します.これでシステムサーバの起動が完了します.
1.SystemServer起動
SystemServerはZygote.startSystemServerが起動するので、まず対応するコードを見てみましょう.その対応する実装はdalvik_にあります.system_Zygote.cではnative関数です.
[-->dalvik_system_Zygote.c]
static voidDalvik_dalvik_system_Zygote_forkSystemServer(
const u4* args, JValue* pResult)
{
pid_tpid;
// ,fork
pid =forkAndSpecializeCommon(args);
if (pid > 0) {
int status;
gDvm.systemServerPid = pid;// system_server id
// 。
if(waitpid(pid, &status, WNOHANG) == pid) {
// system_server ,Zygote
// Zygote SS , !
kill(getpid(), SIGKILL);
}
}
RETURN_INT(pid);
}
上記のコードから、Zygoteはシステムサーバのホストとしてプロセスをforkし、具体的な操作は
forkAndSpecializeCommon
で完了することがわかります.SystemServerの作成プロセスが完了すると、Zygoteは対応するプロセスが終了したかどうかを確認し、終了した場合、Zygoteも自分を殺します.次に、forkAndSpecializeCommonを見てみましょう.コードは次のとおりです.[-->dalvik_system_Zygote.c]
static pid_t forkAndSpecializeCommon(const u4*args)
{
pid_tpid;
uid_tuid = (uid_t) args[0];
gid_tgid = (gid_t) args[1];
ArrayObject* gids = (ArrayObject *)args[2];
u4debugFlags = args[3];
ArrayObject *rlimits = (ArrayObject *)args[4];
// , 。
setSignalHandler();
pid =fork(); //fork
if (pid== 0) {
// , , id( id, id )
}
......
}
最後にsetSignalHandler関数を見てみましょう.これは、forkサブプロセスの前にZygoteによって呼び出されます.コードは次のようになります.
[-->dalvik_system_Zygote.c]
static void setSignalHandler()
{
interr;
structsigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sigchldHandler;
err =sigaction (SIGCHLD, &sa, NULL);// ,
}
この信号処理関数sigchldHandlerを直接見て
static void sigchldHandler(int s)
{
pid_tpid;
intstatus;
while((pid = waitpid(-1, &status, WNOHANG)) > 0) {
} else if (WIFSIGNALED(status)) {
}
}
// SS, Zygote , !
if(pid == gDvm.systemServerPid) {
kill(getpid(), SIGKILL);
}
}
2.SystemServerの役割
次に、SystemServerが起動中に具体的に何をしたかを見てみましょう.
pid =Zygote.forkSystemServer();
if(pid == 0) { // :
handleSystemServerProcess(parsedArgs);
}
コードから分かるように、システムサーバがforkされると、handleSystemServer Processが呼び出され、自身の起動ロジックが処理されます.
[-->ZygoteInit.java]
private static void handleSystemServerProcess(
ZygoteConnection.ArgumentsparsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
// Zygote Socket。
closeServerSocket();
// SS 。
setCapabilities(parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
// ZygoteInit 。
RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
}
よし、SSはRuntimeInitに着いた.そのコードはRuntimeInitにある.JAvaでは、以下のようになります.
[-->RuntimeInit.java]
public static final void zygoteInit(String[]argv)
throws ZygoteInit.MethodAndArgsCaller {
//
commonInit();
//①native 。
zygoteInitNative();
intcurArg = 0;
for (/* curArg */ ; curArg < argv.length; curArg++) {
String arg = argv[curArg];
if (arg.equals("--")) {
curArg++;
break;
} else if (!arg.startsWith("--")) {
break;
} else if (arg.startsWith("--nice-name=")) {
String niceName = arg.substring(arg.indexOf('=') + 1);
// niceName, "system_server"
Process.setArgV0(niceName);
}
}
//startClass "com.android.server.SystemServer"
String startClass = argv[curArg++];
String[] startArgs = new String[argv.length - curArg];
System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
//② startClass, com.android.server.SystemServer main 。
invokeStaticMain(startClass, startArgs);
}
上のコードには2つの点が重要です.
zygoteInitNative
この関数は最終的にAppMainのonZygoteInit関数を呼び出します.
[-->App_main.cpp]
virtual void onZygoteInit()
{
// Binder
sp proc = ProcessState::self();
if(proc->supportsProcesses()) {
proc->startThreadPool();// , Binder 。
}
}
2.2 invokeStaticMain
[-->RuntimeInit.java]
private static void invokeStaticMain(StringclassName, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
......
//className "com.android.server.SystemServer"
Class> cl;
try {
cl = Class.forName(className);
}catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class wheninvoking static main " + className,
ex);
}
Method m;
try {
// com.android.server.SystemServer main ,
m = cl.getMethod("main", new Class[] { String[].class });
}catch (NoSuchMethodException ex) {
......
}catch (SecurityException ex) {
......
}
int modifiers = m.getModifiers();
if(! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
......
}
//
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
この関数が奇妙な点は、
com.android.server.SystemServer
クラスにロードされ、対応するmain関数が見つかった後、直接関数を起動するのではなく、ZygoteInitのmain関数でcatchされ、対応する面関数が起動される異常を投げ出したことです.これはスタックを空にするためであり,スタックのスタックトップがZygoteInitであることをユーザに見せるためである.main. 次にZygoteが起動した後に何をしたかを見てみましょう.まずmain関数を見てみましょう.
[-->SystemServer.java]
public static void main(String[] args) {
......
// libandroid_servers.so
System.loadLibrary("android_servers");
// native init1 。
init1(args);
}
だから起動プロセスはinit 1関数に移行しました:init 1はnative関数で、com_android_server_SystemServer.cppで実装:
[-->com_android_server_SystemServer.cpp]
extern "C" int system_init();
static voidandroid_server_SystemServer_init1(JNIEnv* env, jobject clazz)
{
system_init();// 。
}
system_Initの実装はsystem_init.cppでは、そのコードを以下に示します.
[-->system_init.cpp]
extern "C" status_t system_init()
{
// Binder , 6 , 。
sp proc(ProcessState::self());
sp sm = defaultServiceManager();
spgrim = new GrimReaper();
sm->asBinder()->linkToDeath(grim, grim.get(), 0);
charpropBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsurfaceflinger", propBuf,"1");
if(strcmp(propBuf, "1") == 0) {
//SurfaceFlinger system_server
SurfaceFlinger::instantiate();
}
......
// com.android.server.SystemServer init2
AndroidRuntime* runtime = AndroidRuntime::getRuntime();
runtime->callStatic("com/android/server/SystemServer","init2");
// Binder 。
if (proc->supportsProcesses()) {
ProcessState::self()->startThreadPool();
// joinThreadPool , Binder
IPCThreadState::self()->joinThreadPool();
}
returnNO_ERROR;
}
Init 1関数はいくつかのシステムサービスを作成し,呼び出しスレッドをBinder通信に組み込む.しかしその間にJNIを介してcomが呼び出された.android.server.SystemServerクラスのinit 2関数ですが、このinit 2関数を見てみましょう.Init 2はJava層にあり、コードはSystemServerにある.JAva:
[-->SystemServer.java]
public static final void init2() {
Threadthr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();// ServerThread
}
ServerThreadスレッドが起動しました.そのrun関数を直接見てください.この関数は長いので、何をしたか見てみましょう.
[-->SystemServer.java::ServerThread run ]
public void run(){
....
// Entropy Service
ServiceManager.addService("entropy",new EntropyService());
//
power =new PowerManagerService();
ServiceManager.addService(Context.POWER_SERVICE, power);
// 。
battery= new BatteryService(context);
ServiceManager.addService("battery", battery);
//
Watchdog.getInstance().init(context,battery, power, alarm,
ActivityManagerService.self());
// WindowManager
wm =WindowManagerService.main(context, power,
factoryTest !=SystemServer.FACTORY_TEST_LOW_LEVEL);
ServiceManager.addService(Context.WINDOW_SERVICE,wm);
// ActivityManager
(ActivityManagerService)ServiceManager.getService("activity")).setWindowManager(wm);
......//
Looper.loop(); // , 。 5 。
}
Init 2関数は比較的簡単で、システムの各サービスを開始するためにスレッドを個別に作成します.これでシステムサーバの起動が完了します.