Android 시스템 부팅 프로세스 상세 정보

전언
안드로이드의 완전한 가동 과정을 연구하고 싶었는데 인터넷에서 많은 자료를 봤고 책에 있는 설명도 읽었다. 이런 관점에 대해 의심이 생겨서 시스템 가동의 완전한 과정을 스스로 분석했다.커널에서 첫 번째 사용자 프로그램인 init를 시작할 때부터 Home 응용 프로그램이 시작될 때까지 한 걸음 한 걸음 소스 코드가 보여집니다.안드로이드 시스템 가동 과정에 대한 독자들의 곤혹을 해소하고 궁금한 점이 있으면 댓글 교류를 환영합니다.본 연구는 CM10.1 원본 코드, 독자가 원본 코드와 대조하여 볼 수 있다면 효과가 더욱 좋을 것이다.
1) init 시작 서비스 관리자와zygote 두 서비스
안드로이드의 밑바닥은 리눅스 커널입니다. 리눅스와 유사합니다. 커널을 초기화한 후 시작하는 첫 번째 사용자 프로세스는 init입니다. 이것은 init를 해석합니다.rc 스크립트, init. 시작rc에서 설명한 서비스와 액션을 실행합니다.init.rc에는 다음과 같은 코드로 Andriod 공간을 시작하는 주요 서비스가 있습니다.
#…
service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onrestart restart zygote
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart drm
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
#…

서비스 관리자는 모든binder 서비스를 관리합니다. 이binder 서비스는native도 있고java도 있습니다.tive의 binder 서비스는surfaceflinger,drm,media 등이 있고java의 binder 서비스는 우리가 평소에 익숙한 많은 관리 서비스가 있습니다.Activity Manager 서비스,Window Manager 서비스,Battery 서비스,PowerManager 서비스,Inputt Manager 서비스 등입니다.서비스 관리자는 이binder 서비스의 생성을 책임지지 않습니다.native의binder 서비스는 대부분 init에서 init를 시작합니다.rc의 서비스는 만들고 시작합니다. 자바 층의 binder 서비스는 대부분zygote에서 만들고 시작합니다. 다음은 이 서비스가 어떻게 시작되었는지 자세히 설명합니다.
2) zygote 서비스 자바 레이어의 ZygoteInit 시작
zygote 서비스는 자바 층의 모든 프로그램 프로세스의 부모 프로세스입니다. 안드로이드 공간 프로그램의 부화기입니다. 안드로이드 공간의 모든 프로그램은 zygote 프로세스에서 시작합니다.zygote 서비스 대응/system/bin/app프로세스 프로그램, 원본 코드는 프레임워크/base/cmds/appprocess/app_main.cpp, 시작할 때main 함수 코드는 다음과 같습니다.
int main(int argc, const char* const argv[])
{
//...
/*runtime  dalvik     ,  Java    ,
 * fork      ,     ,     runtime      ,
 *     zygote  ,          
 */		 
AppRuntime runtime;
//... 
while (i < argc) {
    const char* arg = argv[i++];
    if (!parentDir) {
        parentDir = arg;
  /*init.rc  app_main     --zygote*/ 
    } else if (strcmp(arg, "--zygote") == 0) {
        zygote = true;
        niceName = "zygote"; //     
  /*init.rc  app_main     --start-system-server,
   *     systemserver
   */
    } else if (strcmp(arg, "--start-system-server") == 0) {
        startSystemServer = true;
 /*        --application  */             
    } else if (strcmp(arg, "--application") == 0) {
        application = true;
/*--nice-name=            */            
    } 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) {
/*      com.android.internal.os.ZygoteInit,
 *     start-system-server
 */
    runtime.start("com.android.internal.os.ZygoteInit",
            startSystemServer ? "start-system-server" : "");
} else if (className) {        
    /*   zygote,         com.android.internal.os.RuntimeInit,
     *RumtimeInit       mClassName
     */
    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.
"); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); return 10; } //... }

상기 코드를 통해zygote 서비스가 Dalvik 가상 기기를 실행하고 가상 기기에서com을 실행하는 것을 알 수 있다.android.internal.os.ZygoteInit, 매개 변수 start-system-server 전달
3) ZygoteInit SystemServer 시작
ZygoteInit 시작 시 관련 소스 코드:
public static void main(String argv[]) {
{
try {   
   //...
   //             ,
   //  Android              zygote      
   registerZygoteSocket();
   //... 
   if (argv[1].equals("start-system-server")) {
        //  SystemServer
        startSystemServer();
    } else if (!argv[1].equals("")) {
        throw new RuntimeException(argv[0] + USAGE_STRING);
    }
   //...
   /*ZYGOTE_FORK_MODE   false,   true  ,         ,
    *         ,                 ,           
    */
    if (ZYGOTE_FORK_MODE) {
        runForkMode();
    } else {
       //  Select poll         ,       ,            
        runSelectLoopMode();
    }
 
    closeServerSocket();
} catch (MethodAndArgsCaller caller) {
    caller.run();
} catch (RuntimeException ex) {
    Log.e(TAG, "Zygote died with exception", ex);
    closeServerSocket();
    throw ex;
}
}

위 코드에서 알 수 있듯이 StartSystemServer가 호출되어 SystemServer를 시작합니다. 관련 소스 코드는 다음과 같습니다.
private static boolean startSystemServer()
{
/* Hardcoded command line to start the system server */
//  SystemServer     
String args[] = {
    "--setuid=1000",
    "--setgid=1000",
    "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,3001,3002,3003,3004,3006,3007,3009",
    "--capabilities=130104352,130104352",
    "--runtime-init",
    "--nice-name=system_server",
    //  :           SystemServer     ,        SystemServer
    "com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
    /* args    ZygoteConnection    ,--           
     *           com.android.server.SystemServer   
     *ZygoteConnection.Arguments remainingArgs ,    handleSystemServerProcess    
     */
    parsedArgs = new ZygoteConnection.Arguments(args); 
    /*        */
    ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
    ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); 
    /*     */
    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   ZygoteConnection.Arguments remainingArgs  
	   *     , com.android.server.SystemServer	   
	   */
    handleSystemServerProcess(parsedArgs);
}
}

ZygoteInit의 startSystemServer에서 forkSystemServer를 호출하고 다음을 수행합니다.
ZygoteInit.forkSystemServer -> Zygote.nativeForkSystemServer-> dalvik_system_Zygote.cpp의 Dalvikdalvik_system_Zygote_forkSystemServer-> forkAndSpecializeCommon->fork 새 프로세스 만들기
ZygoteInit의 startSystemServer에서 시스템 서버를 실제로 시작하려면handleSystemServer가 호출됩니다. 관련 소스 코드는 다음과 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
//... 
if (parsedArgs.niceName != null) {
    Process.setArgV0(parsedArgs.niceName);
}
//  systemserver invokeWith null
if (parsedArgs.invokeWith != null) {
    WrapperInit.execApplication(parsedArgs.invokeWith,
            parsedArgs.niceName, parsedArgs.targetSdkVersion,
            null, parsedArgs.remainingArgs);
} else {
    /*
     *   systemserver ,parsedArgs.remainingArgs com.android.server.SystemServer.
     */
    RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
}
}

그리고 절차는요.
RuntimeInit.zygoteInit-> applicationInit, applicationInit 코드는 다음과 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static void applicationInit(int targetSdkVersion, String[] argv)
{
//...
final Arguments args;
try {
    //    ,     ,argv       com.android.server.SystemServer
    args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
    Slog.e(TAG, ex.getMessage());
    // let the process exit
    return;
}
//...
//       SystemServer
invokeStaticMain(args.startClass, args.startArgs)
}

4) SystemServer 부팅 프로세스
실행com.android.server.시스템 서버 시main 함수에서 init1 함수를 호출합니다. init1 함수는 로컬 함수입니다. init1의 실현은 프레임워크s/base/services/jni/comandroid_server_SystemServer.cpp에서 대응하는 jni 함수는androidserver_SystemServer_init1, 이 함수에서 시스템 호출init, 시스템init의 실현은 프레임워크/base/cmds/시스템server/library/system_init.cpp 함수의 구현 코드는 다음과 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
extern "C" status_t system_init()
{
//... 
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p
"
, sm.get()); sp<GrimReaper> grim = new GrimReaper(); sm->asBinder()->linkToDeath(grim, grim.get(), 0); char propBuf[PROPERTY_VALUE_MAX]; property_get("system_init.startsurfaceflinger", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { // Start the SurfaceFlinger SurfaceFlinger::instantiate(); } property_get("system_init.startsensorservice", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { // Start the sensor service SensorService::instantiate(); } // And now start the Android runtime. We have to do this bit // of nastiness because the Android runtime initialization requires // some of the core system services to already be started. // All other servers should just start the Android runtime at // the beginning of their processes's main(), before calling // the init function. ALOGI("System server: starting Android runtime.
"
); AndroidRuntime* runtime = AndroidRuntime::getRuntime(); ALOGI("System server: starting Android services.
"
); JNIEnv* env = runtime->getJNIEnv(); if (env == NULL) { return UNKNOWN_ERROR; } jclass clazz = env->FindClass("com/android/server/SystemServer"); if (clazz == NULL) { return UNKNOWN_ERROR; } // Java SystemServer init2 jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V"); if (methodId == NULL) { return UNKNOWN_ERROR; } env->CallStaticVoidMethod(clazz, methodId); ALOGI("System server: entering thread pool.
"
); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); ALOGI("System server: exiting thread pool.
"
); }

5) Java 레이어의 다양한 binder 서비스 시작
SystemServer의 init2 함수를 호출하면 새 스레드 android가 열립니다.server.ServerThread는 새로운 스레드에서 다양한 Java 층의 binder 서비스를 시작하고 서비스 관리자에 등록합니다. 이 서비스들은 대부분 새로운 스레드를 실행하기 때문에 시스템 서버의 하위 스레드입니다. 추가된 서비스 목록은 다음과 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
ServiceManager.addService("entropy", new EntropyMixer());
ServiceManager.addService(Context.POWER_SERVICE, power);
ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
ServiceManager.addService("telephony.registry", telephonyRegistry);
ServiceManager.addService(Context.SCHEDULING_POLICY_SERVICE,
ServiceManager.addService(Context.USER_SERVICE,UserManagerService.getInstance());
ServiceManager.addService(Context.ACCOUNT_SERVICE, accountManager);
ServiceManager.addService("battery", battery);
ServiceManager.addService("vibrator", vibrator);
ServiceManager.addService(Context.ALARM_SERVICE, alarm);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);
ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm);
ServiceManager.addService(Context.ACCESSIBILITY_SERVICE,new AccessibilityManagerService(context));
ServiceManager.addService("mount", mountService);
ServiceManager.addService("lock_settings", lockSettings);
ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy);
ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);
ServiceManager.addService(Context.CLIPBOARD_SERVICE,new ClipboardService(context));
ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);
ServiceManager.addService(Context.TEXT_SERVICES_MANAGER_SERVICE, tsms);
ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats);
ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
ServiceManager.addService(Context.WIFI_P2P_SERVICE, wifiP2p);
ServiceManager.addService(Context.WIFI_SERVICE, wifi);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
ServiceManager.addService(Context.NSD_SERVICE, serviceDiscovery);
ServiceManager.addService(Context.THROTTLE_SERVICE, throttle);
ServiceManager.addService("fm_receiver",new FmReceiverService(context));
ServiceManager.addService("fm_transmitter",new FmTransmitterService(context));
ServiceManager.addService(Context.UPDATE_LOCK_SERVICE,new UpdateLockService(context));
ServiceManager.addService(Context.PROFILE_SERVICE, profile);
ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification);
ServiceManager.addService(DeviceStorageMonitorService.SERVICE,
ServiceManager.addService(Context.LOCATION_SERVICE, location);
ServiceManager.addService(Context.COUNTRY_DETECTOR, countryDetector);
ServiceManager.addService(Context.SEARCH_SERVICE,new SearchManagerService(context));
ServiceManager.addService(Context.DROPBOX_SERVICE,new DropBoxManagerService(context, new File("/data/system/dropbox")));
ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);
ServiceManager.addService(Context.AUDIO_SERVICE, new AudioService(context));
ServiceManager.addService(Context.USB_SERVICE, usb);
ServiceManager.addService(Context.SERIAL_SERVICE, serial);
ServiceManager.addService(Context.BACKUP_SERVICE,new BackupManagerService(context));
ServiceManager.addService(Context.APPWIDGET_SERVICE, appWidget);
ServiceManager.addService("diskstats", new DiskStatsService(context));
ServiceManager.addService("samplingprofiler", new SamplingProfilerService(context));
ServiceManager.addService("commontime_management", commonTimeMgmtService);
ServiceManager.addService(DreamService.DREAM_SERVICE, dreamy);
ServiceManager.addService("assetredirection", new AssetRedirectionManagerService(context));
ServiceManager.addService("pieservice", pieService);

위에서 언급한 바와 같이 서비스 관리자 관리에 Activity Manager 서비스를 추가하는 것을 보지 못했습니다. 이 서비스의 추가 과정은 비교적 특별합니다.라인에서android.server.ServerThread에서 Activity Manager Service가 호출됩니다.setSystemProcess();setSystemProcess 함수의 코드는 다음과 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void setSystemProcess() {
//…
ActivityManagerService m = mSelf;            
ServiceManager.addService("activity", m, true);
ServiceManager.addService("meminfo", new MemBinder(m));
ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
ServiceManager.addService("dbinfo", new DbBinder(m));
if (MONITOR_CPU_USAGE) {
    ServiceManager.addService("cpuinfo", new CpuBinder(m));
}
ServiceManager.addService("permission", new PermissionController(m));
ApplicationInfo info =
    mSelf.mContext.getPackageManager().getApplicationInfo(
                "android", STOCK_PM_FLAGS);
mSystemThread.installSystemApplicationInfo(info);
//…
}

Activity Manager Service가 단일 모드를 사용하고 Service Manager를 호출하는 것을 볼 수 있습니다.addService(“activity”, m, true);Activity Manager Service를 서비스 관리자에게 맡기고,Activity Manager Service에는 MemBinder,GraphicsBinder,DbBinder와 같은 다른 binder 서비스도 추가했습니다.
Looper가 마지막으로 호출됩니다.loop();loop 순환에 들어가서 다른 프로그램과 통신하기를 기다립니다.
6) 시스템 인터페이스 시작
라인android.server.ServerThread에는 다음과 같은 코드가 있습니다.
1
2
3
4
5
6
7
8
ActivityManagerService.self().systemReady(new Runnable() {
    public void run() {
        Slog.i(TAG, "Making services ready");
 
        if (!headless) startSystemUi(contextF);
        //...
     }
}

startSystemUi는 다음과 같은 시스템 인터페이스를 시작하는 데 사용됩니다.
1
2
3
4
5
6
7
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.startServiceAsUser(intent, UserHandle.OWNER);
}

이렇게 하면com이 시작됩니다.android.시스템ui 응용 프로그램, 이 응용 프로그램은 PowerUI와 RingtonePlayer 두 개의 라인을 시작합니다.
7) Home 프로그램 시작
라인android.server.ServerThread에는 다음과 같은 코드가 있습니다.
1
2
3
4
5
6
7
//…
ActivityManagerService.self().systemReady(new Runnable() {
            public void run() {
                  //…
                }
    });
//…

ActivityManagerService.self().시스템Ready에는 다음과 같은 코드가 있습니다.
1
2
3
//…
mMainStack.resumeTopActivityLocked(null);
//…

ActivityStack. resumeTopActivityLocked()에는 다음과 같은 코드가 있습니다.
1
resumeTopActivityLocked(prev, null);

resumeTopActivityLocked의 구현에는 다음과 같은 코드가 있습니다.
1
2
3
4
5
6
7
8
9
10
//…
if (next == null) {
    // There are no more activities!  Let's just start up the
    // Launcher...
    if (mMainStack) {
        ActivityOptions.abort(options); 
        return mService.startHomeActivityLocked(mCurrentUser);
    }
}
//…

mService 유형은 Activity Manager Service, Activity Manager Service입니다.startHomeActivityLocked의 구현에는 다음과 같은 코드가 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
boolean startHomeActivityLocked(int userId) {
//…
Intent intent = new Intent(
    mTopAction,
    mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
//      Intent.CATEGORY_HOME,
//   Home           Activity,          Home  
if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
    intent.addCategory(Intent.CATEGORY_HOME);
}
ActivityInfo aInfo =
    resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
    intent.setComponent(new ComponentName(
            aInfo.applicationInfo.packageName, aInfo.name));
    // Don't do this if the home app is currently being
    // instrumented.
    aInfo = new ActivityInfo(aInfo);
    aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
    ProcessRecord app = getProcessRecordLocked(aInfo.processName,
            aInfo.applicationInfo.uid);
    if (app == null || app.instrumentationClass == null) {
        intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
        mMainStack.startActivityLocked(null, intent, null, aInfo,
                null, null, 0, 0, 0, 0, null, false, null);
    }
}
}

Intent를 사용하는 방법을 먼저 찾습니다.CATEGORY_HOME에서 선언한 Activity 구성 요소를 호출한 다음 mMainStack을 호출합니다.startActivityLocked에서 Activity를 시작합니다.
시스템 서버 시작 Home 프로그램 요약:
android.server.ServerThread->ActivityManagerService.self().systemReady->mMainStack.resumeTopActivityLocked->resumeTopActivityLocked-> mService.startHomeActivityLocked-> intent.addCategory(Intent.CATEGORY_HOME);mMainStack.startActivityLocked
총결산
커널을 초기화한 후, 실행하는 첫 번째 사용자 프로그램은 init입니다. init는 init를 시작합니다.rc에 명시된 여러 서비스는 안드로이드 공간과 관련된 서비스 관리자와zygote가 있고 서비스 관리자는 모든binder 서비스를 관리하며,zygote는 모든안드로이드 공간을 부화시키는 프로그램을 책임진다.zygote 서비스에 대응하는 프로그램은 app프로세스, 단지 일부 시작 매개 변수를 추가했기 때문에 자바 층의 ZygoteInit를 시작합니다. ZygoteInit에서는 System 서버를 시작합니다. System 서버는 두 단계로 나뉘는데 그것이 바로 로컬 init1과 자바 층의 init2입니다. init2에서는 라인 android를 시작합니다.server.ServerThread.android에 있습니다.server.ServerThread 스레드에서 자바 층의 각종binder 서비스, 예를 들어Activity Manager 서비스, Package Manager 서비스, Window Manager 서비스 등이 시작됩니다.그리고 Activity Manager 서비스의 시스템 Ready 방법을 호출합니다. 이 방법에서는 시스템 인터페이스와 Home 프로그램을 시작합니다.

좋은 웹페이지 즐겨찾기