[转]IBinder对象在进程间传递的形式

article/2025/9/2 9:05:45

目录:

  • 问题引出:由onServiceConnected()的IBinder类型说起
  • IBinder传递时Driver Module的处理
  • IBinder传递时framework的处理
    • 发送IBinder
    • 接收IBinder

问题引出:由onServiceConnected()的IBinder类型说起

service被远程调用时,我们常常使用aidl来定义一个接口给serviceclient来使用,这个其实就是使用Binder机制的IPC通信。当client bind Service成功之后,系统AM会调用回调函数onServiceConnected()将service的IBinder传递给client, client再通过调用aidl生成的asInterface()方法获得service的调用接口,此时一个bind过程结束了,我们在client端就可以远程调用的方法了。

我们先来看一下onServiceConnected()方法

public void onServiceConnected(ComponentName className, IBinder service) {mSecondaryService = ISecondary.Stub.asInterface(service);
}

aidl生成的asInterface()的定义

public static com.example.android.apis.app.ISecondary asInterface(android.os.IBinder obj)
{if ((obj==null)) {return null;}android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.example.android.apis.app.ISecondary))) {return ((com.example.android.apis.app.ISecondary)iin);}return new com.example.android.apis.app.ISecondary.Stub.Proxy(obj);
}

asInterface()方法中会通过queryLocalInterface()来判断传入的IBinder对象是service本身的引用还是代理

  1. asInterface的输入的IBinder为server的引用(Binder类型)时,则直接返回该引用,那么此时调用server的方法不为IPC通信,而是直接的函数调用;
  2. asInterface的输入的IBinder为server的代理(BinderProxy类型)时,则需要创建该server的代理并返回,此时调用server的方法为IPC通信。

那么asInterface()在实际情况下会被传入什么参数类型呢?要想回答这个问题,我们来看一下IBinder传递的流程。

IBinder传递时Driver Module的处理

IBinder作为参数在IPC通信中进行传递,可能会使某些人困惑,IBinder不就是IPC通信的媒介吗?怎么还会被作为参数来传递呢,这样理解就有点狭隘了,拿native层的IPC来说,clientSM(service manager)中获取service端的Interface,这个Interface同时也是IBinder类型,当C/S两端需要双工通信时,即所谓的Service端需要反过来调用Client端的方法时,就需要Client通过前述的那个InterfaceClient端的IBinder传递给Service

拿Java应用层的Service来说更是如此,如本文的这个命题,下面我们会分析,首先来介绍原理性的知识。

Binder IPC通信中,Binder是通信的媒介,Parcel是通信的内容。方法远程调用过程中,其参数都被打包成Parcel的形式来传递的。

IBinder对象也不例外,我们看一下Parcel类中的writeStrongBinder()(由于java层和native层的方法是相对应的,java层只是native的封装,因此我们只需要看native方法即可),

status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{return flatten_binder(ProcessState::self(), val, this);
}status_t flatten_binder(const sp<ProcessState>& proc,const sp<IBinder>& binder, Parcel* out)
{flat_binder_object obj;obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;if (binder != NULL) {IBinder *local = binder->localBinder();if (!local) {BpBinder *proxy = binder->remoteBinder();...const int32_t handle = proxy ? proxy->handle() : 0;obj.type = BINDER_TYPE_HANDLE;obj.handle = handle;obj.cookie = NULL;} else {obj.type = BINDER_TYPE_BINDER;obj.binder = local->getWeakRefs();obj.cookie = local;}} else {obj.type = BINDER_TYPE_BINDER;obj.binder = NULL;obj.cookie = NULL;}return finish_flatten_binder(binder, obj, out);
}

上面代码分下面2种情况:

  1. 如果传递的IBinder为service的本地 IBinder对象,那么该IBinder对象为BBinder类型的,因此上面的local不为NULL,故binder type为BINDER_TYPE_BINDER
  2. 如果传递的IBinder对象代理IBinder对象,那么binder type则为BINDER_TYPE_HANDLE

client端将方法调用参数打包成Parcel之后,会发送到内核的Binder模块,因此下面我们将分析一下内核的Binder模块的处理。

kernel/drivers/staging/android/Binder.c中的函数binder_transaction()

binder_transaction()
{...switch (fp->type) {case BINDER_TYPE_BINDER:case BINDER_TYPE_WEAK_BINDER: {struct binder_ref *ref;struct binder_node *node = binder_get_node(proc, fp->binder);...ref = binder_get_ref_for_node(target_proc, node);...if (fp->type == BINDER_TYPE_BINDER)fp->type = BINDER_TYPE_HANDLE;elsefp->type = BINDER_TYPE_WEAK_HANDLE;fp->handle = ref->desc;binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,&thread->todo);} break;case BINDER_TYPE_HANDLE:case BINDER_TYPE_WEAK_HANDLE: {struct binder_ref *ref = binder_get_ref(proc, fp->handle);...if (ref->node->proc == target_proc) {if (fp->type == BINDER_TYPE_HANDLE)fp->type = BINDER_TYPE_BINDER;elsefp->type = BINDER_TYPE_WEAK_BINDER;fp->binder = ref->node->ptr;fp->cookie = ref->node->cookie;...} else {struct binder_ref *new_ref;new_ref = binder_get_ref_for_node(target_proc, ref->node);...fp->handle = new_ref->desc;...}} break;...

上面代码也分为了2种不同的情况:

  1. 传来的IBinder类型为BINDER_TYPE_BINDER时,会将binder type值为BINDER_TYPE_HANDLE
  2. 传来的IBinder类型为BINDER_TYPE_HANDLE时,会判断该IBinder的实体被定义的进程(也就是该IBinder代表的server被定义的进程)与目标进程(也即IBinder被传递的目标进程)是否相同,如果相同,则将该IBinder type转化为BINDER_TYPE_BINDER,同时使其变为IBinder本地对象的引用。

通过上述的处理,我们可以得出下面结论:

  1. 不同进程间传递的IBinder本地对象引用(BINDER_TYPE_BINDER类型),在内核中均会被转化为代理(BINDER_TYPE_HANDLE类型,目前只是改变其类型,在IBinder接收方会根据其类型转化为代理);
  2. 由于只有不同进程间传递才会将IBinder发送到Binder模块,所以IBinder在多级传递的过程中,有下面2种可能:
进程A-->进程B-->进程A
进程A-->进程B-->进程C

其对应的IBinder类型就是

BINDER_TYPE_BINDER->BINDER_TYPE_HANDLE->BINDER_TYPE_BINDER
BINDER_TYPE_BINDER->BINDER_TYPE_HANDLE->BINDER_TYPE_HANDLE

根据上述结论,我们就会明白:

Binder IPC通信过程
相同进程间的IBinder本地对象,如果不经过不同进程的传递,那么IBinder就不会传给内核的Binder模块,因此它一直是IBinder的本地对象;
如果在进程间传递,即使通过再多的进程间的传递,只要最后的目标是同一个进程的component,那么他得到的IBinder对象就是本地的对象。

在这里插入图片描述

理解了上面的这个模型,我们再回过头看最开始的那个问题可以给出答案了:

1.当client和service处在相同进程中的话,asInterface的输入的IBinder为server的引用
2.当client和service处在不同进程中的话,asInterface的输入的IBinder为server的代理

举个例子:
假如某一个component(例如一个Acitivity)处在进程A,它需要bind()一个service,而该service处在进程B中,我们简单介绍一下bind()的过程。

binder service流程

  1. 进程AAM(进程system_server)发出Bind请求,并将回调ServiceConnection提供给AM(传递给AM的也是一个接口(IServiceConnection),因为AM进程A之间是双工通信,所以进程A需要向AM提供IBinder);
  2. AM启动进程B并创建service进程BserviceIBinder对象传递给AMAM再通过IServiceConnection传递给进程A。所以serviceIBinder对象的传递路径为:
进程B-->进程system_server(AM)-->进程A。

所以进程A中asInterface的输入的IBinder为server的代理对象

IBinder传递时framework的处理

Android中主要通过2种方法来获得service IBinder:

  1. 通过ServiceManager.getService(String Descriptor)来获得Service Manager管理的serviceIBinder
  2. Client获得Application ServiceIBinder,如上图描述的binder service流程。

不管哪种方法,均涉及到IBinder在不同进程间的传递,因为不论是Application Service 还是 System Service,它们在注册时均会涉及到第三方进程,如Application Service注册在Acitivity Manager中(system_server进程),System Service注册在Service Manager中(servicemanager进程)。

Service Manager中获得IBinder涉及到serviceservicemanager进程以及clientservicemanager进程之间的IBinder传递;
获得Application ServiceIBinder,更是涉及到ApplicationServicesystem_server进程以及clientsystem_server进程之间的IBinder传递,如上图描述的binder service流程。

研究这个主题的意义在于,虽然从表面上看,在用到IBinder时,我们在应用中使用的是同一个接口,但是它的实质是怎么样的?是一套什么样的机制保证在同进程间client调用的是service的实体,而在不同进程间则是调用的serviceproxy

关于Binder的传递过程,首先需要了解一个service的类图关系。下图为JNI以上的类图。(涉及到JNI和JAVA层的Binder对应关系。JNI层以下的Binder不涉及到这个文章的主题。)
在这里插入图片描述

IISERVICEInterface表示aidl文件生成的或者用户自定义的当前service的接口文件,Service表示当前service的实现。IISERVICEInterface.Proxy表示当前service的代理。

在JNI层,JavaBBinder继承自BBinder,是Binder的实体,它是在BBinder的基础上添加了成员变量jobjectmObject,该成员变量指向JAVA的Service对象。这么做的好处就是在同进程间传递时,接收方能够直接向JAVA层返回Service对象。

JavaBBinderHolder类,可以说是JavaBBinder类的一个容器,当JAVA层的Service对象被创建时,就会相应的创建一个JavaBBinderHolder实例,但是只有Service对象被IPC传递时,JavaBBinderHolder对象才会创建一个JavaBBinder实例。

发送IBinder

IBinder在IPC通信中,通过Parcel类writeStrongBinder()写入IBinder数据

// java
data.writeStrongBinder(ISERVICE_C_Interface.Stub);

先来看下writeStrongBinder()方法
frameworks/base/core/jni/android_util_Binder.cpp

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jint nativePtr, jobject object)
{Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);if (parcel != NULL) {const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));...}
}

ibinderForJavaObject()函数会判断JAVAIBinder的类型并转化为nativeIBinder类型,也就是将BinderBinderProxy对象分别转换为JavaBBinderBpBinder

sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{...if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {JavaBBinderHolder* jbh = (JavaBBinderHolder*)env->GetIntField(obj, gBinderOffsets.mObject);return jbh != NULL ? jbh->get(env) : NULL; //分析见下1}if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {return (IBinder*)env->GetIntField(obj, gBinderProxyOffsets.mObject); //分析见下2}...
}
  1. IBinder是以JavaBBinder的形式传递的,即是一个ServiceIBinderreference。如上面代码中的第一个return语句。
    这种较常见,作为传输介质的IBinder所处的service发送方在同一进程中。
    在这里插入图片描述
    Service处在Process A中,Process A为IBinder发送方。

  2. IBinder是以BpBinder的形式传递的,即是一个ServiceIBinderProxy。如上面代码中的第二个return语句。
    在这里插入图片描述
    Service 处在Process C`中,Process A为IBinder发送方。

这种情况比较典型的就是bindservice时会用到,如图中最后一步中AMS通知client bind成功时,传递给client的就是一个service IBinderProxy。作为传输介质的IBinder所处的service和发送方在不同的进程中。

kernel中,Binder Module会根据IPC通信双方是否处于同一个进程中,来设置binder object type值。

kernel/drivers/staging/android/Binder.c

static void binder_transaction(struct binder_proc *proc,struct binder_thread *thread,struct binder_transaction_data *tr, int reply)
{...switch (fp->type) {case BINDER_TYPE_BINDER: //见下文1case BINDER_TYPE_WEAK_BINDER: {struct binder_ref *ref;struct binder_node *node = binder_get_node(proc, fp->binder);...ref = binder_get_ref_for_node(target_proc, node);...if (fp->type == BINDER_TYPE_BINDER)fp->type = BINDER_TYPE_HANDLE;elsefp->type = BINDER_TYPE_WEAK_HANDLE;fp->handle = ref->desc;binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,&thread->todo);} break;case BINDER_TYPE_HANDLE: //见下文2case BINDER_TYPE_WEAK_HANDLE: {struct binder_ref *ref = binder_get_ref(proc, fp->handle);...if (ref->node->proc == target_proc) {if (fp->type == BINDER_TYPE_HANDLE)fp->type = BINDER_TYPE_BINDER;elsefp->type = BINDER_TYPE_WEAK_BINDER;fp->binder = ref->node->ptr;fp->cookie = ref->node->cookie;...} else {struct binder_ref *new_ref;new_ref = binder_get_ref_for_node(target_proc, ref->node);...fp->handle = new_ref->desc;...}} break;...
  1. IBinder的发送方和Service在同一进程的话,那么传递给内核的binder_objecttypeBINDER_TYPE_BINDER,由于IBinder发送到内核均是在进程间传递的,所以Binder Module driver会将type改为BINDER_TYPE_HANDLE
  2. IBinder的发送方和Service不在同一进程的话,那么传递给内核的binder_objecttype就为BINDER_TYPE_HANDLE,并且这种情况接收方和Service可能处在同一个进程中,因此当这种情况发生时,需要将其改为BINDER_TYPE_BINDER

IBinder发送的流程图:
在这里插入图片描述

接收IBinder

java中用来接收binder driver传来parcel数据的接口

IBinder b = data.readStrongBinder();

看一下readStrongBinder() 方法

frameworks/base/core/java/android/os/Parcel.java

public final IBinder readStrongBinder() {return nativeReadStrongBinder(mNativePtr);
}

对应的JNI实现

frameworks/base/core/jni/android_os_Parcel.cpp

static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jint nativePtr)
{Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);if (parcel != NULL) {return javaObjectForIBinder(env, parcel->readStrongBinder());}return NULL;
}

1.先看一下android_os_Parcel_readStrongBinder调用的Parcel的readStrongBinder()方法
frameworks/native/libs/binder/Parcel.cpp

sp<IBinder> Parcel::readStrongBinder() const
{sp<IBinder> val;unflatten_binder(ProcessState::self(), *this, &val);return val;
}

其中调用了unflatten_binder方法
frameworks/native/libs/binder/Parcel.cpp

status_t unflatten_binder(const sp<ProcessState>& proc,const Parcel& in, sp<IBinder>* out)
{const flat_binder_object* flat = in.readObject(false);if (flat) {switch (flat->type) {case BINDER_TYPE_BINDER:*out = static_cast<IBinder*>(flat->cookie);return finish_unflatten_binder(NULL, *flat, in);case BINDER_TYPE_HANDLE:*out = proc->getStrongProxyForHandle(flat->handle);return finish_unflatten_binder(static_cast<BpBinder*>(out->get()), *flat, in);}        }return BAD_TYPE;
}
  1. 当从BinderModule中读出的binder_objecttypeBINDER_TYPE_BINDER说明接收方收到的Service是同进程的,那么此时直接将保存在cookie中的Service的实体传递给JNI层。
    在这里插入图片描述
    此时,JNI层收到的Service实体为一个JavaBBinder对象,由上面的类图可以知道,JavaBBinder对象中包含着JAVAService对象的引用。

  2. 当从Binder Module中读出的binder_objecttypeBINDER_TYPE_HANDLER说明接收方收到的Service不是同进程的,那么会创建或者引用已有的一个BpBinder对象给JNI层。
    在这里插入图片描述
    Service 处在Process C中,Process B为IBinder接收方。

下面我们再来看一下当binder_objecttypeBINDER_TYPE_HANDLER时所调用的getStrongProxyForHandle()方法

frameworks/native/libs/binder/ProcessState.cpp

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{sp<IBinder> result;AutoMutex _l(mLock);handle_entry* e = lookupHandleLocked(handle);if (e != NULL) {IBinder* b = e->binder;if (b == NULL || !e->refs->attemptIncWeak(this)) {...b = new BpBinder(handle); e->binder = b;if (b) e->refs = b->getWeakRefs();result = b;} else {...}}return result;
}

首先,lookupHandleLocked方法从参数接收服务Handle,查找与其相对应的Vector并返回,若查找不到,则创建entry并更新Vector。这样做是为了保证ProcessState不会对同一进程中针对指定的服务生成多个重复的对象。

frameworks/native/libs/binder/ProcessState.cpp

// Vector<handle_entry>mHandleToObject;
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{const size_t N=mHandleToObject.size();if (N <= (size_t)handle) {handle_entry e;e.binder = NULL;e.refs = NULL;status_t err = mHandleToObject.insertAt(e, N, handle+1-N);if (err < NO_ERROR) return NULL;}return &mHandleToObject.editItemAt(handle);
}

如果没有查找到BpBinder对象,则new BpBinder,生成对应服务的HandleBpBinder对象并保存。(在Binder Modlue中handle可以唯一标识BpBinder对象。)

2.再来看一下android_os_Parcel_readStrongBinder()调用的javaObjectForIBinder()方法

frameworks/base/core/jni/android_util_Binder.cpp

jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{...if (val->checkSubclass(&gBinderOffsets)) {// One of our own!jobject object = static_cast<JavaBBinder*>(val.get())->object();LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);return object;}...object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);if (object != NULL) {// The proxy holds a reference to the native object.env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get());}return object;
}

javaObjectForIBinder()分别将JavaBBinderBpBinder对象转换成BinderBinderProxy对象。当是BpBinder时,生成一个BinderProxy对象,将BpBinder保存到BinderProxymObject中。
在这里插入图片描述

如上图所示:

  1. 每个进程中会保存多个当前进程调用过的BpBinder对象;
  2. 每个BpBinder对象都会保存与之对应的JAVA层的BinderProxy。

参考文章:
https://blog.csdn.net/windskier/article/details/6625883
https://blog.csdn.net/windskier/article/details/6913698


http://chatgpt.dhexx.cn/article/INw0TFCe.shtml

相关文章

android i 网络接口,从IBinder接口学习Proxy-Stub设计模式

定义了抽象函数&#xff0c;如上图里的onTransact()函数&#xff0c;成为提供给众多子类别来实现的内部接口。我们以来表示之。 如下图所示&#xff1a; 图3、基类实现CI&#xff0c;并定义 ---- 由子类来实现内部接口。Binder基类的很重要目的是支持跨进程调用Service&#xf…

Android IPC 之获取服务(IBinder)

前言 IPC 系列文章&#xff1a; 建议按顺序阅读。 Android IPC 之Service 还可以这么理解 Android IPC 之Binder基础 Android IPC 之Binder应用 Android IPC 之AIDL应用(上) Android IPC 之AIDL应用(下) Android IPC 之Messenger 原理及应用 Android IPC 之服务端回调 Android…

android ibinder 机制,Android IBinder机制简单介绍

原理简介 我们都知道android 是通过IBinder来实现IPC(Inter Process Communication)进程间通信的。。。 借用一下: 1. Client、Server和Service Manager实现在用户空间中,Binder驱动程序实现在内核空间中 2. Binder驱动程序和Service Manager在Android平台中已经实现,开发者…

sql之嵌套查询中的带exists谓词的子查询

数据库系统概论之嵌套查询中的带exists谓词的子查询 一、exists谓词概述&#xff1a;exists谓词代表存在量词。带有exists谓词的子查询不返回任何数据&#xff0c;只产生逻辑真值“true”或逻辑假值“false”。可以利用exists来判断属性与关系表之间的属于关系&#xff0c;关系…

sql in和exist

前言 最近写SQL的时候要求在排除A表中所存在的B表的某些同属性值的记录。 然后就想到了in和exist&#xff0c;但是其实一直都没有真正的去弄懂两者不同&#xff0c; 于是在网上查询了一些大佬的文章&#xff0c;然后去实践了一番&#xff0c;最后做一个总结 开始啰 1&#xff…

SQL之EXISTS的理解

将外查询表的每一行&#xff0c;代入内查询作为检验&#xff0c;如果内查询返回的结果取非空值&#xff0c;则EXISTS子句返回TRUE&#xff0c;这一行行可作为外查询的结果行&#xff0c;否则不能作为结果。 先上表 过程&#xff1a;外查询Persons表&#xff0c;提取出数据到E…

sql中exists的常用用法

exists中子查询结果集非空&#xff0c;则exists子查询返回true。如果exists子查询结果集为空&#xff0c;则exists子查询返回false。在平常的开发工作中&#xff0c;经常会用到exists&#xff0c;那么它应该如何使用呢&#xff1f; 1&#xff1a;查询兴趣爱好为跳舞的同学姓名及…

MySQL SQL语句EXISTS

MySQL中EXITS语句用于查明表中是否存在特定的行。普遍情况下EXITS与子查询一起使用&#xff0c;并返回与子查询返回的结果相等或匹配的行。如果行在表中存在&#xff0c;则返回true&#xff0c;否则返回false。在MySQL中使用EXISTS是低效的&#xff0c;因为EXISTS对查理表中的每…

SQL语句中EXISTS的用法

SQL萌新一个&#xff0c;在这里记录一下自学过程中遇到的问题。 exists&#xff1a;强调的是&#xff0c;是否有返回集&#xff0c;不需要知道具体返回的是什么 比如这两个表&#xff1a; 输入查询语句&#xff1a; select * from customer c where not exists( select * from…

sql中 exists的用法

现有&#xff1a;班级表&#xff08;A_CLASS&#xff09; 学生表( STUDENT) 注&#xff1a;学生表(STUDENT)的classId关联班级表&#xff08;A_CLASS&#xff09;的主键ID 代码&#xff1a; select * from STUDENT s WHERE exists (select 1 from A_ClASS c where s.CLASS_…

SQL语句中EXISTS的详细用法大全

SQL语句中EXISTS的详细用法大全 前言一、建表1.在MySQL数据库建表语句2.在ORACLE数据库建表语句 二、在SELECT语句中使用EXISTS1.在SQL中使用EXISTS2.在SQL中使用NOT EXISTS3.在SQL中使用多个NOT EXISTS4.在SQL中使用多个EXISTS5.在SQL中使用NOT EXISTS和EXISTS 三、在DELETE语…

DNS服务器解析问题

DNS服务器解析问题 前言 重点&#xff1a; 本文摘选链接&#xff1a;https://www.ancii.com/aazeaa674/ 正文 问题 域名状态异常会导致网站不能访问吗&#xff1f; 刚修改过域名解析&#xff0c;为什么不生效呢&#xff1f; 如何查看解析是否生效呢&#xff1f; 刚在注…

dns服务器怎么设置

dns服务器怎么设置 在修改DNS之前需要先知道你的大DNS服务器地址是什么&#xff0c;那么怎么来查询DNS服务器地址呢&#xff1f;直接按住键盘上的“winR”&#xff0c;调出运行框。在输入框中输入“cmd”&#xff0c;点击“确定”或者回车。在管理员界面中输入命令&#xff1a;…

手机显示DNS服务器异常,手机dns服务器异常怎么设置

手机dns服务器异常怎么设置 内容精选 换一换 华为云帮助中心,为用户提供产品简介、价格说明、购买指南、用户指南、API参考、最佳实践、常见问题、视频帮助等技术文档,帮助您快速上手使用华为云服务。 本章节介绍如何通过控制台重启服务器。重启服务器时,可以批量更换云手机…

小米路由器显示DNS服务器设置错误,小米路由器dns地址怎么设置

小米路由器与日常所有的路由器一样&#xff0c;在默认情况下都是路由器的地址作为无线设备获取的 DNS 地址。如果你想手动修改小米路由器的DNS地址&#xff0c;也是可以的&#xff0c;下面是学习啦小编给大家整理的一些有关小米路由器dns地址设置方法&#xff0c;希望对大家有帮…

如何设置正确的dns服务器地址,dns服务器地址如何设置

dns服务器地址如何设置 (Windows 2000、Windows XP操作系统)&#xff1a; 1、 开机后在桌面上选定图标"网上邻居"&#xff0c; 点击鼠标右键&#xff0c; 在弹出的菜单上选择"属性"项&#xff0c;打开"网络和拔号连接"窗口&#xff0c; 如图 2、…

北京联通dns服务器位置,联通DNS服务器地址怎么设置

联通DNS服务器地址怎么设置 如电脑Win7系统,以下方法设置DNS:您右键点击电脑桌“网络”图标 ,“属性” >选择“控制面板” >在“网络和共享中心”中可看到当前的网络状况,点击左边的“更改适配器设置” >右键单击“本地连接”择“属性” >选择“internet协议版本4(TCP/…

路由器显示DNS服务器设置错误,路由器dns设置错误怎么处理

一般都给家里配上了无线路由器&#xff0c;但是在用了无线路由器后&#xff0c;很容易导致电脑断网&#xff0c;大家一般用软件检测后上面会显示是DNS地址出现了异常&#xff0c;那么应该怎么解决这个问题&#xff0c;不让电脑频繁断网呢?下面是学习啦小编给大家整理的一些有关…

无线路由dns服务器地址,tplink无线路由器怎么设置DNS服务器地址

作为不同网络之间互相连接的枢纽,路由器系统构成了基于TCP/IP 的国际互联网络Internet 的主体脉络,也可以说,路由器构成了Internet的骨架。在设置路由器的时候,很多用户不知道该怎么手动设置路由器的DNS服务器地址,下面我们就来看看详细的设置教程,需要的朋友可以参考下 …

Ros系统配置DNS服务器,ros设置dns服务器

ros设置dns服务器 内容精选 换一换 域名的DNS服务器定义了域名用于解析的权威DNS服务器。通过华为云注册成功的域名默认使用华为云DNS进行解析,详细内容,请参见华为云DNS对用户提供域名服务的DNS是什么?。若您选择非华为云DNS进行域名解析,可以修改域名的DNS服务器。域名注…