浅谈 Android(安卓)体系结构
16lz
2021-01-25
很多没有写博客了,最近一段时间一直忙着工作,另外一方面也在忙着学点更深层次的东西及一些新的东西,如 Android Framework、PHP 等等。经过那么长时间的努力学习,终于初步了解了 Android Framework 及相关的东西,还有 PHP、ThinkPHP 等等。现在工作也不是很忙了,终于有时间写点总结了。其实我这篇文章写的挺杂的,也算不上是 Android 体系结构,但是实在想不到更好的名字了。而且很多东西都是一笔代过,因为其中的很多知识点,要详细讨论的话不是一两篇文章就能写的完的。这里我就先从整体上做个总结,后面我会就其中的很多问题进行总结讨论,敬请期待。
一、TheBinder
Binder 是 Android 中最重要的进程间通信手段,即最重要的 RPC/IPC 机制。但是 Binder 并不是 Android 的创意,早在 BeOS 出现的时期,Palm 就发明了 OpenBinder,并在他逝世的前几周发布其源代码。后来 George Hoffman和 Dianne Hackborn继续发展这个项目。当然,Android 也没有直接复制 OpenBinder 的所有实现,而是基于它的思想设计了自己的一套实现,就是 Binder 。想要了解更多关于 OpenBinder 的东西,请前往 http://www.angryredplanet.com/~hackbod/openbinder。 Android 的 Binder 和 Rosette Stone类似,Apps 的进程可以通过它与系统服务(进程)进行通信,Apps 之间的通信也可以通过 Binder 来进行。但是开发者不必知道 Binder 底层实现的细节,因为 Binder 向外提供了简单易用的接口,开发者只需要按需调用就可以完成进程间通信的功能。下图描述了 Binder 在系统中的位置。
二、System Services
System Services 是所有服务中最重要的一个,为什么它那么重要呢?因为系统中几乎所有的其它服务都是由它来启动的,只有启动了这些服务,app 才能调用它们,才能为用户提供相关的功能 。所有服务间的通信协作都依赖于 Binder,用户也可以通过 Binder 来创建自己的服务。除了那些需要硬件加速或者对性能要求较高的服务通常用 C/C++ 来写之外(如 sensor service 和 surface flinger),其它的大多数的服务都是用 Java 来写的。 System Services 启动起来后,它会加载其它的核心服务,并把这些服务都添加到 Service Manager 上。每个服务的启动都是耗时的,所以开机的时候,不必要的服务就不要启动,这样可以加快开机速度。如下是 SystemServer.java 的片断代码:
Android 系统的核心服务如下图
三、Service Manager Service Manager 就像是一个向导一样,它记录和管理着系统中所有的服务,它和 Binder 的协作是很紧密的。Service Manager 是系统中第一个启动起来的服务,它是由 Init 进程启动的。系统启动之初,启动的一些服务如下
Service Manager 源码如下
从源码中可以看出,当需要调用 ServiceManager 的功能时,要通过它的静态方法 getIServiceManager() 来获取它的 IServiceManager( sServiceManager) 对象,实际上对系统中的 Services 操作(如 getService()、addService()、checkService())是通过这个对象来完成的。
IServiceManager 类的源码如下
下图是 Android Framework 的整体结构图
四、Zygote
Zygote 进程是一个守护进程,它的任务是启动 Apps 进程。Init.rc 的启动项中就有 Zygote,在 Service Manager 启动后,系统就启动 Zygote 进程。实际上 Zygote 进程是由 app_process 进程来启动的。我们来看一下下面这个启动进程顺序列表就知道了
因为所有的 Applications 进程都是由 Zygote 进程来启动的,所以 Zygote 进程是所有 App 进程的父进程。当 app_process 进程启动 Zygote 进程的时候,它就会为其创建第一个 Dalvik VM 并调用 Zygote 进程的 main() 方法。Zygote 进程启动后,它就会加载所有必要的 Java 类及资源,启动 System Server,然后打开 /dev/socket/zygote 监听启动 application 的请求。System Server 进程是完全脱离其父进程的,它启动后就会初始化 System Services,然后启动 Activity Manager。 当 Zygote 通过/dev/socket/zygote接到 launch App(即启动 App)的请求的时候,它就会执行 fork() 方法,这个方法会在另外的地址空间中克隆当前进程。复制出来的进程中当然会和 Zygote 进程一样,拥有 Dalvik VM 实例,预加载了所有必要的 Java classes 及资源文件,这些东西都是 App 运行需要的。这样生成一个新的进程来运行 App 的效率是非常高的,而实际上,系统在这个 fork() 的实现上比我们想象的更加高效。我们都知道 Android 是运行在 Linux 上的,而 Linux 内核实现Copy On Write机制(写时复制),即在 fork() 一个进程的时候,克隆出来的子进程并不会真的全部去复制父进程的内存,当父进程的内存空间的内容没有发生变化的时候,子进程就和父进程共享这段空间。当父进程的某区域的内存因被写入而发生改变的时候,子进程才复制这一区域的内存空间。对于 Android 来说,Zygote 进程所加载的 Java classess 和公共资源是不可写的,所以实际 fork() 出来的子进程和 Zygote 进程共享了这些 classess 和资源。这样一方面使得从 Zygote 进程 fork() 出新进程的速度非常快,另一方面还大大节省了内存空间,所以 Android 每次启动一个新的 App 所需要的内存开销是很小的。 在进程系统移植的早期,如果你还不想启动 Zygote 进程,那么你在 init.rc 的适当位置加上 disabled 就行了,如下
Zygote 的 main() 方法
然后再来看一下 Zygote 是如何启动 System Server 的
五、Activity Manager
实际上手机桌面也是一个 Activity(即LauncherActivity),当用户在屏幕上点击一个 App 的图标的时候,会触发LauncherActivity 的 onClick() 方法。LauncherActivity 在监听到 App icon 的点击事件后,它就会通过 Binder 来获取 ActivityManager 向外提供的 handler,然后通过 handler 调用 ActivityManager 的 startActivity() 方法,即请求 ActivityManager 启动新的 App。前面我们有说到过,一个进程要与远程的进程通信时,它必须先通过系统的 Binder 来获取到远程进程向外提供的 handler 对象,然后才能通过这个 handler 调用远程进程的相关方法。当 Activity Manager 收到 startActivity() 请求的时候,它就调用 startViaZygote() 方法(通过 Zygote socket(/dev/socket/zygote) 调用)请求 Zygote 进行 fork() 操作,然后在 fork 出来的进程中加载相应的 App。
到这里,我们就可以来看看上面所讨论的各系统模块的结构是怎样的了,下图是整个 Android 系统启动的顺序图
实际上 Activity Manager 的任务远远不止上面说到的那些,它负责的任务是非常多的。这里我只再简单介绍一下它的另外一些任务(1)broadcasting intents(即广播 intent)。大家都应该知道 ANR,当发生 ANR 的时候,系统会弹出一个提示框,这个任务就是由 Activity Manager 来负责的。(2)当 Activity Manager 启动完成后,它就会向系统发出相关信息,告诉系统它已启动完成的事件。
一、TheBinder
Binder 是 Android 中最重要的进程间通信手段,即最重要的 RPC/IPC 机制。但是 Binder 并不是 Android 的创意,早在 BeOS 出现的时期,Palm 就发明了 OpenBinder,并在他逝世的前几周发布其源代码。后来 George Hoffman和 Dianne Hackborn继续发展这个项目。当然,Android 也没有直接复制 OpenBinder 的所有实现,而是基于它的思想设计了自己的一套实现,就是 Binder 。想要了解更多关于 OpenBinder 的东西,请前往 http://www.angryredplanet.com/~hackbod/openbinder。 Android 的 Binder 和 Rosette Stone类似,Apps 的进程可以通过它与系统服务(进程)进行通信,Apps 之间的通信也可以通过 Binder 来进行。但是开发者不必知道 Binder 底层实现的细节,因为 Binder 向外提供了简单易用的接口,开发者只需要按需调用就可以完成进程间通信的功能。下图描述了 Binder 在系统中的位置。
二、System Services
System Services 是所有服务中最重要的一个,为什么它那么重要呢?因为系统中几乎所有的其它服务都是由它来启动的,只有启动了这些服务,app 才能调用它们,才能为用户提供相关的功能 。所有服务间的通信协作都依赖于 Binder,用户也可以通过 Binder 来创建自己的服务。除了那些需要硬件加速或者对性能要求较高的服务通常用 C/C++ 来写之外(如 sensor service 和 surface flinger),其它的大多数的服务都是用 Java 来写的。 System Services 启动起来后,它会加载其它的核心服务,并把这些服务都添加到 Service Manager 上。每个服务的启动都是耗时的,所以开机的时候,不必要的服务就不要启动,这样可以加快开机速度。如下是 SystemServer.java 的片断代码:
class ServerThread extends Thread { private static final String TAG = "SystemServer"; private static finalString ENCRYPTING_STATE = "trigger_restart_min_framework"; private static final String ENCRYPTED_STATE = "1"; ContentResolver mContentResolver; void reportWtf(String msg, Throwable e) { Slog.w(TAG, "***********************************************"); Log.wtf(TAG, "BOOT FAILURE "+ msg, e); } @Override public void run() { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis()); Looper.prepareMainLooper(); android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); ... Slog.i(TAG, "Battery Service"); battery = newBatteryService(context, lights); ServiceManager.addService("battery", battery); Slog.i(TAG, "Vibrator Service"); vibrator = newVibratorService(context); ServiceManager.addService("vibrator", vibrator); ... Slog.i(TAG, "Window Manager"); wm = WindowManagerService.main(context, power, display, inputManager, uiHandler, wmHandler, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL, !firstBoot, onlyCore); ServiceManager.addService(Context.WINDOW_SERVICE, wm); ServiceManager.addService(Context.INPUT_SERVICE, inputManager); ActivityManagerService.self().setWindowManager(wm); inputManager.setWindowManagerCallbacks(wm.getInputMonitor()); inputManager.start(); display.setWindowManager(wm); display.setInputManager(inputManager); ...
Android 系统的核心服务如下图
三、Service Manager Service Manager 就像是一个向导一样,它记录和管理着系统中所有的服务,它和 Binder 的协作是很紧密的。Service Manager 是系统中第一个启动起来的服务,它是由 Init 进程启动的。系统启动之初,启动的一些服务如下
service servicemanager /system/bin/servicemanager class core user system group system criticalonrestart restart zygoteonrestart restart mediaonrestart restart surfaceflingeronrestart restart drm
Service Manager 源码如下
package android.os;import com.android.internal.os.BinderInternal;import android.util.Log;import java.util.HashMap;import java.util.Map;public final class ServiceManager { private static final String TAG = "ServiceManager"; private static IServiceManager sServiceManager; private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>(); private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject()); return sServiceManager; } /** * Returns a reference to a service with the given name. * * @param name the name of the service to get * @return a reference to the service, or <code>null</code> if the service doesn't exist */ public static IBinder getService(String name) { try { IBinder service = sCache.get(name); if (service != null) { return service; } else { return getIServiceManager().getService(name); } } catch (RemoteException e) { Log.e(TAG, "error in getService", e); } return null; } /** * Place a new @a service called @a name into the service * manager. * * @param name the name of the new service * @param service the service object */ public static void addService(String name, IBinder service) { try { getIServiceManager().addService(name, service, false); } catch (RemoteException e) { Log.e(TAG, "error in addService", e); } } /** * Place a new @a service called @a name into the service * manager. * * @param name the name of the new service * @param service the service object * @param allowIsolated set to true to allow isolated sandboxed processes * to access this service */ public static void addService(String name, IBinder service, boolean allowIsolated) { try { getIServiceManager().addService(name, service, allowIsolated); } catch (RemoteException e) { Log.e(TAG, "error in addService", e); } } /** * Retrieve an existing service called @a name from the * service manager. Non-blocking. */ public static IBinder checkService(String name) { try { IBinder service = sCache.get(name); if (service != null) { return service; } else { return getIServiceManager().checkService(name); } } catch (RemoteException e) { Log.e(TAG, "error in checkService", e); return null; } } /** * Return a list of all currently running services. */ public static String[] listServices() throws RemoteException { try { return getIServiceManager().listServices(); } catch (RemoteException e) { Log.e(TAG, "error in listServices", e); return null; } } /** * This is only intended to be called when the process is first being brought * up and bound by the activity manager. There is only one thread in the process * at that time, so no locking is done. * * @param cache the cache of service references * @hide */ public static void initServiceCache(Map<String, IBinder> cache) { if (sCache.size() != 0) { throw new IllegalStateException("setServiceCache may only be called once"); } sCache.putAll(cache); }}
从源码中可以看出,当需要调用 ServiceManager 的功能时,要通过它的静态方法 getIServiceManager() 来获取它的 IServiceManager( sServiceManager) 对象,实际上对系统中的 Services 操作(如 getService()、addService()、checkService())是通过这个对象来完成的。
IServiceManager 类的源码如下
public interface IServiceManager extends IInterface{/*** Retrieve an existing service called @a name from the* service manager. Blocks for a few seconds waiting for it to be* published if it does not already exist.*/public IBinder getService(String name) throws RemoteException;/*** Retrieve an existing service called @a name from the* service manager. Non-blocking.*/public IBinder checkService(String name) throws RemoteException;/*** Place a new @a service called @a name into the service* manager.*/public void addService(String name, IBinder service, boolean allowIsolated)throws RemoteException;/*** Return a list of all currently running services.*/public String[] listServices() throws RemoteException;/*** Assign a permission controller to the service manager. After set, this* interface is checked before any services are added.*/public void setPermissionController(IPermissionController controller)throws RemoteException;static final String descriptor = "android.os.IServiceManager";int GET_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;int CHECK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+1;int ADD_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+2;int LIST_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+3;int CHECK_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+4;int SET_PERMISSION_CONTROLLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+5;}
下图是 Android Framework 的整体结构图
四、Zygote
Zygote 进程是一个守护进程,它的任务是启动 Apps 进程。Init.rc 的启动项中就有 Zygote,在 Service Manager 启动后,系统就启动 Zygote 进程。实际上 Zygote 进程是由 app_process 进程来启动的。我们来看一下下面这个启动进程顺序列表就知道了
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-serverclass mainsocket zygote stream 660 root systemonrestart write /sys/android_power/request_state wakeonrestart write /sys/power/state ononrestart restart mediaonrestart restart netd
因为所有的 Applications 进程都是由 Zygote 进程来启动的,所以 Zygote 进程是所有 App 进程的父进程。当 app_process 进程启动 Zygote 进程的时候,它就会为其创建第一个 Dalvik VM 并调用 Zygote 进程的 main() 方法。Zygote 进程启动后,它就会加载所有必要的 Java 类及资源,启动 System Server,然后打开 /dev/socket/zygote 监听启动 application 的请求。System Server 进程是完全脱离其父进程的,它启动后就会初始化 System Services,然后启动 Activity Manager。 当 Zygote 通过/dev/socket/zygote接到 launch App(即启动 App)的请求的时候,它就会执行 fork() 方法,这个方法会在另外的地址空间中克隆当前进程。复制出来的进程中当然会和 Zygote 进程一样,拥有 Dalvik VM 实例,预加载了所有必要的 Java classes 及资源文件,这些东西都是 App 运行需要的。这样生成一个新的进程来运行 App 的效率是非常高的,而实际上,系统在这个 fork() 的实现上比我们想象的更加高效。我们都知道 Android 是运行在 Linux 上的,而 Linux 内核实现Copy On Write机制(写时复制),即在 fork() 一个进程的时候,克隆出来的子进程并不会真的全部去复制父进程的内存,当父进程的内存空间的内容没有发生变化的时候,子进程就和父进程共享这段空间。当父进程的某区域的内存因被写入而发生改变的时候,子进程才复制这一区域的内存空间。对于 Android 来说,Zygote 进程所加载的 Java classess 和公共资源是不可写的,所以实际 fork() 出来的子进程和 Zygote 进程共享了这些 classess 和资源。这样一方面使得从 Zygote 进程 fork() 出新进程的速度非常快,另一方面还大大节省了内存空间,所以 Android 每次启动一个新的 App 所需要的内存开销是很小的。 在进程系统移植的早期,如果你还不想启动 Zygote 进程,那么你在 init.rc 的适当位置加上 disabled 就行了,如下
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-serverclass mainsocket zygote stream 660 root systemonrestart write /sys/android_power/request_state wakeonrestart write /sys/power/state ononrestart restart mediaonrestart restart netddisabled
Zygote 的 main() 方法
public static void main(String argv[]) { try{ // Start profiling the zygote initialization. SamplingProfilerIntegration.start(); registerZygoteSocket(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); preload(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); // Finish profiling the zygote initialization. SamplingProfilerIntegration.writeZygoteSnapshot(); // Do an initial gc to clean up after startup gc(); // Disable tracing so that forked processes do not inherit stale tracing tags from // Zygote. Trace.setTracingEnabled(false); // If requested, start system server directly from Zygote if(argv.length != 2) { thrownewRuntimeException(argv[0] + USAGE_STRING); } if(argv[1].equals("start-system-server")) { startSystemServer(); } elseif(!argv[1].equals("")) { thrownewRuntimeException(argv[0] + USAGE_STRING); } Log.i(TAG, "Accepting command socket connections"); runSelectLoop(); closeServerSocket(); } catch(MethodAndArgsCaller caller) { caller.run(); } catch(RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throwex; }}
然后再来看一下 Zygote 是如何启动 System Server 的
/** * Prepare the arguments and fork for the system server process. */ privatestaticbooleanstartSystemServer() throwsMethodAndArgsCaller, 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,3006,3007", "--capabilities=130104352,130104352", "--runtime-init", "--nice-name=system_server", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; intpid; try{ parsedArgs = newZygoteConnection.Arguments(args); ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); /* Request to fork the system server process */ pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch(IllegalArgumentException ex) { thrownewRuntimeException(ex); } /* For child process */ if(pid == 0) { handleSystemServerProcess(parsedArgs); } returntrue; }
五、Activity Manager
实际上手机桌面也是一个 Activity(即LauncherActivity),当用户在屏幕上点击一个 App 的图标的时候,会触发LauncherActivity 的 onClick() 方法。LauncherActivity 在监听到 App icon 的点击事件后,它就会通过 Binder 来获取 ActivityManager 向外提供的 handler,然后通过 handler 调用 ActivityManager 的 startActivity() 方法,即请求 ActivityManager 启动新的 App。前面我们有说到过,一个进程要与远程的进程通信时,它必须先通过系统的 Binder 来获取到远程进程向外提供的 handler 对象,然后才能通过这个 handler 调用远程进程的相关方法。当 Activity Manager 收到 startActivity() 请求的时候,它就调用 startViaZygote() 方法(通过 Zygote socket(/dev/socket/zygote) 调用)请求 Zygote 进行 fork() 操作,然后在 fork 出来的进程中加载相应的 App。
到这里,我们就可以来看看上面所讨论的各系统模块的结构是怎样的了,下图是整个 Android 系统启动的顺序图
实际上 Activity Manager 的任务远远不止上面说到的那些,它负责的任务是非常多的。这里我只再简单介绍一下它的另外一些任务(1)broadcasting intents(即广播 intent)。大家都应该知道 ANR,当发生 ANR 的时候,系统会弹出一个提示框,这个任务就是由 Activity Manager 来负责的。(2)当 Activity Manager 启动完成后,它就会向系统发出相关信息,告诉系统它已启动完成的事件。
更多相关文章
- Nginx系列教程(六)| 手把手教你搭建 LNMP 架构并部署天空网络电影
- 一款霸榜 GitHub 的开源 Linux 资源监视器!
- 正确认识android内存管理原理
- android 系统调用大全
- Android中的4.0新布局控件:Space和GridLayout
- Android(安卓)即时通讯开发小结(一)
- 修改Android中hosts文件的步骤详解
- 学徒浅析Android——Android(安卓)8.0(O)后台服务的限制和变化
- 2016年Windows Phone将超越iPhone