IBinder

Binder 继承自 IBinder,所以我们先来了解下它。

IBinder 是一个接口,它代表了一种跨进程传输的能力。只要实现了这个接口,就能将这个对象进行跨进程传递。

IBinder 是高性能、轻量级远程调用机制的核心部分,它定义了远程操作对象的基本接口。

这些方法中最关键的一个是 transact():

public boolean transact(int code, Parcel data, Parcel reply, int flags)throws RemoteException;

与它对应的是 Binder.onTransact()

protected boolean onTransact(int code, Parcel data, Parcel reply,int flags) throws RemoteException {...}

可以看到这两个方法非常相似,介绍一下方法中的各个参数:

  • code:要执行的动作,类似 Handler 的 msg.what,IBinder 中定义了以下几个 code 
    • PING_TRANSACTION,表示要调用 pingBinder() 方法
    • DUMP_TRANSACTION,表示要获取 Binder 内部状态
    • SHELL_COMMAND_TRANSACTION,执行一个 shell 命令
    • INTERFACE_TRANSACTION,询问被调用方的接口描述符号
    • TWEET_TRANSACTION
    • LIKE_TRANSACTION
    • 如果我们需要自定义 code,code 的值范围需要在 FIRST_CALL_TRANSACTION(0x00000001) 和 LAST_CALL_TRANSACTION(0x00ffffff) 之间
  • datareply:传入的参数和返回的值
  • flags:表示是否需要阻塞等待返回值,有两个值 
    • 0
    • FLAG_ONEWAY (0x00000001),表示 Client 的 transact() 是单向调用,执行后立即返回

①经常的场景是,我们调用 IBinder.transact() 给一个 IBinder 对象发送请求,然后经过 BinderBinder.onTransact() 得到调用,接着远程操作的目标得到对应的调用。

这个过程不仅在同一进程中可以进行,在跨进程(IPC)间也可以完成。

IBinder.transact() 方法是同步的,它被调用后一直到 Binder.onTransact() 调用完成后才返回。

②通过 IBinder.transact() 方法传输的数据被保存为一个 Parcel 对象,Parcel 中保存了数据以及描述数据的元数据,元数据在缓存区中保持了 IBinder 对象的引用,这样不同进程都可以访问同一个数据。

因此在一个 IBinder 对象写入 Parcel 对象然后发送到另一个进程时,另外那进程将这个 IBinder 对象发送回去时,原本进程接收到的 IBinder 对象和开始发送出去的是同一个引用。

在跨进程传输后引用没有改变,这是非常关键的一点,这就使得 IBinder/Binder 对象在跨进程通信时可以作为唯一的标识(比如作为 token 什么的)。

③系统在每个进程中都有一个处理事物的线程池,这些线程用于调度其他进程对当前进程的跨进程访问。

比如说进程 A 对进程 B 发起 IPC 时,A 中调用 transact() 的线程会阻塞。B 中的事物线程池收到 A 的 IPC,调用目标对象的 Binder.onTransact() 方法,然后返回带结果的 Parcel。一旦接收到结果,A 中阻塞的线程得以继续执行。

这个过程和线程通信非常相似吧。

④Binder 机制还支持进程间的递归调用

比如,进程 A 向进程 B 发起 IPC,而进程 B 在其 Binder.onTransact() 中又用 transact() 向进程 A 发起 IPC,那么进程 A 在等待它发出的调用返回的同时,也会响应 B 的调用,对调用的对象执行 Binder.onTransact() 方法。

这种机制可以让我们觉得到跨进程的调用与进程内的调用没什么区别,这是非常重要的。

⑤在跨进程通信时,我们常常想要知道另外进程是否可用,IBinder 提供了三个检查的方法:

  1. transact() 
    • 当你调用的 IBinder 所在进程不存在时,会抛出 RemoteException 异常
  2. pingBinder() 
    • 当远程进程不存在时该方法返回 false
  3. linkToDeath() 
    • 这个方法可以向 IBinder 中注册一个 IBinder.DeathRecipient,它将在 IBinder 所在的进程退出时被调用
/*** 检查远程 Binder 对象是否存在* * 当不存在时返回 false*/
public boolean pingBinder();
/*** 注册一个 Binder 销毁的监听如果一个 Binder 被销毁(通常是它所在的进程被关闭),会回调 DeathRecipient 的 BinderDied 方法* 注意,只会监听远程的 Binder,本地 Binder 一般不会销毁,除非当前进程退出* * 如果要注册的 Binder 进程已经销毁,就抛出 RemoteException */
public void linkToDeath(DeathRecipient recipient, int flags)throws RemoteException;/*** linkToDeath 注册监听回调的接口*/
public interface DeathRecipient {public void binderDied();
}

Binder

官方文档中建议:

日常开发中一般不需要我们再实现 IBinder,直接使用系统提供的 Binder 即可

Binder 实现了 IBinder 定义的操作,它是 Android IPC 的基础,平常接触到的各种 Manager(ActivityManager, ServiceManager 等),以及绑定 Service 时都在使用它进行跨进程操作。

它的存在不会影响一个应用的生命周期,只要创建它的进程在运行它就一直可用。

通常我们需要在顶级的组件(Service, Activity, ContentProvider)中使用它,这样系统才知道你的进程应该一直被保留。

下面介绍 Binder 的几个关键方法:

实现 IBinder 的 transact() 方法:

public final boolean transact(int code, Parcel data, Parcel reply,int flags) throws RemoteException {if (false) Log.v("Binder", "Transact: " + code + " to " + this);if (data != null) {data.setDataPosition(0);}boolean r = onTransact(code, data, reply, flags);if (reply != null) {reply.setDataPosition(0);}return r;
}

可以看到,这个方法就是调用 onTransact() ,然后将返回的结果再返回回去。

接着看看 onTransact() 方法:

protected boolean onTransact(int code, Parcel data, Parcel reply,int flags) throws RemoteException {if (code == INTERFACE_TRANSACTION) {    //获取接口描述reply.writeString(getInterfaceDescriptor());return true;} else if (code == DUMP_TRANSACTION) {    //获取当前状态ParcelFileDescriptor fd = data.readFileDescriptor();String[] args = data.readStringArray();if (fd != null) {try {dump(fd.getFileDescriptor(), args);} finally {IoUtils.closeQuietly(fd);}}// Write the StrictMode header.if (reply != null) {reply.writeNoException();} else {StrictMode.clearGatheredViolations();}return true;} else if (code == SHELL_COMMAND_TRANSACTION) {    //执行 shell 脚本ParcelFileDescriptor in = data.readFileDescriptor();ParcelFileDescriptor out = data.readFileDescriptor();ParcelFileDescriptor err = data.readFileDescriptor();String[] args = data.readStringArray();ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data);try {if (out != null) {shellCommand(in != null ? in.getFileDescriptor() : null,out.getFileDescriptor(),err != null ? err.getFileDescriptor() : out.getFileDescriptor(),args, resultReceiver);}} finally {IoUtils.closeQuietly(in);IoUtils.closeQuietly(out);IoUtils.closeQuietly(err);// Write the StrictMode header.if (reply != null) {reply.writeNoException();} else {StrictMode.clearGatheredViolations();}}return true;}return false;
}

也没看出什么特别的,系统的 Binder.onTransact() 方法只定义了系统要进行的操作,我们如果创建自己的 Binder 时,就需要重写这个方法,根据 code 对传入的参数 data 做相应的处理,然后写入 reply,这样就能返回操作后的数据。

另外一个关键的方法 attachInterface

public void attachInterface(IInterface owner, String descriptor) {mOwner = owner;mDescriptor = descriptor;
}
/* mObject is used by native code, do not remove or rename */
private long mObject;
private IInterface mOwner;
private String mDescriptor;

这个方法的作用是将一个描述符、特定的 IInterface 与当前 Binder 绑定起来,这样后续调用 queryLocalInterface 就可以拿到这个 IInterface,那 IInterface 又是什么呢?

public interface IInterface
{/*** Retrieve the Binder object associated with this interface.* You must use this instead of a plain cast, so that proxy objects* can return the correct result.*/public IBinder asBinder();
}

其实看名字就可以大概猜出来,IInterface 应该就是进程间通信定义的通用接口,我们通过定义接口,然后再服务端实现接口、客户端调用接口,就可以实现跨进程通信。

IInterface 里只定义了一个 asBinder() 方法,这个方法可以返回当前接口关联的 Binder 对象。

Binder 通信机制

上面介绍了 Binder 类以及相关的方法,但是这只是 Binder 机制的最基础部分。

我们平常看的文章或者面试时,说的 Binder 其实是范围更大的整个 “Binder 消息通信机制”。

 

在 Android 系统的 Binder 机制中,由四个组件组成,分别是:

  • Client
  • Server
  • ServiceManager:提供辅助管理 Server 的功能
  • Binder 驱动程序:整个机制的核心

Binder 驱动

驱动程序一般指的是设备驱动程序(Device Driver),是一种可以使计算机和设备通信的特殊程序。相当于硬件的接口,操作系统只有通过这个接口,才能控制硬件设备的工作。

我们知道,在 Linux 系统中,内存空间分为两部分:

  • 用户空间:运行着应用程序
  • 内核空间:运行着系统内核和驱动

 

用户空间中的进程无法直接访问内核空间,需要通过上图中的 System Call Interface (系统调用接口),通过这个统一入口,所有资源访问都是在内核的控制下执行,这样可以避免用户程序对系统资源的越权访问,从而保障了系统的安全和稳定。

同样的,用户空间中的进程直接也不可以直接访问数据,需要通过内核空间进行中转。

在 Binder 机制中,由 Binder 驱动负责完成这个中转操作,主要过程如下:

  • 当 Client 向 Server 发起 IPC 请求时,Client 会先将请求数据从用户空间拷贝到内核空间
  • 数据被拷贝到内核空间之后,驱动程序将内核空间中的数据拷贝到 Server 位于用户空间的缓存中

这样,就成功的将 Client 进程中的请求数据传递到了 Server 进程中。

实际上,Binder 驱动是整个 Binder 机制的核心。除了实现数据传输之外,Binder 驱动还是实现线程控制(通过中断等待队列实现线程的等待/唤醒),以及 UID/PID 等安全机制的保证。 

 

Service Manager

ServiceManager 运行在用户空间,它负责管理 Service 注册与查询。

看下 ServiceManager 的代码:

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 managersServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());return sServiceManager;}/*** 根据 Service 名称获取 Service*/public static IBinder getService(String name) {try {IBinder service = sCache.get(name);if (service != null) {return service;} else {//如果不存在就去 IServiceManager 中找,这时可能会阻塞return getIServiceManager().getService(name);}} catch (RemoteException e) {Log.e(TAG, "error in getService", e);}return null;}/*** 添加一个 Service 到 Manager 中*/public static void addService(String name, IBinder service) {try {getIServiceManager().addService(name, service, false);} catch (RemoteException e) {Log.e(TAG, "error in addService", e);}}/*** 添加一个 Service 到 Manager 中,如果 allowIsolated 为 true 表示运行在沙盒中的进程也可以访问这个 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;}}/*** 获取 Service 列表*/public static String[] listServices() {try {return getIServiceManager().listServices();} catch (RemoteException e) {Log.e(TAG, "error in listServices", e);return null;}}/*** 当前进程首次被 activity manager 创建时调用这个方法 */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 提供了 Service 的添加和查询,其中主要操作都是通过 IServiceManager,它是何方神圣?

public interface IServiceManager extends IInterface
{/*** 获取一个 Service,不存在就会阻塞几秒*/public IBinder getService(String name) throws RemoteException;/*** 不阻塞的获取 Service*/public IBinder checkService(String name) throws RemoteException;public void addService(String name, IBinder service, boolean allowIsolated)throws RemoteException;public String[] listServices() throws RemoteException;/*** 为 Service Manager 添加权限,具体作用暂不追究*/public void setPermissionController(IPermissionController controller)throws RemoteException;static final String descriptor = "android.os.IServiceManager";//定义了一些用于调用 transact() 方法的 codeint 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;
}

可以看到 IServiceManager 是一个接口,它定义了管理 Service 的一些方法,同时继承了 IInterface。最常见的实现是 BnServiceManager.getDefault()

Binder 机制跨进程通信流程

上面两节简单介绍了 Binder 机制中非常重要的两部分,ServiceManager 和 Binder 驱动。

在 Binder 机制的四个部分中, Client、Server 和 ServiceManager 运行在用户空间,Binder 驱动程序运行内核空间。

Binder 就是一种把这四个组件粘合在一起的粘结剂。

这个流程是如何进行的呢?

 

  • Binder实体 
    • Binder 实体实际上是内核中 binder_node 结构体的对象,它的作用是在内核中保存 Server 和ServiceManager 的信息(例如,Binder 实体中保存了 Server 对象在用户空间的地址)
    • Binder 实体是 Server 在 Binder 驱动中的存在形式,内核通过 Binder 实体可以找到用户空间的Server对象
    • 在上图中,Server 和 ServiceManager 在 Binder 驱动中都对应的存在一个 Binder 实体
  • Binder 引用 
    • Binder引用实际上是内核中 binder_ref 结构体的对象,是某一个 Binder 实体的引用,通过Binder 引用可以在内核中找到对应的 Binder 实体
    • 如果将 Server 看作是 Binder 实体的话,那么 Client 就好比 Binder 引用,Client 通过保存一个Server 对象的 Binder 引用,再通过该 Binder 引用在内核中找到对应的 Binder 实体,进而找到Server 对象,然后将通信内容发送给 Server 对象
  • 远程服务 
    • 本地服务的代理,通过调用远程服务可以间接调用本地服务

1.Client、Server 和 ServiceManager 处于用户空间的不同进程。 
2.Binder 实体和 Binder 引用都是内核(即 Binder 驱动)中的数据结构。

它们的关系如下:

 

每一个 Server 在内核中就表现为一个 Binder 实体,而每一个 Client 则表现为一个 Binder 引用。这样,每个 Binder 引用都对应一个 Binder 实体,而每个 Binder 实体则可以多个 Binder 引用。

Binder 跨进程通讯流程主要为如下 4 步:

  1. ServiceManager 初始化 
    • 当该应用程序启动时,ServiceManager 会和 Binder 驱动进行通信,告诉 Binder 驱动它是服务管理者
    • Binder 驱动新建 ServiceManager 对应的 Binder 实体
  2. Server 向 ServiceManager 注册自己 
    • Server 向 Binder 驱动发起注册请求,Binder 为它创建 Binder 实体
    • 然后如果 ServiceManager 中没有这个 Server 时就添加 Server 名称与 Binder 引用到它的 Binder 引用表
  3. Client 获取远程服务 
    • Client 首先会向 Binder 驱动发起获取服务的请求,传递要获取的服务名称
    • Binder 驱动将该请求转发给 ServiceManager 进程
    • ServiceManager 查找到 Client 需要的 Server 对应的 Binder 实体的 Binder 引用信息,然后通过 Binder 驱动反馈给 Client
    • Client 收到 Server 对应的 Binder 引用后,会创建一个 Server 对应的远程服务(即 Server 在当前进程的代理)
  4. Client 通过代理调用 Server 
    • Client 调用远程服务,远程服务收到 Client 请求之后,会和 Binder 驱动通信
    • 因为远程服务中有 Server 的 Binder 引用信息,因此驱动就能轻易的找到对应的 Server,进而将Client 的请求内容发送 Server

Binder 机制的优点

对比 Linux 上的其他进程通信方式(管道/消息队列/共享内存/信号量/Socket),Binder 机制的优点有以下几点:

  1. 高效简单

    • 通过驱动在内核空间拷贝数据,不需要额外的同步处理
    • 对比 Socket 等传输效率高
  2. 安全

    • Binder 机制为每个进程分配了 UID/PID 来作为鉴别身份的标示,并且在 Binder 通信时会根据UID/PID 进行有效性检测
  3. Client/Server 架构

    • 这种架构使得通讯更为简单

总结

Binder 机制的学习过程是痛苦的 T.T,即使光看 Java 层也费了不少功夫,这可能是由于我实战中没有遇到,光看源码和抽象概念掌握太慢的原因吧。

本文简单介绍了 Binder 机制,参考了很多优秀的文章,真佩服他们!

借用《Android 开发艺术探索》对 Binder 的概括:

  • 从代码角度来看,Binder 是一个类,实现了 IBinder 接口;
  • 从来源看,Binder 来自于 OpenBinder,是 Android IPC 机制中的一种,Binder 还可以理解成一个虚拟物理设备,设备驱动是dev/binder;
  • 从 Framework 层看,Binder 是 Service Manager 连接各种Manager(ActivityManager,PackageManager…) 和相应Service (ActivityManagerService, PackageManagerService…) 的桥梁;
  • 从客户端看,Binder 是客户端服务器通讯的媒介。

 

 

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. ActivityGroup详解

    本文转载自http://blog.csdn.net/caowenbin/article/details/5876019 此前,我们对Activity进行了一些学习,在Android中,还提供了一个ActivityGroup类,该类是Activity的容器,可以包含多个嵌套进来的Activitys,我们接下来依然采用源码分析的方式来了解该类的内部实现。 首先…...

    2024/4/28 4:21:06
  2. 读《高效能人士七个习惯》总结

    高效能人士的七个习惯 之个人领域的成功: 1、积极主动:自由选择回应,不受外界干扰。 2、以终为始:即自我领导;先构思、认清目标再执行。 3、要事优先:即自我管理;将事务排好优先级,把时间花在重要但不紧迫的事上。 高效能人士的七个习惯 之公共领域的成功: 1、双赢思维…...

    2024/4/28 17:58:03
  3. html的button的onserverclick事件不管用

    将<input type="button" />换成<input type="submit" />就ok了。...

    2024/4/28 22:41:19
  4. Python爬虫基础知识及前期准备

    学习爬虫有一小段时间了,于是决定把自己学爬虫时所学的,写过的代码以及看过的文档记录下来,权当小结。第一次写这些,如果有错误,请多指教。首先我们需要了解一下什么是爬虫。根据百度百科上给出的定义,” 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常…...

    2024/4/28 5:09:03
  5. ActivityGroup---activity的管理器

    通过名字,就应该知道ActivityGroup是一个Activity的管理器,对于一组Activity的管理非常方面。下面是实例代码: ActivityGroupTest.java[java] viewplain copypackage app.imo; import android.app.ActivityGroup; import android.content.Intent; import android.os.Bu…...

    2024/4/28 5:23:27
  6. [Innost]Android深入浅出之Binder机制

    ZZ FROM:http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html================================================================Android深入浅出之Binder机制 一 说明Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制…...

    2024/4/28 4:16:48
  7. 爬虫课程一(爬虫的概念与HTTP的复习)

    目前在学习爬虫的课程以下小坐总结:第一天主要看了以写爬虫的原理以及爬虫数据的抓取一1.1:为什么学习爬虫最主要的是在目前看来,爬虫工程师属于紧缺型人才,并且薪资待遇普遍较高1,学习爬虫,可以私人定制一个搜索引擎。2,大数据时代,要进行数据分析,首先要有数据源3,…...

    2024/4/28 10:48:42
  8. 《高效能人士7个习惯》读书心得

    个人成长篇-----------构建自主的独立的人格1.打破旧的思维惯性的旧模式,将原有刺激→反应旧习惯模式,改为由刺激→自我选择习惯模式(自我意识、想象力、良知、独立意志)2.积极主动,随时培养自己随时具备选择的能力,养成积极主动习惯。习惯改变由三者的交集形成(技能、愿…...

    2024/4/27 23:51:08
  9. Spark SQL:从入门到精通(二)[IDEA开发Spark SQL]

    创建DataFrame/DataSet Spark会根据文件信息尝试着去推断DataFrame/DataSet的Schema,当然我们也可以手动指定,手动指定的方式有以下几种: 第1种:指定列名添加Schema 第2种:通过StructType指定Schema 第3种:编写样例类,利用反射机制推断Schema 指定列名添加Schema packag…...

    2024/4/17 4:25:48
  10. 从源码角度分析Android中的Binder机制的前因后果

    前面我也讲述过一篇文章《带你从零学习linux下的socket编程》,主要是从进程通信的角度开篇然后延伸到linux中的socket的开发。本篇文章依然是从进程通信的角度去分析下Android中的进程通信机制。为什么在Android中使用binder通信机制?众所周知linux中的进程通信有很多种方式,…...

    2024/4/19 23:52:40
  11. ActivityGroup相关--getLocalActivityManager() 【转载】

    ActivityGroup简介 1.ActivityGroup的核心就是继承了该类,能够通过getLocalActivityManager()得到一个LocalActivityManager如,LocalActivityManager am= getLocalActivityManager(); 2.然后通过LocalActivityManager通过startActivity(String id, Intent intent),可以与指定…...

    2024/4/28 18:34:43
  12. 高效能人士的七个习惯——习惯一:积极主动

    我以前所理解积极主动是,做事的时候表现的非常积极,主动去做一些事情而不是等着领导分配任务才去开始。这是比较狭隘的一种理解。积极主动不仅仅指行事态度,还意味着人一定要为自己的人生负责。它强调的是:个人行为取决于自身的抉择,而不是外在的环境。一种不愿意承担责任…...

    2024/4/17 4:26:00
  13. 爬虫及相关概念的简述

    爬虫及相关概念的简述 什么是爬虫?网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。爬虫应用的一些例子搜索引擎 : 当你在百度/谷歌中输入关键字搜索的时候,会跳出一些相关…...

    2024/4/18 7:20:59
  14. form中button提交表单

    发现:springmvc 项目,js校验不通过,return后,表单依然可以提交。原因:form表单下的按钮在没有指定type类型的时候,如果我们同时给其添加了点击事件的话。会发现我们在点击的时候回默认的把表单也给提交了 https://www.w3.org/TR/2011/WD-html5-20110525/the-button-eleme…...

    2024/4/21 0:47:45
  15. Elasticsearch教程-从入门到精通

    各位运维同行朋友们,大家好,非常高兴能有这么个机会与大家一起交流一些技术问题。此前的各位分享达人们在技术领域或管理领域均有十分精彩的分享,他们带给我们的是多个领域中研究或实践的最前沿知识。这使我本人获益良多,首先要郑重感谢他们。开始之前,本人首先做一下自我…...

    2024/4/20 17:20:18
  16. 网站开发进阶(四十四)input type="submit" 和"button"的区别

    网站开发进阶(四十四)input type=”submit” 和”button”的区别在一个页面上画一个按钮,有四种办法:这就是一个按钮。如果你不写javascript 的话,按下去什么也不会发生。这样的按钮用户点击之后会自动提交 form,除非你写了javascript 阻止它。这个按钮放在 form 中也会点…...

    2024/4/17 4:26:06
  17. 《高效能人士的7个习惯》——习惯三:要事第一 之 独立意志的重要性

    重要之事决不可受芝麻绿豆小事牵绊。 —— 歌德(Goethe)|德国诗人高效能人士的7个习惯之三——要事第一。其核心我认为能用歌德的这句话概括之。在了解“习惯三:要事第一”之前,让我们先回顾一下习惯一和习惯二分别是什么。习惯一:积极主动 告诉你:“你是创造者,你掌控…...

    2024/4/20 2:03:47
  18. Python爬虫初级(十三)—— 水木社区论坛爬取实战

    上一篇文章:Python爬虫初级(十二)—— 新闻消息抓取实战 实战阶段一:分析首页大板块 URL 我们首先打开待爬取页面 —— 水木社区的首页:http://www.newsmth.net/nForum/#!mainpage,进入后页面如下: 我们看到左边有很多讨论区板块,我们点进去试试:我们现在就已经点进去…...

    2024/4/17 4:25:42
  19. 3分钟带你看懂android中的Binder机制

    3分钟带你看懂android中的Binder机制https://www.jianshu.com/p/beebcd0c2e85...

    2024/4/17 4:26:06
  20. 《Oracle.11g.从入门到精通》书籍错误

    首先说明下,本人只是一个普通的开发人员,并不是针对此书,在读这本书的时候通过理解加实践操作得出了一些结论显示此书中有一些错误,可能不正确,希望贴出操作及相关代码指正,以供大家共同进步,谢谢! 错误一、P83, update语句后面只能跟一个表,不能同时修改多个表,书上…...

    2024/4/17 4:25:36

最新文章

  1. 一文讲解Android车载系统camera架构 - EVS

    Android的camera开发中&#xff0c;使用最多的是camera2 以及现在Google主推的cameraX 架构&#xff0c;而这两个架构主要针对的是手机移动端上camera的流程。 而今天介绍的EVS(Exterior View System)架构是不同于camera2上的手机架构&#xff0c;针对Automotive的版本&#x…...

    2024/4/29 1:04:20
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. [实战经验]Mybatis的mapper.xml参数#{para}与#{para, jdbcType=BIGINT}有什么区别?

    在MyBatis框架中&#xff0c;传入参数使用#{para}和#{para, jdbcTypeBIGINT}的有什么区别呢&#xff1f; #{para}&#xff1a;这种写法表示使用MyBatis自动推断参数类型&#xff0c;并根据参数的Java类型自动匹配数据库对应的类型。例如&#xff0c;如果参数para的Java类型是Lo…...

    2024/4/26 8:43:28
  4. npm常用命令技巧

    NPM (Node Package Manager) 是 JavaScript 的包管理工具&#xff0c;广泛用于管理项目中的依赖。无论是前端项目还是Node.js后端项目&#xff0c;NPM 都扮演着重要的角色。本文将介绍 NPM 中常用的几个命令&#xff0c;并提供相应的代码示例。 1. 初始化项目&#xff1a;npm …...

    2024/4/28 21:50:48
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/28 13:52:11
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/28 3:28:32
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/26 23:05:52
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/28 13:51:37
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/28 15:57:13
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/28 1:22:35
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/25 18:39:14
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/4/26 23:04:58
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/26 19:46:12
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/27 11:43:08
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/27 8:32:30
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57