Framework中的连接管理机制(原)

2024-05-26 10:18

本文主要是介绍Framework中的连接管理机制(原),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上一节《 Wifi服务框架介绍》介绍了WIFI的大致框架,本文主要介绍连接管理中的几个重要角色,包括: NetworkInfo、NetworkAgent、ConnectivityService、ConnectivityManager等。
        为了便于讨论,本文选取一个具体问题展开分析,那就是: 当当前的网络连接变为不可用时,系统如何自动切换其他可用的网络连接的

        我们知道,当手机在使用移动数据上网时,如果进入WIFI环境,手机将会自动连上WIFI使用数据,而当WIFI失去覆盖或者关闭WIFI时,手机又会自动连上移动数据,那么这个机制是如何实现的呢?本文从WIFI框架触发,跟踪当WIFI被disconnect时,如何切换为数据网络。


一、WifiStateMachine更新状态


        WifiStateMachine利用setNetworkDetailedState()方法更新WIFI状态, 如果WIFI网络被断开后,就会将DISCONNECTED的状态传递给setNetworkDetailedState(),此时WifiStateMachine就会把状态先同步到NetworkInfo,然后再更新到NetworkAgent对象:
        private boolean setNetworkDetailedState(NetworkInfo.DetailedState state) {boolean hidden = false;if (state != mNetworkInfo.getDetailedState()) {//更新NetworkInfo的状态mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());if (mNetworkAgent != null) {//将最新状态发送到NetworkAgentmNetworkAgent.sendNetworkInfo(mNetworkInfo);}sendNetworkStateChangeBroadcast(null);return true;}return false;}

        到这里就不得不介绍一下NetworkInfo和NetworkAgent了。


二、NetworkInfo介绍


        NetworkInfo用于标识一个网络连接的状态、类型等属性的,从其提供的public方法我们就能看出其提供了一个网络连接最基本的信息:
        @NetworkInfo.java//获取网络类型,TYPE_MOBILE/TYPE_WIFI/TYPE_MOBILE_MMS等public int getType() {}//获取网络类型名称public String getTypeName() {}//网络是否是CONNECTED或者CONNECTING状态public boolean isConnectedOrConnecting() {}//网络是否是CONNECTED状态public boolean isConnected() {}//设置网络是否可用public void setIsAvailable(boolean isAvailable) {}//判断网络是否可用public boolean isAvailable() {}//是否漫游状态public boolean isRoaming() {}//设置漫游状态public void setRoaming(boolean isRoaming) {}//获取网络的state、mReason等信息public DetailedState getDetailedState() {}
        应用程序可以 通过ConnectivityManager的getNetworkInfo()方法获取到该对象,并通过该对象查询当前的网络状态,比如可以这样获取当前是否有网络连接:
        private boolean isNetworkConnected() {final ConnectivityManager connectivity = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);if (connectivity == null) {return false;}final NetworkInfo info = connectivity.getActiveNetworkInfo();return info != null && info.isConnected();}
        上面是应用读取NetworkInfo的方法,那么当网络变化时,就应该由WIFI或者DATA去更新当前的NetworkInfo,而WifiStateMachine在setNetworkDetailedState中做的就是把当前的网络状态更新到NetworkInfo,即:
        mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());

        更新完NetworkInfo之后,需要将其更新到ConnectivityManager才可被其他应用读取到,那么如何将其更新到ConnectivityManager呢?这就需要NetworkAgent来完成了。


三、NetworkAgent介绍


        NetworkAgent的作用可以从其官方描述中略知一二:
        "A Utility class for handling for communicating between bearer-specific code and ConnectivityService."
        这句话描述了NetworkAgent的作用: 他是某个网络连接与ConnectivityService之间的通讯的工具
        接下来我们通过代码来认识一下他究竟如何在网络连接与ConnectivityService之间进行通讯。
        先来看一下这个类的定义:
        public abstract class NetworkAgent extends Handler {}
        我们发现,这是一个Handler的子类,并且他是一个抽象类(abstract), 需要在子类中被实例化
        然后来看其构造方法:
        public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score) {this(looper, context, logTag, ni, nc, lp, score, null);}public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {super(looper);mContext = context;if (ni == null || nc == null || lp == null) {throw new IllegalArgumentException();}//获取ConnectivityManager对象,并向其注册自己ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( Context.CONNECTIVITY_SERVICE);cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);}
        我们看到其构造方法里面主要做了一件事情,获取ConnectivityManager对象,并通过registerNetworkAgent方式注册当前的NetworkAgent。

        接下来我们插入两节来分别介绍另外两个对象:ConnectivityManager和ConnectivityService,然后再回头来看这里的registerNetworkAgent()方法。


四、ConnectivityService介绍


        ConnectivityService是负责连接管理的大总管,他以Service的形式在系统初始化时就被创建:
        @SystemServer.javapublic static final String CONNECTIVITY_SERVICE = "connectivity";private void startOtherServices() {try {//创建ConnectivityServiceconnectivity = new ConnectivityService(context, networkManagement, networkStats, networkPolicy);//注册的name为"connectivity"ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);networkStats.bindConnectivityManager(connectivity);networkPolicy.bindConnectivityManager(connectivity);} catch (Throwable e) {reportWtf("starting Connectivity Service", e);}}

        从上面知道,该Service在SystemServer中的name为"Connectivity"。知道了这一点就够了,至于ConnectivityService本身我们暂且不去关注。


五、ConnectivityManager介绍


        与其他众多Manager一样,ConnectivityManager也是在ContextImpl中被创建的:
        @ContextImpl.javaregisterService(CONNECTIVITY_SERVICE, new ServiceFetcher() {public Object createService(ContextImpl ctx) {IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);return new ConnectivityManager(IConnectivityManager.Stub.asInterface(b));}});
        从这里我们看到,创建ConnectivityManager时传递了一个name为CONNECTIVITY_SERVICE的服务对象,这个对象就是刚才我们向SystemServer注册的ConnectivityService。然后来看ConnectivityManager的构造方法:
        @ConnectivityManager.javapublic ConnectivityManager(IConnectivityManager service) {mService = checkNotNull(service, "missing IConnectivityManager");}
        这里我们看到,构造方法里面只是将参数ConnectivityService传递给mService对象就完了。

        好了,ConnectivityManager我们了解这么多就够了。下面继续我们NetworkAgent的初始化流程。


六、继续NetworkAgent初始化流程


        现在我们继续NetworkAgent的初始化流程,这个流程中包含AsyncChannel的使用,不了解的同学可以在这里了解其使用方法和机制。


6.1、NetworkAgent向ConnectivityService注册过程


        前面我们说道,NetworkAgent初始化的时候只做了一个事情,就是向ConnectivityManager注册自己,现在我们继续看该注册过程:
        public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {super(looper);mContext = context;if (ni == null || nc == null || lp == null) {throw new IllegalArgumentException();}//获取ConnectivityManager对象,并向其注册自己ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( Context.CONNECTIVITY_SERVICE);cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);}
        在调用注册方法时传递了六个参数,其中有三个比较重要的参数,都是从构造方法的参数中获取并重新new出来的,其分别是:
        1、new Messenger(this)
        2、new NetworkAgent(ni)
        3、new NetworkCapabilities(nc)

        需要注意的是,这里new出来的三个对象的来源,都应该是NetworkAgent子类被初始化时传递给构造方法的。
        然后我们继续来看ConnectivityManager的registerNetworkAgent()方法。
        @ConnectivityManager.javapublic void registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, NetworkCapabilities nc, int score, NetworkMisc misc) {try {mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc);} catch (RemoteException e) { }}
        经过前面的介绍我们现在知道,这里的mService就是ConnectivityService,继续来看接下来的流程:
        @ConnectivityService.javapublic void registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int currentScore, NetworkMisc networkMisc) {//权限检查enforceConnectivityInternalPermission();//创建NetworkAgentInfo对象NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),new NetworkInfo(networkInfo), new LinkProperties(linkProperties),new NetworkCapabilities(networkCapabilities), currentScore, mContext, mTrackerHandler,new NetworkMisc(networkMisc));synchronized (this) {nai.networkMonitor.systemReady = mSystemReady;}//向自己Handler发送EVENT_REGISTER_NETWORK_AGENT消息mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));}
        在ConnectivityService的registerNetworkAgent中做了两件事情:
        1、创建NetworkAgentInfo对象;
        2、向Handler发送EVENT_REGISTER_NETWORK_AGENT消息;

        其中创建NetworkAgentInfo时,传递了九个参数,我们只关注其中三个,分别是:
        1、messenger ----这个参数是registerNetworkAgent的参数,从NetworkAgent传递过来
        2、new AsyncChannel()   ----这是现在创建的新对象
        3、new NetworkCapabilities(NetworkCapabilities) ----这也是用NetworkAgent传递过来的参数创建的对象

        然后我们来看ConnectivityService对EVENT_REGISTER_NETWORK_AGENT的处理:
        private class InternalHandler extends Handler {public void handleMessage(Message msg) {NetworkInfo info;switch (msg.what) {case EVENT_REGISTER_NETWORK_AGENT: {handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);break;}}}}
        继续看handleRegisterNetworkAgent():
        private void handleRegisterNetworkAgent(NetworkAgentInfo na) {mNetworkAgentInfos.put(na.messenger, na);assignNextNetId(na);//向NetworkAgentInfo的asyncChannel对象发起连接请求na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);NetworkInfo networkInfo = na.networkInfo;na.networkInfo = null;updateNetworkInfo(na, networkInfo);}
        这里我们看到,ConnectivityService向NetworkAgentInfo的asyncChannel对象发起connect请求,并且 该AsyncChannel的srcHandler是mTrackerHandler,而dstMessenger对象是NetworkAgentInfo的messenger,那么这里的NetworkAgentInfo是哪里来的呢?
        其实不难看出,这里的NetworkAgentInfo就是在registerNetworkAgent()中创建的, 而dstMessenger自然就是NetworkAgent调用registerNetworkAgent()时传递进来的。

        接下来,ConnectivityService将会利用获取到的NetworkAgent对象创建AsyncChannel双向通道。


6.2、ConnectivityService向NetworkAgent申请双向AsyncChannel过程


        我们记得,NetworkAgent当初是这样调用registerNetworkAgent()的:
        @NetworkAgent.javapublic NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( Context.CONNECTIVITY_SERVICE);cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);}
        因此 ConnectivityService中的dstMessenger其实就是NetworkAgent,准确来说应该是NetworkAgent的子类
        从AsyncChannel的机制我们知道,当利用其发起connect请求时,其将会触发单向连接过程,此时srcHandler(也就是mTrackerHandler)将会收到CMD_CHANNEL_HALF_CONNECTED的消息:
        private class NetworkStateTrackerHandler extends Handler {public void handleMessage(Message msg) {NetworkInfo info;switch (msg.what) {case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {handleAsyncChannelHalfConnect(msg);break;}}}}
        继续来看handleAsyncChannelHalfConnect:
        private void handleAsyncChannelHalfConnect(Message msg) {AsyncChannel ac = (AsyncChannel) msg.obj;if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {} else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {//向AsyncChannel发送消息mNetworkAgentInfos.get(msg.replyTo).asyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);} else {}}}
        这里我们看到,此刻ConnectivityService通过AsyncChannel向dstMessenger发送了CMD_CHANNEL_FULL_CONNECTION的消息,从AsyncChannel的机制我们想到,这个消息应该是在向NetworkAgent申请 双向通道
        那么NetworkAgent究竟会如何处理该请求呢?
        由于前面我们介绍过,NetworkAgent是抽象类,他需要在子类中被实例化,那么 对于WIFI环境来说,他的子类就是在WifiStateMachine中的WifiNetworkAgent对象
        现在我们再回到WifiStateMachine中,我们可以看到,在L2ConnectedState状态机被初始化时将会创建WifiNetworkAgent对象:
        class L2ConnectedState extends State {@Overridepublic void enter() {mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext, "WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter, mLinkProperties, 60);}} 
        然后来看该WifiNetworkAgent的定义:
        @WifiStateMachine.javaprivate class WifiNetworkAgent extends NetworkAgent {public WifiNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score) {super(l, c, TAG, ni, nc, lp, score);}protected void unwanted() {if (this != mNetworkAgent) return;unwantedNetwork(network_status_unwanted_disconnect);}protected void networkStatus(int status) {if (status == NetworkAgent.INVALID_NETWORK) {unwantedNetwork(network_status_unwanted_disable_autojoin);}}}
        从这里我们看到,WifiNetworkAgent并没有覆盖父类NetworkAgent中的handleMessage方法,那么也就是说,当ConnectivityService向WifiNetworkAgent发送AsyncChannel请求时,该请求应该在NetworkAgent中被处理,也就是这里:
        @NetworkAgent.javapublic void handleMessage(Message msg) {switch (msg.what) {case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {if (mAsyncChannel != null) {} else {//创建WifiNetworkAgent中的AsyncChannel对象AsyncChannel ac = new AsyncChannel();//完成双向通道连接动作ac.connected(null, this, msg.replyTo);ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, AsyncChannel.STATUS_SUCCESSFUL);synchronized (mPreConnectedQueue) {mAsyncChannel = ac;for (Message m : mPreConnectedQueue) {ac.sendMessage(m);}mPreConnectedQueue.clear();}}break;}}}
        从这个handleMessage()中我们看到,对于ConnectivityService发起的CMD_CHANNEL_FULLY_CONNECTED申请,WifiNetworkAgent创建了自己的AsyncChannel对象并连接上然后发送了STATUS_SUCCESSFUL的消息。
        经过以上过程, 在ConnectivityService与WifiNetworkAgent之间就建立了双向的AsyncChannel通道
        以下是整个WifiNetworkAgent的初始化流程:

        


七、WIFI的断开过程


        现在我们再回到WifiStateMachine对当前WIFI状态的更新过程中。当WIFI断开时,WifiStateMachine将会通过setNetworkDetailedState()更新当前WIFI的NetworkInfo对象,并将其传递给WifiNetworkAgent:
        private boolean setNetworkDetailedState(NetworkInfo.DetailedState state) {boolean hidden = false;if (state != mNetworkInfo.getDetailedState()) {//更新NetworkInfo的状态mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());if (mNetworkAgent != null) {//将最新状态发送到NetworkAgentmNetworkAgent.sendNetworkInfo(mNetworkInfo);}sendNetworkStateChangeBroadcast(null);return true;}return false;}
        然后我们来看NetworkAgent如何将最新的networkInfo传递到ConnectivityService中去:
        @NetworkAgent.javapublic void sendNetworkInfo(NetworkInfo networkInfo) {queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));}
        继续:
        private void queueOrSendMessage(int what, Object obj) {synchronized (mPreConnectedQueue) {if (mAsyncChannel != null) {//通过AsyncChannel发送请求mAsyncChannel.sendMessage(what, obj);} else {Message msg = Message.obtain();msg.what = what;msg.obj = obj;mPreConnectedQueue.add(msg);}}}
        到这里我们发现,NetworkAgent将最新的NetworkInfo作为一个Object放入一个EVENT_NETWORK_INFO_CHANGED的消息中,然后通过AsyncChannel发送出去。那么这个消息发送到哪里了呢?
        此时我们应该能够想到,当初是ConnectivityService与WifiNetworkAgent创建了双向的AsyncChannel通道,那么 此时的消息当然就会发送给ConnectivityService了,并且该消息将会在其NetworkStateTrackerHandler中被处理:
        @ConnectivityService.javaprivate class NetworkStateTrackerHandler extends Handler {public void handleMessage(Message msg) {NetworkInfo info;switch (msg.what) {case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {//拿到消息中最新的NetworkInfo信息NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);if (nai == null) {loge("EVENT_NETWORK_INFO_CHANGED from unknown NetworkAgent");break;}info = (NetworkInfo) msg.obj;//通过updateNetworkInfo来进行更新updateNetworkInfo(nai, info);break;}}}}
        然后我们继续来看updateNetworkInfo()的操作:
        private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {NetworkInfo.State state = newInfo.getState();NetworkInfo oldInfo = null;synchronized (networkAgent) {oldInfo = networkAgent.networkInfo;//将最新的networkInfo更新到ConnectivityServicenetworkAgent.networkInfo = newInfo;}if (state == NetworkInfo.State.CONNECTED && !networkAgent.created) {} else if (state == NetworkInfo.State.DISCONNECTED || state == NetworkInfo.State.SUSPENDED) {//断开WIFI的NetworkAgent中的AsyncChannelnetworkAgent.asyncChannel.disconnect();}}
        在updateNetworkInfo()中,ConnectivityService将最新的NetworkInfo保存在networkAgent中,等待其他应用来获取。然后就向NetworkAgent的AsyncChannel发起disconnect()的请求,该请求将会在ConnectivityService中收到CMD_CHANNEL_DISCONNECTED的回应:
        private class NetworkStateTrackerHandler extends Handler {public void handleMessage(Message msg) {NetworkInfo info;switch (msg.what) {case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {handleAsyncChannelDisconnected(msg);break;}}}}
        继续来看handleAsyncChannelDisconnected():
        private void handleAsyncChannelDisconnected(Message msg) {NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);if (nai != null) {final ArrayList<NetworkAgentInfo> toActivate = new ArrayList<NetworkAgentInfo>();for (int i = 0; i < nai.networkRequests.size(); i++) {//当前网络断开,寻找可替代的网络连接NetworkRequest request = nai.networkRequests.valueAt(i);NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId);if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {mNetworkForRequestId.remove(request.requestId);sendUpdatedScoreToFactories(request, 0);NetworkAgentInfo alternative = null;}}}}
        在这里,将会取出当前断开的网络所能处理的NetworkRequest,然后在当前所有向ConnectivityService注册的列表中查找可替代的连接,并通过sendUpdatedScoreToFactories()向其发起连接请求:
        private void sendUpdatedScoreToFactories(NetworkAgentInfo nai) {for (int i = 0; i < nai.networkRequests.size(); i++) {NetworkRequest nr = nai.networkRequests.valueAt(i);if (!isRequest(nr)) continue;sendUpdatedScoreToFactories(nr, nai.getCurrentScore());}}
        继续:
        private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0, networkRequest);}}
        到这里将会向新的连接的NetworkFactoryInfo对象发起CMD_REQUEST_NETWORK的请求,之后相应的连接对象就可以建立连接了。
        至此,从一个连接类型遍转换到另一个连接类型中。
        以下是该过程的流程图:

这篇关于Framework中的连接管理机制(原)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1004179

相关文章

【Altium】查找PCB上未连接的网络

【更多软件使用问题请点击亿道电子官方网站】 1、文档目标: PCB设计后期检查中找出没有连接的网络 应用场景:PCB设计后期,需要检查是否所有网络都已连接布线。虽然未连接的网络会有飞线显示,但是由于布线后期整板布线密度较高,虚连,断连的网络用肉眼难以轻易发现。用DRC检查也可以找出未连接的网络,如果PCB中DRC问题较多,查找起来就不是很方便。使用PCB Filter面板来达成目的相比DRC

Java面试题:通过实例说明内连接、左外连接和右外连接的区别

在 SQL 中,连接(JOIN)用于在多个表之间组合行。最常用的连接类型是内连接(INNER JOIN)、左外连接(LEFT OUTER JOIN)和右外连接(RIGHT OUTER JOIN)。它们的主要区别在于它们如何处理表之间的匹配和不匹配行。下面是每种连接的详细说明和示例。 表示例 假设有两个表:Customers 和 Orders。 Customers CustomerIDCus

Windows中,.net framework 3.5安装

安装.net framework,目前已知2种方法,如下: 一、在MSDN下载对应的安装包,安装,这种可能无法安装成功,概率很大,不成功使用第二种方法,基本上没问题。 二、win8/8.1/10 下安装 .net framework 3.5.1: 1. 打开 win8/8.1/10 安装盘(这里指系统安装镜像文件),提取 sources\sxs 文件夹到 X:\sources\sxs (X代

神经网络第一篇:激活函数是连接感知机和神经网络的桥梁

前面发布的文章介绍了感知机,了解了感知机可以通过叠加层表示复杂的函数。遗憾的是,设定合适的、能符合预期的输入与输出的权重,是由人工进行的。从本章开始,将进入神经网络的学习,首先介绍激活函数,因为它是连接感知机和神经网络的桥梁。如果读者认知阅读了本专题知识,相信你必有收获。 感知机数学表达式的简化 前面我们介绍了用感知机接收两个输入信号的数学表示如下:

段,页,段页,三种内存(RAM)管理机制分析

段,页,段页         是为实现虚拟内存而产生的技术。直接使用物理内存弊端:地址空间不隔离,内存使用效率低。 段 段:就是按照二进制文件的格式,在内存给进程分段(包括堆栈、数据段、代码段)。通过段寄存器中的段表来进行虚拟地址和物理地址的转换。 段实现的虚拟地址 = 段号+offset 物理地址:被分为很多个有编号的段,每个进程的虚拟地址都有段号,这样可以实现虚实地址之间的转换。其实所谓的地

PHP ODBC:连接数据库的桥梁

PHP ODBC:连接数据库的桥梁 PHP ODBC(Open Database Connectivity)是一个允许PHP应用程序连接到各种数据库管理系统的扩展。它为PHP提供了一个标准的数据库访问接口,使得开发者可以编写不依赖于特定数据库系统的代码。本文将详细介绍PHP ODBC的概念、工作原理、使用方法以及在实际开发中的应用。 什么是PHP ODBC? PHP ODBC扩展使得PHP能

Android Framework学习(四)之Launcher启动流程解析

在之前的博客中,我们学习了init进程、Zygote进程和SyetemServer进程的启动过程,我们知道SystemServer进程主要用于启动系统的各种服务,二者其中就包含了负责启动Launcher的服务,LauncherAppService,本篇博客我们将一起学习Launcher相关的知识。 Launcher概述 Launcher程序就是我们平时看到的桌面程序,它其实也是一个Androi

Android Framework学习(三)之SyetemServer进程启动解析

从上篇博客中,我们知道了Zygote进程启动了SyetemServer进程,本篇博客我们就一起来学习SyetemServer进程。 SystemServer的作用 整个系统的android framework进程启动流程如下: init进程 –> Zygote进程 –> SystemServer进程 –>各种应用进程 SystemServer进程主要的作用是启动各种系统服务,比如Activ

Android Framework学习(二)之Zygote进程启动解析

上篇博客,我们学习了init进程的相关知识,本篇博客我们一次来学习zygote进程的相关知识。 Zygote简介 在Android系统中,JavaVM(Java虚拟机)、应用程序进程以及运行系统的关键服务的SystemServer进程都是由Zygote进程来创建的,我们也将它称为孵化器。它通过fock(复制进程)的形式来创建应用程序进程和SystemServer进程,由于Zygote进程在启动