当前位置: 首页 > news >正文

车机开发—【CarService启动流程】

汽车架构:车载HAL是汽车与车辆网络服务之间的接口定义(同时保护传入的数据):

车载HAL与Android Automotive架构:

  • Car App:包括OEM和第三方开发的App
  • Car API:内有包含CarSensorManager在内的API。位于/platform/packages/services/Car/car-lib
  • CarService:系统中与车相关的服务,位于/platform/packages/services/Car/
  • Vehicle HAL:汽车的硬件抽象层描述。位于hardware/interfaces/automotive/vehicle/2.0/default/(接口属性:hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/)

Framework CarService

Android O/P为Automotive场景提供了一系列的服务,这些服务统被称为CarService。它们与HAL层的VehicleHAL通信,进而通过车载总线(例如CAN总线)与车身进行通讯,同时它们还为应用层的APP提供接口,从而让APP能够实现对车身的控制与状态的显示

  • Car***Manager:packages/services/Car/car-lib/src/android/car/hardware
  • Car***Service:packages/services/Car/service/src/com/android/car/

CarService启动流程

和汽车相关的服务的启动主要依靠一个系统服务CarServiceHelperService开机时在SystemServer中启动:

CarServiceHelperService启动

private static final String CAR_SERVICE_HELPER_SERVICE_CLASS ="com.android.internal.car.CarServiceHelperService";private void startOtherServices(@NonNull TimingsTraceAndSlog t) {......​if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {t.traceBegin("StartCarServiceHelperService");mSystemServiceManager.startService(CAR_SERVICE_HELPER_SERVICE_CLASS);t.traceEnd();}......}

CarServiceHelperService被定义在frameworks/opt/car/下,它和其他系统服务一样,属于SystemService的子类,通过SystemServiceManager.startService启动:

SystemServiceManager.startService

public SystemService startService(String className) {final Class<SystemService> serviceClass = loadClassFromLoader(className,this.getClass().getClassLoader());return startService(serviceClass);}private static Class<SystemService> loadClassFromLoader(String className,ClassLoader classLoader) {try {return (Class<SystemService>) Class.forName(className, true, classLoader);} catch (ClassNotFoundException ex) {...}}

loadClassFromLoader通过类加载器直接获取CarServiceHelperService的class对象,拿到class对象进而再调用startService重载方法:

    public <T extends SystemService> T startService(Class<T> serviceClass) {try {final String name = serviceClass.getName();
​
​// Create the service.if (!SystemService.class.isAssignableFrom(serviceClass)) {throw new RuntimeException("Failed to create " + name+ ": service must extend " + SystemService.class.getName());}final T service;try {Constructor<T> constructor = serviceClass.getConstructor(Context.class);service = constructor.newInstance(mContext);} catch (InstantiationException ex) {...} catch (IllegalAccessException ex) {...} catch (NoSuchMethodException ex) {...} catch (InvocationTargetException ex) {...}startService(service);return service;} finally {Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);}}
​

接着通过反射构造CarServiceHelperService的实例对象,然后再调用startService重载方法:

 public void startService(@NonNull final SystemService service) {// Register it.mServices.add(service);// Start it.long time = SystemClock.elapsedRealtime();try {service.onStart();} catch (RuntimeException ex) {throw new RuntimeException("Failed to start service " + service.getClass().getName()+ ": onStart threw an exception", ex);}warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");}

这里先将CarServiceHelperService保存到mServices这个list中,然后调用CarServiceHelperService的onStart方法正式启动此服务。

CarServiceHelperService.onStart

 @Overridepublic void onStart() {EventLog.writeEvent(EventLogTags.CAR_HELPER_START, mHalEnabled ? 1 : 0);
​IntentFilter filter = new IntentFilter(Intent.ACTION_REBOOT);filter.addAction(Intent.ACTION_SHUTDOWN);mContext.registerReceiverForAllUsers(mShutdownEventReceiver, filter, null, null);mCarWatchdogDaemonHelper.addOnConnectionChangeListener(mConnectionListener);mCarWatchdogDaemonHelper.connect();Intent intent = new Intent();intent.setPackage("com.android.car");intent.setAction(ICarConstants.CAR_SERVICE_INTERFACE);if (!mContext.bindServiceAsUser(intent, mCarServiceConnection, Context.BIND_AUTO_CREATE,UserHandle.SYSTEM)) {Slog.wtf(TAG, "cannot start car service");}loadNativeLibrary();}

这里首先注册了开关机广播,CarWatchdogDaemonHelper用于监控此服务,接着会绑定一个包名为"com.android.car",Action为"android.car.ICar"的服务,这就是系统中和汽车相关的核心服务CarService,相关源代码在packages/services/Car/service目录下,然后我们先去看看CarService,等下再回头来看绑定此服务之后的mCarServiceConnection回调部分。

如下是CarService的AndroidManifest部分截图,可以看到CarService的sharedUserId是系统级别的,这是一个系统级服务,类似SystemUI,它编译出来同样是一个APK文件。 来具体看CarService,它的onStartCommand没什么东西,主要来看onBind:

CarService.onBind

@Overridepublic IBinder onBind(Intent intent) {return mICarImpl;}

ICarImpl是一个Binder服务端,其顶级接口为ICar,在onCreate中初始化:

CarService.onCreate

 @Overridepublic void onCreate() {//通知用户有关 CAN 总线故障 mCanBusErrorNotifier = new CanBusErrorNotifier(this /* context */);//获取Vehicle hal的client端mVehicle = getVehicle();if (mVehicle == null) {throw new IllegalStateException("Vehicle HAL service is not available.");}try {mVehicleInterfaceName = mVehicle.interfaceDescriptor();} catch (RemoteException e) {...}//实例化ICarImplmICarImpl = new ICarImpl(this,mVehicle,SystemInterface.Builder.defaultSystemInterface(this).build(),mCanBusErrorNotifier,mVehicleInterfaceName);//初始化mICarImpl.init();//Vehicle hal对端死亡回调linkToDeath(mVehicle, mVehicleDeathRecipient);//将mICarImpl注册到ServiceManagerServiceManager.addService("car_service", mICarImpl);//修改boot.car_service_created属性为1SystemProperties.set("boot.car_service_created", "1");super.onCreate();}

此方法中主要会对ICarImpl实例化,之后init进行初始化,最后将其注册到ServiceManager。

ICarImpl构造方法

ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,CanBusErrorNotifier errorNotifier, String vehicleInterfaceName,@Nullable CarUserService carUserService,@Nullable CarWatchdogService carWatchdogService) {......mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext, mCarUserService);mCarBluetoothService = new CarBluetoothService(serviceContext, mPerUserCarServiceHelper);mCarInputService = new CarInputService(serviceContext, mHal.getInputHal(), mCarUserService);mCarProjectionService = new CarProjectionService(serviceContext, null /* handler */, mCarInputService, mCarBluetoothService);mGarageModeService = new GarageModeService(mContext);mAppFocusService = new AppFocusService(serviceContext, mSystemActivityMonitoringService);mCarAudioService = new CarAudioService(serviceContext);mCarNightService = new CarNightService(serviceContext, mCarPropertyService);mFixedActivityService = new FixedActivityService(serviceContext);mInstrumentClusterService = new InstrumentClusterService(serviceContext,mAppFocusService, mCarInputService);mSystemStateControllerService = new SystemStateControllerService(serviceContext, mCarAudioService, this);mCarStatsService = new CarStatsService(serviceContext);mCarStatsService.init();if (mFeatureController.isFeatureEnabled(Car.VEHICLE_MAP_SERVICE)) {mVmsBrokerService = new VmsBrokerService(mContext, mCarStatsService);} else {mVmsBrokerService = null;}if (mFeatureController.isFeatureEnabled(Car.DIAGNOSTIC_SERVICE)) {mCarDiagnosticService = new CarDiagnosticService(serviceContext,mHal.getDiagnosticHal());} else {mCarDiagnosticService = null;}if (mFeatureController.isFeatureEnabled(Car.STORAGE_MONITORING_SERVICE)) {mCarStorageMonitoringService = new CarStorageMonitoringService(serviceContext,systemInterface);} else {mCarStorageMonitoringService = null;}mCarConfigurationService =new CarConfigurationService(serviceContext, new JsonReaderImpl());mCarLocationService = new CarLocationService(serviceContext);mCarTrustedDeviceService = new CarTrustedDeviceService(serviceContext);mCarMediaService = new CarMediaService(serviceContext, mCarUserService);mCarBugreportManagerService = new CarBugreportManagerService(serviceContext);......CarLocalServices.addService(CarPowerManagementService.class, mCarPowerManagementService);CarLocalServices.addService(CarPropertyService.class, mCarPropertyService);CarLocalServices.addService(CarUserService.class, mCarUserService);CarLocalServices.addService(CarTrustedDeviceService.class, mCarTrustedDeviceService);CarLocalServices.addService(CarUserNoticeService.class, mCarUserNoticeService);CarLocalServices.addService(SystemInterface.class, mSystemInterface);CarLocalServices.addService(CarDrivingStateService.class, mCarDrivingStateService);CarLocalServices.addService(PerUserCarServiceHelper.class, mPerUserCarServiceHelper);CarLocalServices.addService(FixedActivityService.class, mFixedActivityService);CarLocalServices.addService(VmsBrokerService.class, mVmsBrokerService);.....List<CarServiceBase> allServices = new ArrayList<>();allServices.add(mFeatureController);allServices.add(mCarUserService);allServices.add(mSystemActivityMonitoringService);allServices.add(mCarPowerManagementService);allServices.add(mCarPropertyService);allServices.add(mCarDrivingStateService);...mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]);
}

这里省略了和Vehicle hal有关的初始化和分析,后续文章再看。

ICarImpl构造方法中创建了一系列CarService模块下的服务,这些服务有部分被添加到了CarLocalServices内部,其提供了getService静态方法用于直接获取这些服务,所有服务都被保存在ICarImpl内部的CarServiceBase类型数组mAllServices中(所有服务都是CarServiceBase的子类)。

ICarImpl构造方法完了之后会接着调用其init方法:

ICarImpl.init

 @MainThreadvoid init() {mBootTiming = new TimingsTraceLog(VHAL_TIMING_TAG, Trace.TRACE_TAG_HAL);traceBegin("VehicleHal.init");//hal初始化//...省略traceEnd();traceBegin("CarService.initAllServices");for (CarServiceBase service : mAllServices) {service.init();}traceEnd();}

此方法很简单,遍历mAllServices,分别执行所有服务的init,各自初始化,有兴趣的可以自己去研究各个服务。

到此ICarImpl初始化完毕,最后会作为binder返回给绑定此服务的mCarServiceConnection:

private final ServiceConnection mCarServiceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {if (DBG) {Slog.d(TAG, "onServiceConnected:" + iBinder);}handleCarServiceConnection(iBinder);}
​@Overridepublic void onServiceDisconnected(ComponentName componentName) {handleCarServiceCrash();}};

CarServiceHelperService.handleCarServiceConnection

   void handleCarServiceConnection(IBinder iBinder) {...synchronized (mLock) {if (mCarService == iBinder) {return; // already connected.}mCarService = iBinder;...sendSetCarServiceHelperBinderCall();......}}

这个方法我们主要关注上面部分,返回的ICarImpl被保存在了CarServiceHelperService的mCarService,后续可通过mCarService跨进程通信。

CarServiceHelperService.sendSetCarServiceHelperBinderCallprivate void sendSetCarServiceHelperBinderCall() {Parcel data = Parcel.obtain();data.writeInterfaceToken(ICarConstants.CAR_SERVICE_INTERFACE);data.writeStrongBinder(mHelper.asBinder());// void setCarServiceHelper(in IBinder helper)sendBinderCallToCarService(data, ICarConstants.ICAR_CALL_SET_CAR_SERVICE_HELPER);}

这里将会进行跨进程通信,首先构造传输数据,ICarConstants是定义在ExternalConstants的静态内部类:

     static final class ICarConstants {....static final String CAR_SERVICE_INTERFACE = "android.car.ICar";static final int ICAR_CALL_SET_CAR_SERVICE_HELPER = 0;....}

CAR_SERVICE_INTERFACE用来标识远程服务接口,其具体传输数据是一个Binder对象,我们来看看mHelper是什么?

​private final ICarServiceHelperImpl mHelper = new ICarServiceHelperImpl();

mHelper是定义在CarServiceHelperService的内部类,是一个Binder对象:

private class ICarServiceHelperImpl extends ICarServiceHelper.Stub {...........
}

CarServiceHelperService.sendBinderCallToCarService 再回到前面看sendBinderCallToCarService方法:

private void sendBinderCallToCarService(Parcel data, int callNumber) {// Cannot depend on ICar which is defined in CarService, so handle binder call directly// instead.IBinder carService;synchronized (mLock) {carService = mCarService;}if (carService == null) {Slog.w(TAG, "Not calling txn " + callNumber + " because service is not bound yet",new Exception());return;}int code = IBinder.FIRST_CALL_TRANSACTION + callNumber;try {carService.transact(code, data, null, Binder.FLAG_ONEWAY);} catch (RemoteException e) {handleCarServiceCrash();} catch (RuntimeException e) {throw e;} finally {data.recycle();}}

这个方法很明显就是跨进程传输的具体实现了,对端是mCarService即ICarImpl,调用binder的transact进行跨进程通信,其code代表需要调用的对端方法,data为携带的传输数据,ICAR_CALL_SET_CAR_SERVICE_HELPER等于0,这里调用的是对端的0号方法。

于是我们来看看ICar.aidl中定义的0号方法:

interface ICar {.....oneway void setCarServiceHelper(in IBinder helper) = 0;......}

ICarImpl.setCarServiceHelper

接着来看setCarServiceHelper具体实现:

 @Overridepublic void setCarServiceHelper(IBinder helper) {//权限检查assertCallingFromSystemProcess();ICarServiceHelper carServiceHelper = ICarServiceHelper.Stub.asInterface(helper);synchronized (mLock) {mICarServiceHelper = carServiceHelper;}mSystemInterface.setCarServiceHelper(carServiceHelper);mCarOccupantZoneService.setCarServiceHelper(carServiceHelper);}

这里将ICarServiceHelper的代理端保存在ICarImpl内部mICarServiceHelper,同时也传给了SystemInterface和CarOccupantZoneService,我们暂时不需要知道这三个类拿到ICarServiceHelper的代理端的具体用处,只需要知道他们有能力跨进程访问CarServiceHelperService就行了。

全文解析了车机开发中CarFramework框架的CarService启动流程;车机开发的知识点非常的多;总结如上图资料文档参考《车载技术手册》,里面内容包含以上进阶技术。

CarService启动流程总结

  • 首先CarService是一个系统级别的服务APK,类似SystemUI,其在开机时由SystemServer通过CarServiceHelperService启动。
  • CarServiceHelperService通过绑定服务的方式启动CarService,启动之后创建了一个Binder对象ICarImpl,并通过onBind返回给system_server进程。
  • ICarImpl构造方法中创建了一系列和汽车相关的核心服务,并依次启动这些服务即调用各自init方法。
  • ICarImpl返回给CarServiceHelperService之后,CarServiceHelperService也将其内部的一个Binder对象(ICarServiceHelperImpl)传递到了CarService进程,自此CarService和system_server两个进程建立了双向Binder通信。

相关文章:

车机开发—【CarService启动流程】

汽车架构&#xff1a;车载HAL是汽车与车辆网络服务之间的接口定义&#xff08;同时保护传入的数据&#xff09;&#xff1a; 车载HAL与Android Automotive架构&#xff1a; Car App&#xff1a;包括OEM和第三方开发的AppCar API&#xff1a;内有包含CarSensorManager在内的AP…...

webpack中require.context的运用

1. 作用&#xff1a; 利用require创建context (上下文)&#xff0c;来告知在编译时具体需要导入哪些模块(即&#xff1a;批量处理待导入模块进行导入)&#xff1b; webpack会在构建的时候解析代码中的require.context() (实际上是webpack的方法&#xff0c;vue一般基于webpack…...

2023“Java基础-中级-高级”面试集结,已奉上我的膝盖

Java基础&#xff08;对象线程字符接口变量异常方法&#xff09; 面向对象和面向过程的区别&#xff1f; Java 语言有哪些特点&#xff1f; 关于 JVM JDK 和 JRE 最详细通俗的解答 Oracle JDK 和 OpenJDK 的对比 Java 和 C的区别&#xff1f; 什么是 Java 程序的主类&…...

RabbitMQ之发布确认

发布确认 1 发布确认原理 生产者将信道设置成 confirm 模式,一旦信道进入 confirm 模式,所有在该信道上面发布的消息都将会被指派一个唯一的 ID(从 1 开始),一旦消息被投递到所有匹配的队列之后,broker就会发送一个确认给生产者(包含消息的唯一 ID),这就使得生产者知道消…...

一文读懂函数编程及其工作原理

微软MVP实验室研究员 马洪喜-微软 MVP 19年研发经验 云计算咨询顾问专家 容器云及基础架构云技术专家 DevOps 及微服务咨询专家 什么是函数编程 我先用通俗的大白话给大家解释一下函数(Functions, Function as a Service, FaaS)的几个要点&#xff0c;这样看后面示例时才不…...

WSO2 apim Subscribe to an API

WSO2 apim Application Subscribe to an API1. Published an Api2. Subscribe to an API using Key Generation Wizard3. Subscribe to an existing application4. AwakeningWSO2安装使用的全过程详解: https://blog.csdn.net/weixin_43916074/article/details/127987099. Offi…...

聚类(性能度量)

文章目录聚类&#xff08;性能度量&#xff09;外部指标例1内部指标例2聚类&#xff08;性能度量&#xff09; 对数据集 D{x1,x2,...,xm}D\{x_1,x_2,...,x_m\}D{x1​,x2​,...,xm​} &#xff0c;假定通过聚类给出的簇划分为 C{C1,C2,...,Ck}C\{C_1,C_2,...,C_k\}C{C1​,C2​,…...

GPT-4——比GPT-3强100倍

GPT-4——比GPT-3强100倍 当前世界上最强大的人工智能系统当属ChatGPT。推出2个月用户数就突破1亿。ChatGPT是当下最炙手可热的话题&#xff0c;科技圈几乎人人都在讨论。这边ChatGPT的热度还在不断攀升&#xff0c;另一边来自《纽约时报》的最新报道称ChatGPT即将被自家超越&…...

echart中x轴数据过多时展示不全

项目中遇到需要展示一些柱状图&#xff0c;之前做相关功能时&#xff0c;横坐标x轴一直用的是时间&#xff0c;所以没有注意到这个问题。 如下图所示&#xff1a; 当x轴显示的是”人名“这种类型的值的时候&#xff0c;这种显示情况就有问题了&#xff0c;这样就不会知道&…...

关于GIS原理的实际分析应用题的一些解法

话不多说&#xff0c;看题.01 公园选址问题1题目请写出利用GIS技术进行公园选址的空间操作步骤。其中公园选址条件:1&#xff09;为了安静舒适&#xff0c;要求该园区离主要公路1公里以外&#xff0c;且交通方便&#xff0c;离主要公路3公里以内。2&#xff09;公园最好依附在大…...

混合精度训练,FP16加速训练,降低内存消耗

计算机中的浮点数表示&#xff0c;按照IEEE754可以分为三种&#xff0c;分别是半精度浮点数、单精度浮点数和双精度浮点数。三种格式的浮点数因占用的存储位数不同&#xff0c;能够表示的数据精度也不同。 Signed bit用于控制浮点数的正负&#xff0c;0表示正数&#xff0c;1表…...

每天五分钟机器学习:新的大规模的机器学习机制——在线学习机制

本文重点 本节课程我们将学习一种新的大规模的机器学习机制--在线学习机制。在线学习机制让我们可以模型化问题。在线学习算法指的是对数据流进行学习而非离线的静态数据集的学习。许多在线网站都有持续不断的用户流,对于每一个用户,网站希望能在不将数据存储到数据库中便顺…...

计算机组成原理错题

静态RAM&#xff08;SRAM&#xff09;和动态RAM&#xff08;DRAM&#xff09;的基本电路图不同&#xff0c;因此可以通过观察存储器的基本电路图来判断它属于哪一类。 静态RAM的基本电路图包括一个存储单元和一个数据选择器。每个存储单元由一个触发器&#xff08;flip-flop&a…...

数学基础整理

收纳一些天天忘的结论qwq 线性求逆元 invi(p−pi)invpmodiinv_i(p-\dfrac{p}{i})\times inv_{p\bmod i}invi​(p−ip​)invpmodi​ 卡特兰数 组合数公式&#xff1a;HnC2nn−C2nn−1H_nC_{2n}^n-C_{2n}^{n-1}Hn​C2nn​−C2nn−1​ 递推式&#xff1a;HnHn−1(4n−2)n1H_n\d…...

JavaWeb11-死锁

目录 1.死锁定义 1.1.代码演示 1.2.使用jconsole/jvisualvm/jmc查看死锁 ①使用jconsole&#xff1a;最简单。 ②使用jvisualvm&#xff1a;&#xff08;Java虚拟机&#xff09;更方便&#xff0c;更直观&#xff0c;更智能&#xff0c;更高级&#xff0c;是合适的选择。 …...

堆的概念和结构以及堆排序

前言 普通的二叉树是不适合用数组来存储的&#xff0c;因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结 构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储&#xff0c;需要注意的是这里的堆和操作系统 虚拟进程地址空间中的堆是两回事&#xff0c…...

【Linux学习笔记】1.Linux 简介及安装

前言 本章介绍Linux及其安装方法。 Linux 简介 Linux 内核最初只是由芬兰人林纳斯托瓦兹&#xff08;Linus Torvalds&#xff09;在赫尔辛基大学上学时出于个人爱好而编写的。 Linux 是一套免费使用和自由传播的类 Unix 操作系统&#xff0c;是一个基于 POSIX 和 UNIX 的多…...

代码练习2~

在一个二维数组中&#xff08;每个一维数组的长度相同&#xff09;&#xff0c;每一行都按照从左到右递增的顺序排序&#xff0c;每一列都按照从上到下递增的顺序排序。请完成一个函数&#xff0c;输入这样的一个二维数组和一个整数&#xff0c;判断数组中是否含有该整数。def …...

微信小程序 之 云开发

一、概念1. 传统开发模式2. 新开发模式 ( 云开发模式 )3. 传统、云开发的模式对比4. 传统、云开发的项目流程对比5. 云开发的定位1. 个人的项目或者想法&#xff0c;不想开发服务器&#xff0c;直接使用云开发2. 某些公司的小程序项目是使用云开发的&#xff0c;但是不多&#…...

程序员的三门课,学习成长笔记

最近是有了解到一本好书&#xff0c;叫做程序员的三门课在这本书的内容当中我也确实汲取到了很多前辈能够传达出来的很多关于程序员职业规划以及成长路线上的见解&#xff0c;令我受益匪浅&#xff0c;故此想要把阅读完的每一章节结合自己的工作经验做一个精细化的小结&#xf…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...