AMS分析 -- 启动过程
一. AMS简介
AmS可以说是Android上层系统最核心的模块之一,其主要完成管理应用进程的生命周期以及进程的Activity,Service,Broadcast和Provider等。
从系统运行的角度看,AmS可以分为Client端和Service端:
Client端运行在各个app进程,app进程实现了具体的 Activity,Service等,告诉系统我有那些Activity,Service等,并且调用系统接口来完成显示;
Service端运行在 SystemServer进程,是系统级别的ActivityManagerService的具体实现,其响应Client端的系统调用请求,并且管理 Client端各个app进程的生命周期。
图1 AmS基本类图
关于AMS的代理模式可以参考 http://www.cnblogs.com/neo-java/p/7230042.html
如下图是AmS内部主要数据结构类图,看了code相信大家都会知道这些类都是干什么的,这儿只是总结一下。
图2 AmS内部主要数据结构类图
二. AMS启动过程
启动过程主要分为四部分:
1、创建出SystemServer进程的Android运行环境。
在这一部分,SystemServer进程主要创建出对应的ActivityThread和ContextImpl,构成Android运行环境。
AMS的后续工作依赖于SystemServer在此创建出的运行环境。
2、完成AMS的初始化和启动。
在这一部分,单纯地调用AMS的构造函数和start函数,完成AMS的一些初始化工作。
3、将SystemServer进程纳入到AMS的管理体系中。
AMS作为Java世界的进程管理和调度中心,要对所有Java进程一视同仁,因此SystemServer进程也必须被AMS管理。
在这个过程中,AMS加载了SystemServer中framework-res.apk的信息,并启动和注册了SettingsProvider.apk。
4、开始执行AMS启动完毕后才能进行的工作。
系统中的一些服务和进程,必须等待AMS完成启动后,才能展开后续工作。
在这一部分,AMS通过调用systemReady函数,通知系统中的其它服务和进程,可以进行对应工作了。
在这个过程中,值得我们关注的是:Home Activity被启动了。当该Activity被加载完成后,最终会触发ACTION_BOOT_COMPLETED广播。
下面分别讲解。
2.1 创建SystemServer进程的Android运行环境
2.1.1 我们已经知道了,zygote创建出的第一个java进程是SystemServer。
在SystemServer的run函数中,在启动AMS之前,调用了createSystemContext函数。
其代码如下所示:
1 .............
2 //SystemServer在启动任何服务之前,就调用了createSystemContext
3 //创建出的Context保存在mSystemContext中
4 // Initialize the system context.
5 createSystemContext();
6
7 // Create the system service manager.
8 //SystemServiceManager负责启动所有的系统服务,使用的Context就是mSystemContext
9 mSystemServiceManager = new SystemServiceManager(mSystemContext);
10 .............
我们跟进一下createSystemContext:
1 private void createSystemContext() {
2 //调用ActivityThread的systemMain函数,其中会创建出系统对应的Context对象
3 ActivityThread activityThread = ActivityThread.systemMain();
4
5 //取出上面函数创建的Context对象,保存在mSystemContext中
6 mSystemContext = activityThread.getSystemContext();
7
8 //设置系统主题
9 mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
10 }
以上函数中,最重要的就是ActivityThread.systemMain了,我们分析一下该函数。
2.1.2 ActivityThread.systemMain的代码如下
1 public static ActivityThread systemMain() {
2 // The system process on low-memory devices do not get to use hardware
3 // accelerated drawing, since this can add too much overhead to the
4 // process.
5 if (!ActivityManager.isHighEndGfx()) {
6 //虽然写着ActivityManager,但和AMS没有任何关系
7 //就是利用系统属性和配置信息进行判断
8
9 //关闭硬件渲染功能
10 ThreadedRenderer.disable(true);
11 } else {
12 ThreadedRenderer.enableForegroundTrimming();
13 }
14
15 //创建ActivityThread
16 ActivityThread thread = new ActivityThread();
17 //调用attach函数,参数为true
18 thread.attach(true);
19 return thread;
20 }
从上面的代码可以看出,ActivityThread的systemMain函数中,除了进行是否开启硬件渲染的判断外,主要作用是:
创建出ActivityThread对象,然后调用该对象的attach函数。
ActivityThread的构造函数比较简单:
1 ActivityThread() {
2 mResourcesManager = ResourcesManager.getInstance();
3 }
比较关键的是它的成员变量:
1 ..........
2 //定义了AMS与应用通信的接口
3 final ApplicationThread mAppThread = new ApplicationThread();
4
5 //拥有自己的looper,说明ActivityThread确实可以代表事件处理线程
6 final Looper mLooper = Looper.myLooper();
7
8 //H继承Handler,ActivityThread中大量事件处理依赖此Handler
9 final H mH = new H();
10
11 //用于保存该进程的ActivityRecord
12 final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>()
13 ..........
14 //用于保存进程中的Service
15 final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
16 ...........
17 //用于保存进程中的Application
18 final ArrayList<Application> mAllApplications = new ArrayList<Application>();
19 ...........
我们需要知道的是,ActivityThread是android Framework中一个非常重要的类,它代表一个应用进程的主线程,其职责就是调度及执行在该线程中运行的四大组件。
在Android中,应用进程指那些运行APK的进程,它们由zygote fork出来,其中运行着独立的dalvik虚拟机。
与应用进程相对的就是系统进程,例如zygote和SystemServer。
注意到此处的ActivityThread创建于SystemServer进程中。
由于SystemServer中也运行着一些系统APK,例如framework-res.apk、SettingsProvider.apk等,因此也可以认为SystemServer是一个特殊的应用进程。
对于上面提到的ActivityThread的成员变量,其用途基本上可以从名称中得知,这里仅说明一下ApplicationThread。
AMS负责管理和调度进程,因此AMS需要通过Binder机制和应用进程通信。
为此,Android提供了一个IApplicationThread接口,该接口定义了AMS和应用进程之间的交互函数。
如上图所示,ActivityThread作为应用进程的主线程代表,在其中持有ApplicationThread。ApplicationThread继承ApplicationThreadNative。
当AMS与应用进程通信时,ApplicationThread将作为Binder通信的服务端。
AMS与应用进程通信时,通过ApplicationThreadNative获取应用进程对应的ApplicationThreadProxy对象。
通过ApplicationThreadProxy对象,将调用信息通过Binder传递到ActivityThread中的ApplicationThread。
这个调用过程,今后还会遇到,碰到的时候再详细分析。
2.1.3 ActivityThread.attach
1 我们看看ActivityThread的attach函数:
2
3 //此时,我们传入的参数为true,表示该ActivityThread是系统进程的ActivityThread
4 private void attach(boolean system) {
5 //创建出的ActivityThread保存在类的静态变量sCurrentActivityThread
6 //AMS中的大量操作将会依赖于这个ActivityThread
7 sCurrentActivityThread = this;
8 mSystemThread = system;
9
10 if (!system) {
11 //应用进程的处理流程
12 ..........
13 } else {
14 //系统进程的处理流程,该情况只在SystemServer中处理
15
16 // Don't set application object here -- if the system crashes,
17 // we can't display an alert, we just want to die die die.
18 //设置DDMS(Dalvik Debug Monitor Service)中看到的SystemServer进程的名称为“system_process”
19 android.ddm.DdmHandleAppName.setAppName("system_process",
20 UserHandle.myUserId());
21
22 try {
23 //创建ActivityThread中的重要成员:Instrumentation、Application和Context
24 mInstrumentation = new Instrumentation();
25 ContextImpl context = ContextImpl.createAppContext(
26 this, getSystemContext().mPackageInfo);
27 mInitialApplication = context.mPackageInfo.makeApplication(true, null);
28 mInitialApplication.onCreate();
29 } catch (Exception e) {
30 throw new RuntimeException(
31 "Unable to instantiate Application():" + e.toString(), e);
32 }
33 }
34
35 //以下系统进程和非系统进程均会执行
36 ................
37 //注册Configuration变化的回调通知
38 ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
39 @Override
40 public void onConfigurationChanged(Configuration newConfig) {
41 //当系统配置发生变化时(例如系统语言发生变化),回调该接口
42 ...............
43 }
44 .............
45 });
46 }
从上面的代码可以看出,对于系统进程而言,ActivityThread的attach函数最重要的工作就是创建了Instrumentation、Application和Context。
Instrumentation
Instrumentation是Android中的一个工具类,当该类被启用时,它将优先于应用中其它的类被初始化。
此时,系统先创建它,再通过它创建其它组件。
此外,系统和应用组件之间的交互也将通过Instrumentation来传递。
因此,Instrumentation就能监控系统和组件的交互情况了。
实际使用时,可以创建该类的派生类进行相应的操作。
这个类在介绍启动Activity的过程时还会碰到,此处不作展开。
Context
Context是Android中的一个抽象类,用于维护应用运行环境的全局信息。
通过Context可以访问应用的资源和类,甚至进行系统级的操作,例如启动Activity、发送广播等。
ActivityThread的attach函数中,通过下面的代码创建出系统应用对应的Context:
1 .......
2 //ContextImpl是Context的实现类
3 ContextImpl context = ContextImpl.createAppContext(
4 this, getSystemContext().mPackageInfo);
5 .......
Application
Android中Application类用于保存应用的全局状态。
我们经常使用的Activity和Service均必须和具体的Application绑定在一起。
通过上图的继承关系,每个具体的Activity和Service均被加入到Android运行环境中。
在ActivityThread中,针对系统进程,通过下面的代码创建了初始的Application:
1 ..............
2 //调用LoadedApk的makeApplication函数
3 mInitialApplication = context.mPackageInfo.makeApplication(true, null);
4
5 //启动Application
6 mInitialApplication.onCreate();
7 ..............
我们看一下LoadedApk.makeApplication:
1 public Application makeApplication(boolean forceDefaultAppClass,
2 Instrumentation instrumentation) {
3 if (mApplication != null) {
4 return mApplication;
5 }
6 .............
7 Application app = null;
8
9 String appClass = mApplicationInfo.className;
10 if (forceDefaultAppClass || (appClass == null)) {
11 //系统进程中,对应下面的appClass
12 appClass = "android.app.Application";
13 }
14
15 try {
16 java.lang.ClassLoader cl = getClassLoader();
17 if (!mPackageName.equals("android")) {
18 ............
19 }
20
21 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
22 //实际上最后通过反射创建出Application
23 app = mActivityThread.mInstrumentation.newApplication(
24 cl, appClass, appContext);
25 appContext.setOuterContext(app);
26 } catch (Exception e) {
27 ..........
28 }
29
30 //一个进程支持多个Application,mAllApplications用于保存该进程中的Application对象
31 mActivityThread.mAllApplications.add(app);
32 mApplication = app;
33
34 ..............
35 }
从上面的代码不难看出,这部分主要是创建framework-res.apk对应的Application,然后调用它的onCreate函数,完成启动。
第一步的总结
至此,createSystemContext函数介绍完毕。
当SystemServer调用createSystemContext完毕后:
1、得到了一个ActivityThread对象,它代表当前进程 (此时为系统进程) 的主线程;
2、得到了一个Context对象,对于SystemServer而言,它包含的Application运行环境与framework-res.apk有关。
在继续分析AMS之前,我们先停下来思考一下,为什么在启动所有的服务前,SystemServer先要调用createSystemContext?
个人觉得《深入理解Android》对这个问题,解释的比较好,大致意思如下:
Android努力构筑了一个自己的运行环境。
在这个环境中,进程的概念被模糊化了。组件的运行及它们之间的交互均在该环境中实现。
createSystemContext函数就是为SystemServer进程搭建一个和应用进程一样的Android运行环境。
Android运行环境是构建在进程之上的,应用程序一般只和Android运行环境交互。
基于同样的道理,SystemServer进程希望它内部运行的应用,
也通过Android运行环境交互,因此才调用了createSystemContext函数。
创建Android运行环境时,
由于SystemServer的特殊性,调用了ActivityThread.systemMain函数;
对于普通的应用程序,将在自己的主线程中调用ActivityThread.main函数。
上图表示了进程的Android运行环境涉及的主要类之间的关系。
其中的核心类是ContextImpl,通过它可以得到ContentResolver、系统资源、应用信息等。
2.2 AMS的初始化和启动
创建完Android运行环境后,SystemServer调用startBootstrapServices,其中就创建并启动了AMS:
1 private void startBootstrapServices() {
2 Installer installer = mSystemServiceManager.startService(Installer.class);
3
4 // Activity manager runs the show.
5 //启动AMS,然后获取AMS保存到变量中
6 mActivityManagerService = mSystemServiceManager.startService(
7 ActivityManagerService.Lifecycle.class).getService();
8
9 //以下均是将变量存储到AMS中
10 mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
11 mActivityManagerService.setInstaller(installer);
12 ..........
13 }
注意到上面的代码并没有直接启动AMS,而是启动AMS的内部类Lifecycle。
这是迫不得已的做法,由于AMS并没有继承SystemService,因此不能通过SystemServiceManager的startService直接启动它。
可以这样理解:内部类Lifecycle对于AMS而言,就像一个适配器一样,让AMS能够像SystemService一样被SystemServiceManager通过反射的方式启动。
1 public static final class Lifecycle extends SystemService {
2 private final ActivityManagerService mService;
3
4 public Lifecycle(Context context) {
5 //Lifecycle由SystemServiceManager启动,传入的context就是SystemServer创建出的SystemContext
6 super(context);
7
8 //1、调用AMS的构造函数
9 mService = new ActivityManagerService(context);
10 }
11
12 @Override
13 public void onStart() {
14 //2、调用AMS的start函数
15 mService.start();
16 }
17
18 public ActivityManagerService getService() {
19 return mService;
20 }
21 }
接下来我们分别看看AMS的构造函数和start函数。
AMS的构造函数
1 public ActivityManagerService(Context systemContext) {
2 //AMS的运行上下文与SystemServer一致
3 mContext = systemContext;
4 ............
5 //取出的是ActivityThread的静态变量sCurrentActivityThread
6 //这意味着mSystemThread与SystemServer中的ActivityThread一致
7 mSystemThread = ActivityThread.currentActivityThread();
8 ............
9 mHandlerThread = new ServiceThread(TAG,
10 android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
11 mHandlerThread.start();
12 //处理AMS中消息的主力
13 mHandler = new MainHandler(mHandlerThread.getLooper());
14
15 //UiHandler对应于Android中的UiThread
16 mUiHandler = new UiHandler();
17
18 if (sKillHandler == null) {
19 sKillThread = new ServiceThread(TAG + ":kill",
20 android.os.Process.THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
21 sKillThread.start();
22 //用于接收消息,杀死进程
23 sKillHandler = new KillHandler(sKillThread.getLooper());
24 }
25
26 //创建两个BroadcastQueue,前台的超时时间为10s,后台的超时时间为60s
27 mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
28 "foreground", BROADCAST_FG_TIMEOUT, false);
29 mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
30 "background", BROADCAST_BG_TIMEOUT, true);
31 mBroadcastQueues[0] = mFgBroadcastQueue;
32 mBroadcastQueues[1] = mBgBroadcastQueue;
33
34 //创建变量,用于存储信息
35 mServices = new ActiveServices(this);
36 mProviderMap = new ProviderMap(this);
37 mAppErrors = new AppErrors(mContext, this);
38
39 //这一部分,分析BatteryStatsService时提过,进行BSS的初始化
40 File dataDir = Environment.getDataDirectory();
41 File systemDir = new File(dataDir, "system");
42 systemDir.mkdirs();
43 mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
44 mBatteryStatsService.getActiveStatistics().readLocked();
45 mBatteryStatsService.scheduleWriteToDisk();
46 mOnBattery = DEBUG_POWER ? true
47 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
48 mBatteryStatsService.getActiveStatistics().setCallback(this);
49
50 //创建ProcessStatsService,感觉用于记录进程运行时的统计信息,例如内存使用情况,写入/proc/stat文件
51 mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
52
53 //启动Android的权限检查服务,并注册对应的回调接口
54 mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler);
55 mAppOpsService.startWatchingMode(AppOpsManager.OP_RUN_IN_BACKGROUND, null,
56 new IAppOpsCallback.Stub() {
57 @Override public void opChanged(int op, int uid, String packageName) {
58 if (op == AppOpsManager.OP_RUN_IN_BACKGROUND && packageName != null) {
59 if (mAppOpsService.checkOperation(op, uid, packageName)
60 != AppOpsManager.MODE_ALLOWED) {
61 runInBackgroundDisabled(uid);
62 }
63 }
64 }
65 });
66
67 //用于定义ContentProvider访问指定Uri对应数据的权限,aosp中似乎没有这文件
68 mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));
69
70 //创建多用户管理器
71 mUserController = new UserController(this);
72
73 //获取OpenGL版本
74 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
75 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
76 ............
77 //资源配置信息置为默认值
78 mConfiguration.setToDefaults();
79 mConfiguration.setLocales(LocaleList.getDefault());
80 mConfigurationSeq = mConfiguration.seq = 1;
81
82 //感觉用于记录进程的CPU使用情况
83 mProcessCpuTracker.init();
84
85 //解析/data/system/packages-compat.xml文件,该文件用于存储那些需要考虑屏幕尺寸的APK的一些信息
86 //当APK所运行的设备不满足要求时,AMS会根据xml设置的参数以采用屏幕兼容的方式运行该APK
87 mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
88
89 //用于根据规则过滤一些Intent
90 mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
91
92 //以下的类,似乎用于管理和监控AMS维护的Activity Task信息
93 //ActivityStackSupervisor是AMS中用来管理Activity启动和调度的核心类
94 mStackSupervisor = new ActivityStackSupervisor(this);
95 mActivityStarter = new ActivityStarter(this, mStackSupervisor);
96 mRecentTasks = new RecentTasks(this, mStackSupervisor);
97
98 //创建线程用于统计进程的CPU使用情况
99 mProcessCpuThread = new Thread("CpuTracker") {
100 @Override
101 public void run() {
102 while (true) {
103 try {
104 try {
105 //计算更新信息的等待间隔
106 //同时利用wait等待计算出的间隔时间
107 ......
108 } catch(InterruptedException e) {
109 }
110 //更新CPU运行统计信息
111 updateCpuStatsNow();
112 } catch (Exception e) {
113 ..........
114 }
115 }
116 }
117 };
118
119 //加入Watchdog的监控
120 Watchdog.getInstance().addMonitor(this);
121 Watchdog.getInstance().addThread(mHandler);
122 }
从代码来看,AMS的构造函数还是相对比较简单的,主要工作就是初始化一些变量。
大多数变量的用途,从命名上基本可以推测出来,实际的使用情况必须结合具体的场景才能进一步了解。
AMS的start函数
1 private void start() {
2 //完成统计前的复位工作
3 Process.removeAllProcessGroups();
4
5 //开始监控进程的CPU使用情况
6 mProcessCpuThread.start();
7
8 //注册服务
9 mBatteryStatsService.publish(mContext);
10 mAppOpsService.publish(mContext);
11 Slog.d("AppOps", "AppOpsService published");
12 LocalServices.addService(ActivityManagerInternal.class, new LocalService());
13 }
AMS的start函数比较简单,主要是:
1、启动CPU监控线程。该线程将会开始统计不同进程使用CPU的情况。
2、发布一些服务,如BatteryStatsService、AppOpsService(权限管理相关)和本地实现的继承ActivityManagerInternal的服务。
至此AMS初始化相关的内容基本结束,从这些代码可以看出AMS涉及的类比较多,我们目前无法一一详述每个类的具体用途。
有机会遇到具体的场景时,再深入分析,此处有个大致印象即可。
2.3 将SystemServer纳入AMS的管理体系
2.3.1 setSystemProcess
AMS完成启动后,在SystemServer的startBootstrapServices函数中,
下一个与AMS相关的重要调用就是AMS.setSystemProcess了:
1 private void startBootstrapServices() {
2 ...........
3 // Set up the Application instance for the system process and get started.
4 mActivityManagerService.setSystemProcess();
5 ...........
6 }
我们跟进一下setSystemProcess函数:
1 public void setSystemProcess() {
2 try {
3 //以下是向ServiceManager注册几个服务
4
5 //AMS自己
6 ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
7
8 //注册进程统计信息的服务
9 ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
10
11 //用于打印内存信息用的
12 ServiceManager.addService("meminfo", new MemBinder(this));
13
14 //用于输出进程使用硬件渲染方面的信息
15 ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
16
17 //用于输出数据库相关的信息
18 ServiceManager.addService("dbinfo", new DbBinder(this));
19
20 //MONITOR_CPU_USAGE默认为true
21 if (MONITOR_CPU_USAGE) {
22 //用于输出进程的CPU使用情况
23 ServiceManager.addService("cpuinfo", new CpuBinder(this));
24 }
25
26 //注册权限管理服务
27 ServiceManager.addService("permission", new PermissionController(this));
28
29 //注册获取进程信息的服务
30 ServiceManager.addService("processinfo", new ProcessInfoService(this));
31
32 //1、向PKMS查询package名为“android”的应用的ApplicationInfo
33 ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
34 "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
35
36 //2、调用installSystemApplicationInfo
37 mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
38
39 //3、以下与AMS的进程管理有关
40 synchronized (this) {
41 ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
42 app.persistent = true;
43 app.pid = MY_PID;
44 app.maxAdj = ProcessList.SYSTEM_ADJ;
45 app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
46 synchronized (mPidsSelfLocked) {
47 mPidsSelfLocked.put(app.pid, app);
48 }
49 updateLruProcessLocked(app, false, null);
50 updateOomAdjLocked();
51 }
52 } catch (PackageManager.NameNotFoundException e) {
53 throw new RuntimeException(
54 "Unable to find android system package", e);
55 }
56 }
从上面的代码可以看出,AMS的setSystemProcess主要有四个主要的功能:
- 1、注册一些服务;
- 2、获取package名为“android”的应用的ApplicationInfo;
- 3、调用ActivityThread的installSystemApplicationInfo;
- 4、AMS进程管理相关的操作。
这四个主要的功能中,第一个比较简单,就是用Binder通信完成注册。
我们主要看看后三个功能对应的流程。
功能二,获取ApplicationInfo
如前所述,这部分相关的代码为:
1 ..........
2 ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
3 "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
4 ..........
我们先看看mContext.getPackageManager()的操作过程。
我们已经知道mContext的实现类是ContextImpl,其中对应的代码如下:
1 @Override
2 public PackageManager getPackageManager() {
3 if (mPackageManager != null) {
4 return mPackageManager;
5 }
6
7 //依赖于ActivityThread的getPackageManager函数
8 IPackageManager pm = ActivityThread.getPackageManager();
9 if (pm != null) {
10 // Doesn't matter if we make more than one instance.
11 //利用PKMS的代理对象,构建ApplicationPackageManager
12 //该类继承PackageManager
13 return (mPackageManager = new ApplicationPackageManager(this, pm));
14 }
15
16 return null;
17 }
跟进一下ActivityThread中的getPackageManager:
1 public static IPackageManager getPackageManager() {
2 if (sPackageManager != null) {
3 //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
4 return sPackageManager;
5 }
6 //依赖于Binder通信,获取到PKMS对应的BpBinder
7 IBinder b = ServiceManager.getService("package");
8 .....................
9 //得到PKMS对应的Binder服务代理
10 sPackageManager = IPackageManager.Stub.asInterface(b);
11 ....................
12 return sPackageManager;
13 }
从上面的代码我们可以看到,AMS获取PKMS用到了Binder通信。
实际上,PKMS由SystemServer创建,与AMS运行在同一个进程,AMS完全可以不经过Context、ActivityThread、Binder来获取PKMS。
根据一些资料,推断出原生代码这么做的原因是:
SystemServer进程中的服务,也使用Android运行环境来交互, 保留了组件之间交互接口的统一,为未来的系统保留了可扩展性。
得到PKMS的代理对象后,AMS调用PKMS的getApplicationInfo接口,获取package名为”android”的ApplicationInfo。
在AMS的setSystemProcess被调用前,PKMS已经启动了。
之前分析PKMS的博客中,我们已经提到,在PKMS的构造函数中,它将解析手机中所有的AndroidManifest.xml,然后形成各种数据结构以维护应用的信息。
getApplicationInfo就是通过package名,从对应的数据结构中,取出对应的应用信息,这部分内容主要就是查询数据结构的内容,不作深入分析。
功能三,installSystemApplicationInfo
得到framework-res.apk对应的ApplicationInfo后,需要将这部分ApplicationInfo保存到SystemServer对应的ActivityThread中。
这部分对应的代码为:
1 ..............
2 mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
3 ..............
AMS中的mSystemThread就是SystemServer中创建出的ActivityThread。
因此我们跟进一下ActivityThread的installSystemApplicationInfo函数:
1 public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
2 synchronized (this) {
3 //调用SystemServer中创建出的ContextImpl的installSystemApplicationInfo函数
4 getSystemContext().installSystemApplicationInfo(info, classLoader);
5
6 // give ourselves a default profiler
7 //创建一个Profiler对象,用于性能统计
8 mProfiler = new Profiler();
9 }
10 }
继续跟进ContextImpl的installSystemApplicationInfo函数:
1 void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
2 //前面已经提到过mPackageInfo的类型为LoadedApk
3 mPackageInfo.installSystemApplicationInfo(info, classLoader);
4 }
随着流程进入到LoadedApk:
1 /**
2 * Sets application info about the system package.
3 */
4 void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
5 //这个接口仅供系统进程调用,故这里断言一下
6 assert info.packageName.equals("android");
7
8 mApplicationInfo = info;
9 mClassLoader = classLoader;
10 }
至此,我们知道了installSystemApplicationInfo的真相就是:
将“android”对应的ApplicationInfo(即framework-res.apk对应的ApplicationInfo),
加入到SystemServer之前调用createSystemContext时,创建出的LoadedApk中。
毕竟SystemServer创建System Context时,PKMS并没有完成对手机中文件的解析,初始的LoadedApk中并没有持有有效的ApplicationInfo。
在此基础上,AMS下一步的工作就呼之欲出了。
由于framework-res.apk运行在SystemServer进程中,而AMS是专门用于进程管理和调度的,因此SystemServer进程也应该在AMS中有对应的管理结构。
于是,AMS的下一步工作就是将SystemServer的运行环境和一个进程管理结构对应起来,并进行统一的管理。
功能四, AMS进程管理
注意到上面的ContentProvider注册到AMS后,进行了notifyAll的操作。
举例来说:进程A需要查询一个数据库,需要通过进程B中的某个ContentProvider来实施。
如果B还未启动,那么AMS就需要先启动B。在这段时间内,A需要等待B启动并注册对应的ContentProvider。
B一旦完成ContentProvider的注册,就需要告知A退出等待以继续后续的查询工作。
setSystemProcess函数中,进程管理相关的代码为:
1 .............
2 synchronized (this) {
3 //创建进程管理对应的结构ProcessRecord
4 ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
5
6 //由于此时创建的是SystemServer进程对应ProcessRecord
7 //因此设定了一些特殊值
8 app.persistent = true;
9 app.pid = MY_PID;
10 app.maxAdj = ProcessList.SYSTEM_ADJ;
11
12 //将SystemServer对应的ApplicationThread保存到ProcessRecord中
13 app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
14
15 synchronized (mPidsSelfLocked) {
16 //按pid将ProcessRecord保存到mPidsSelfLocked中
17 mPidsSelfLocked.put(app.pid, app);
18 }
19
20 //updateLruProcessLocked来调整进程在mLruProcess列表的位置
21 //在这个列表中,最近活动过得进程总是位于前列,同时拥有Activity的进程位置总是前于只有Service的进程
22 updateLruProcessLocked(app, false, null);
23
24 //更新进程对应的oom_adj值(oom_adj将决定进程是否被kill掉)
25 updateOomAdjLocked();
26 }
27 ...............
这里我们仅分析一下创建进程管理结构的函数newProcessRecordLocked。
updateLruProcessLocked和updateOomAdjLocked函数比较复杂,等对AMS有更多的了解后,再做分析。
1 final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
2 boolean isolated, int isolatedUid) {
3 //进程的名称
4 String proc = customProcess != null ? customProcess : info.processName;
5
6 //将用于创建该进程的电源统计项
7 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8
9 final int userId = UserHandle.getUserId(info.uid);
10 //isolated此时为false
11 if (isolated) {
12 ..........
13 }
14 //创建出对应的存储结构
15 final ProcessRecord r = new ProcessRecord(stats, info, proc, uid);
16
17 //判断进程是否常驻
18 if (!mBooted && !mBooting
19 && userId == UserHandle.USER_SYSTEM
20 && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
21 r.persistent = true;
22 }
23
24 //按进程名将ProcessRecord存入到AMS的变量mProcessNames中
25 //该变量的类型为ProcessMap<ProcessRecord>
26 //结合前面的代码,我们知道AMS有两种方式可以取到ProcessRecord
27 //一是根据进程名,二是根据进程名称
28 addProcessNameLocked(r);
29 return r;
30 }
跟进一下ProcessRecord的构造函数:
1 ProcessRecord(BatteryStatsImpl _batteryStats, ApplicationInfo _info,
2 String _processName, int _uid) {
3 mBatteryStats = _batteryStats; //用于电量统计
4 info = _info; //保存ApplicationInfo
5 ...........
6 processName = _processName; //保存进程名
7
8 //一个进程能运行多个Package,pkgList用于保存package名
9 pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.versionCode));
10
11 //以下变量和进程调度优先级有关
12 maxAdj = ProcessList.UNKNOWN_ADJ;
13 curRawAdj = setRawAdj = ProcessList.INVALID_ADJ;
14 curAdj = setAdj = verifiedAdj = ProcessList.INVALID_ADJ;
15
16 //决定进程是否常驻内存(即使被杀掉,系统也会重启它)
17 persistent = false;
18
19 removed = false;
20 lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis();
21 }
总结
至此,我们对AMS的setSystemProcess函数分析告一段落。
从上面的代码可以看出,在这个函数中除了发布一些服务外,主要是:
将framework-res.apk的信息加入到SystemServer对应的LoadedApk中,同时构建SystemServer进程对应的ProcessRecord,
以将SystemServer进程纳入到AMS的管理中。
2.3.2 AMS的installSystemProviders
接下来AMS启动相关的操作,定义于SystemServer的startOtherServices函数中。
1 private void startOtherServices() {
2 ...........
3 mActivityManagerService.installSystemProviders();
4 ...........
5 }
我们跟进一下AMS的installSystemProviders函数:
1 public final void installSystemProviders() {
2 List<ProviderInfo> providers;
3 synchronized (this) {
4 //AMS根据进程名取出SystemServer对应的ProcessRecord
5 ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID);
6
7 //1、得到该ProcessRecord对应的ProviderInfo
8 providers = generateApplicationProvidersLocked(app);
9
10 //这里仅处理系统级的Provider
11 if (providers != null) {
12 for (int i=providers.size()-1; i>=0; i--) {
13 ProviderInfo pi = (ProviderInfo)providers.get(i);
14 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
15 Slog.w(TAG, "Not installing system proc provider " + pi.name
16 + ": not system .apk");
17 providers.remove(i);
18 }
19 }
20 }
21 }
22 }
23
24 if (providers != null) {
25 //2、安装Provider
26 mSystemThread.installSystemProviders(providers);
27 }
28
29 //创建ContentObserver监控Settings数据库中Secure、System和Global表的变化
30 mCoreSettingsObserver = new CoreSettingsObserver(this);
31
32 //创建ContentObserver监控Settings数据库中字体大小的变化
33 mFontScaleSettingObserver = new FontScaleSettingObserver();
34 }
从上面的代码可以看出,installSystemProviders主要是加载运行在SystemServer进程中的 ContentProvider,即SettingsProvider.apk (定义于frameworks/base/packages/SettingsProvider)。
上面有两个比较重要的函数:
1、generateApplicationProvidersLocked返回一个进程对应的ProviderInfo List。
2、ActivityThread可以看做是进程的Android运行环境,因此它的installSystemProviders表示为对应进程安装ContentProvider。
当SettingsProvider被加载到SystemServer进程中运行后,AMS就注册了两个ContentObserver监控SettingsProvider中的字段变化。
AMS监控的字段影响范围比较广,例如字体发生变化时,很多应用的显示界面都需要做出调整。
这也许就是让AMS来负责监控这些字段的原因。
2.4 AMS的systemReady
接下来,我们看看AMS启动的最后一部分:systemReady。
该函数在SystemServer中startOtherServices的最后被调用:
1 private void startOtherServices() {
2 ............
3 // We now tell the activity manager it is okay to run third party
4 // code. It will call back into us once it has gotten to the state
5 // where third party code can really run (but before it has actually
6 // started launching the initial applications), for us to complete our
7 // initialization.
8 mActivityManagerService.systemReady(new Runnable() {
9 ..............
10 });
11 }
我们分段看看AMS中systemReady的处理流程。
此处的分段并没有实际的意义,只是代码确实太长了,并且连续性不够,因此分开描述。
阶段一
1 public void systemReady(final Runnable goingCallback) {
2 synchronized(this) {
3 ..........
4 //这一部分主要是调用一些关键服务SystemReady相关的函数,
5 //进行一些等待AMS初始完,才能进行的工作
6
7 // Make sure we have the current profile info, since it is needed for security checks.
8 mUserController.onSystemReady();
9
10 mRecentTasks.onSystemReadyLocked();
11 mAppOpsService.systemReady();
12 mSystemReady = true;
13 }
14
15 ArrayList<ProcessRecord> procsToKill = null;
16 synchronized(mPidsSelfLocked) {
17 //mPidsSelfLocked中保存当前正在运行的所有进程的信息
18 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
19 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
20
21 //在AMS启动完成前,如果没有FLAG_PERSISTENT标志的进程已经启动了,
22 //就将这个进程加入到procsToKill中
23 if (!isAllowedWhileBooting(proc.info)){
24 if (procsToKill == null) {
25 procsToKill = new ArrayList<ProcessRecord>();
26 }
27 procsToKill.add(proc);
28 }
29 }
30 }
31
32 synchronized(this) {
33 //利用removeProcessLocked关闭procsToKill中的进程
34 if (procsToKill != null) {
35 for (int i=procsToKill.size()-1; i>=0; i--) {
36 ProcessRecord proc = procsToKill.get(i);
37 Slog.i(TAG, "Removing system update proc: " + proc);
38 removeProcessLocked(proc, true, false, "system update done");
39 }
40 }
41
42 // Now that we have cleaned up any update processes, we
43 // are ready to start launching real processes and know that
44 // we won't trample on them any more.
45
46 //至此系统准备完毕
47 mProcessesReady = true;
48 }
49 ............
50 //根据数据库和资源文件,获取一些配置参数
51 retrieveSettings();
52
53 final int currentUserId;
54 synchronized (this) {
55 //得到当前的用户ID
56 currentUserId = mUserController.getCurrentUserIdLocked();
57
58 //读取urigrants.xml,为其中定义的ContentProvider配置对指定Uri数据的访问/修改权限
59 //原生代码中,似乎没有urigrants.xml文件
60 //实际使用的grant-uri-permission是分布式定义的
61 readGrantedUriPermissionsLocked();
62 }
63 ..........
这一部分的工作主要是调用一些关键服务的初始化函数,
然后杀死那些没有FLAG_PERSISTENT却在AMS启动完成前已经存在的进程,
同时获取一些配置参数。
需要注意的是,由于只有Java进程才会向AMS注册,而一般的Native进程不会向AMS注册,因此此处杀死的进程是Java进程。
阶段二
1 //1、调用参数传入的runnable对象,SystemServer中有具体的定义
2 if (goingCallback != null) goingCallback.run();
3 ..............
4 //调用所有系统服务的onStartUser接口
5 mSystemServiceManager.startUser(currentUserId);
6 .............
7 synchronized (this) {
8 // Only start up encryption-aware persistent apps; once user is
9 // unlocked we'll come back around and start unaware apps
10 2、启动persistent为1的application所在的进程
11 startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
12
13 // Start up initial activity.
14 mBooting = true;
15
16 // Enable home activity for system user, so that the system can always boot
17 //当isSplitSystemUser返回true时,意味者system user和primary user是分离的
18 //这里应该是让system user也有启动home activity的权限吧
19 if (UserManager.isSplitSystemUser()) {
20 ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);
21 try {
22 AppGlobals.getPackageManager().setComponentEnabledSetting(cName,
23 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0,
24 UserHandle.USER_SYSTEM);
25 } catch (RemoteException e) {
26 throw e.rethrowAsRuntimeException();
27 }
28 }
29
30 //3、启动Home
31 startHomeActivityLocked(currentUserId, "systemReady");
32
33 try {
34 //发送消息,触发处理Uid错误的Application
35 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
36 ..........
37 mUiHandler.obtainMessage(SHOW_UID_ERROR_UI_MSG).sendToTarget();
38 }
39 } catch (RemoteException e) {
40 }
41 //发送一些广播信息
42 ............
43 //这里暂时先不深入,等进一步了解Activity的启动过程后,再做了解
44 mStackSupervisor.resumeFocusedStackTopActivityLocked();
45 ............
46 }
47 .............
从部分代码来看,主要的工作就是通知一些服务可以进行systemReady相关的工作,并进行启动服务或应用进程的工作。
2.4.1 调用回调接口
回调接口的具体内容定义与SystemServer.java中,其中会调用大量服务的onBootPhase函数、一些对象的systemReady函数或systemRunning函数。
此处,我们仅截取一些比较特别的内容:
1 public void run() {
2 ............
3 try {
4 //启动NativeCrashListener监听"/data/system/ndebugsocket"中的信息
5 //实际上是监听debuggerd传入的信息
6 mActivityManagerService.startObservingNativeCrashes();
7 } catch (Throwable e) {
8 reportWtf("observing native crashes", e);
9 }
10 ............
11 try {
12 //启动SystemUi
13 startSystemUi(context);
14 } catch (Throwable e) {
15 reportWtf("starting System UI", e);
16 }
17 ............
18 //这个以前分析过,启动Watchdog
19 Watchdog.getInstance().start();
20 ....................
21 }
回调接口中的内容较多,不做一一分析。
2.4.2 启动persistent标志的进程
我们看看startPersistentApps对应的内容:
1 private void startPersistentApps(int matchFlags) {
2 .............
3
4 synchronized (this) {
5 try {
6 //从PKMS中得到persistent为1的ApplicationInfo
7 final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
8 .getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
9 for (ApplicationInfo app : apps) {
10 //由于framework-res.apk已经由系统启动,所以此处不再启动它
11 if (!"android".equals(app.packageName)) {
12 //addAppLocked中将启动application所在进程
13 addAppLocked(app, false, null /* ABI override */);
14 }
15 }
16 } catch (RemoteException ex) {
17 }
18 }
19 }
跟进一下addAppLocked函数:
1 final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
2 String abiOverride) {
3 //以下是取出或构造出ApplicationInfo对应的ProcessRecord
4 ProcessRecord app;
5 if (!isolated) {
6 app = getProcessRecordLocked(info.processName, info.uid, true);
7 } else {
8 app = null;
9 }
10
11 if (app == null) {
12 app = newProcessRecordLocked(info, null, isolated, 0);
13 updateLruProcessLocked(app, false, null);
14 updateOomAdjLocked();
15 }
16 ...........
17 // This package really, really can not be stopped.
18 try {
19 //通过PKMS将package对应数据结构的StoppedState置为fasle
20 AppGlobals.getPackageManager().setPackageStoppedState(
21 info.packageName, false, UserHandle.getUserId(app.uid));
22 } catch (RemoteException e) {
23 } catch (IllegalArgumentException e) {
24 Slog.w(TAG, "Failed trying to unstop package "
25 + info.packageName + ": " + e);
26 }
27
28 if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
29 app.persistent = true;
30 app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
31 }
32
33 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
34 mPersistentStartingProcesses.add(app);
35 //启动应用所在进程,将发送消息给zygote,后者fork出进程
36 startProcessLocked(app, "added application", app.processName, abiOverride,
37 null /* entryPoint */, null /* entryPointArgs */);
38 }
39
40 return app;
41 }
这里最终将通过startProcessLocked函数,启动实际的应用进程。
正如之前分析zygote进程时,提过的一样,zygote中的server socket将接收消息,然后为应用fork出进程。
2.4.3 启动Home Activity
看看启动Home Activity对应的startHomeActivityLocked函数:
1 boolean startHomeActivityLocked(int userId, String reason) {
2 ..............
3 Intent intent = getHomeIntent();
4 //根据intent中携带的ComponentName,利用PKMS得到ActivityInfo
5 ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
6 if (aInfo != null) {
7 intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
8 aInfo = new ActivityInfo(aInfo);
9 aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
10
11 //此时home对应进程应该还没启动,app为null
12 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
13 aInfo.applicationInfo.uid, true);
14 if (app == null || app.instrumentationClass == null) {
15 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
16 //启动home
17 mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);
18 }
19 } else {
20 ..........
21 }
22 return true;
23 }
这里暂时先不深究Home Activity启动的具体过程。
从手头的资料来看,当Home Activity启动后,
ActivityStackSupervisor中的activityIdleInternalLocked函数将被调用(具体调用过程,还需要研究):
1 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
2 Configuration config) {
3 ...........
4 if (isFocusedStack(r.task.stack) || fromTimeout) {
5 booting = checkFinishBootingLocked();
6 }
7 ............
8 }
在checkFinishBootingLocked函数中:
1 private boolean checkFinishBootingLocked() {
2 //mService为AMS,mBooting变量在AMS回调SystemServer中定义的Runnable时,置为了true
3 final boolean booting = mService.mBooting;
4 boolean enableScreen = false;
5 mService.mBooting = false;
6 if (!mService.mBooted) {
7 mService.mBooted = true;
8 enableScreen = true;
9 }
10 if (booting || enableScreen) {、
11 //调用AMS的接口,发送消息
12 mService.postFinishBooting(booting, enableScreen);
13 }
14 return booting;
15 }
最终,AMS的finishBooting函数将被调用:
1 final void finishBooting() {
2 .........
3 //以下是注册广播接收器,用于处理需要重启的package
4 IntentFilter pkgFilter = new IntentFilter();
5 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
6 pkgFilter.addDataScheme("package");
7 mContext.registerReceiver(new BroadcastReceiver() {
8 @Override
9 public void onReceive(Context context, Intent intent) {
10 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
11 if (pkgs != null) {
12 for (String pkg : pkgs) {
13 synchronized (ActivityManagerService.this) {
14 if (forceStopPackageLocked(pkg, -1, false, false, false, false, false,
15 0, "query restart")) {
16 setResultCode(Activity.RESULT_OK);
17 return;
18 }
19 }
20 }
21 }
22 }
23 }, pkgFilter);
24 ...........
25 // Let system services know.
26 mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);
27
28 //以下是启动那些等待启动的进程
29 synchronized (this) {
30 // Ensure that any processes we had put on hold are now started
31 // up.
32 final int NP = mProcessesOnHold.size();
33 if (NP > 0) {
34 ArrayList<ProcessRecord> procs =
35 new ArrayList<ProcessRecord>(mProcessesOnHold);
36 for (int ip=0; ip<NP; ip++) {
37 .................
38 startProcessLocked(procs.get(ip), "on-hold", null);
39 }
40 }
41 }
42 }
43 ..............
44 if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
45 // Start looking for apps that are abusing wake locks.
46 //每15min检查一次系统各应用进程使用电量的情况,如果某个进程使用WakeLock的时间过长
47 //AMS将关闭该进程
48 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
49 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
50
51 // Tell anyone interested that we are done booting!
52 SystemProperties.set("sys.boot_completed", "1");
53 .................
54 //此处从代码来看发送的是ACTION_LOCKED_BOOT_COMPLETED广播
55 //在进行unlock相关的工作后,mUserController将调用finishUserUnlocking,发送SYSTEM_USER_UNLOCK_MSG消息给AMS
56 //AMS收到消息后,调用mUserController的finishUserUnlocked函数,经过相应的处理后,
57 //在mUserController的finishUserUnlockedCompleted中,最终将会发送ACTION_BOOT_COMPLETED广播
58 mUserController.sendBootCompletedLocked(.........);
59 .................
60 }
61 }
最终,当AMS启动Home Activity结束,并发送ACTION_BOOT_COMPLETED广播时,AMS的启动过程告一段落。
总结图
AMS分析 -- 启动过程的更多相关文章
- Symfony2源码分析——启动过程2
文章地址:http://www.hcoding.com/?p=46 上一篇分析Symfony2框架源码,探究Symfony2如何完成一个请求的前半部分,前半部分可以理解为Symfony2框架为处理请求 ...
- quartz2.x源码分析——启动过程
title: quartz2.x源码分析--启动过程 date: 2017-04-13 14:59:01 categories: quartz tags: [quartz, 源码分析] --- 先简单 ...
- mysql源码分析-启动过程
mysql源码分析-启动过程 概要 # sql/mysqld.cc, 不包含psi的初始化过程 mysqld_main: // 加载my.cnf和my.cnf.d,还有命令行参数 if (load_d ...
- Nginx学习笔记(六) 源码分析&启动过程
Nginx的启动过程 主要介绍Nginx的启动过程,可以在/core/nginx.c中找到Nginx的主函数main(),那么就从这里开始分析Nginx的启动过程. 涉及到的基本函数 源码: /* * ...
- Symfony2源码分析——启动过程1
本文通过阅读分析Symfony2的源码,了解Symfony2启动过程中完成哪些工作,从阅读源码了解Symfony2框架. Symfony2的核心本质是把Request转换成Response的一个过程. ...
- Spring Boot源码分析-启动过程
Spring Boot作为目前最流行的Java开发框架,秉承"约定优于配置"原则,大大简化了Spring MVC繁琐的XML文件配置,基本实现零配置启动项目. 本文基于Spring ...
- Tomcat分析-启动过程
Server是Tomcat最顶层的容器 Service用于提供服务 Connector用于处理连接相关的事情,并提供Socket与request和response的转换 Container用于封装和管 ...
- STM32启动过程--启动文件--分析
一.概述 1.说明 每一款芯片的启动文件都值得去研究,因为它可是你的程序跑的最初一段路,不可以不知道.通过了解启动文件,我们可以体会到处理器的架构.指令集.中断向量安排等内容,是非常值得玩味的. ST ...
- mybatis源码分析:启动过程
mybatis在开发中作为一个ORM框架使用的比较多,所谓ORM指的是Object Relation Mapping,直译过来就是对象关系映射,这个映射指的是java中的对象和数据库中的记录的映射,也 ...
随机推荐
- sql数据处理
安装pymysql 读取数据库数据进行pandas操作,并用seaborn和matplotlib进行画图
- go RWMutex 的实现
Overview go 里面的 rwlock 是 write preferred 的,可以避免写锁饥饿. 读锁和写锁按照先来后到的规则持有锁,一旦有协程持有了写锁,后面的协程只能在写锁被释放后才能得到 ...
- Kibana-CentOS7单机安装测试
一.是什么 Kibana 是为 Elasticsearch设计的开源分析和可视化平台.你可以使用 Kibana 来搜索,查看存储在 Elasticsearch 索引中的数据并与之交互.你可以很容易实现 ...
- 【AI】AI学习方向
df
- OSPF协议原理及配置5-LSA分析
OSPF协议原理及配置5-LSA分析 前面,已经介绍了邻接关系的建立和LSDB的同步.通过同步过程的介绍,我们可以了解LSDB的同步是通过交互LSA实现的. 不同角色的路由器发出的LSA的内容是不 ...
- 《手把手教你》系列基础篇(七十六)-java+ selenium自动化测试-框架设计基础-TestNG实现DDT - 下篇(详解教程)
1.简介 今天这一篇宏哥主要是结合实际工作中将遇到的测试场景和前边两篇学习的知识结合起来给大家讲解和分享一下,希望以后大家在以后遇到其他的测试场景也可以将自己的所学的知识应用到测试场景中. 2.测试场 ...
- Anaconda Navigator卡logo打不开闪退问题处理方案-更换阿里云镜像源
镜像下载.域名解析.时间同步请点击阿里云开源镜像站 一.打开软件卡logo,点击图标后闪退 最近有同事使用anaconda时出现了卡logo,显示loading applications,点击图标时发 ...
- 基于Kali的一次DDos攻击实践
镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 一.什么是DDos攻击 DDOS(Distributed Denial of Service),即分布式拒绝服务,是一种针对于网络服务的攻击行为. ...
- Grafana镜像在阿里云镜像站首发上线
阿里云镜像站体验官招募中, 在各大社区平台分享相关内容累计积分就可赢得Airpods耳机和移动硬盘等奖励,银牌体验官的奖励人数不设限哦.立即参与 简介 Grafana是一个跨平台的开源的度量分析和可视 ...
- 4.监控Redis--单节点
prometheus监控redis需要用到redis_exporter. redis_exporter 项目地址:https://github.com/oliver006/redis_exporter ...