Android 12系统源码_屏幕设备(一)DisplayManagerService的启动
前言
DisplayManagerService是Android Framework中管理显示屏幕相关的模块,各种Display的连接、配置等,都是通过DMS和来管理控制。
在DMS模块中,对显示屏幕的描述分为物理显示屏(physical display)和逻辑显示屏(logical display),物理屏主要从SurfaceFlinger中读取参数创建,代表实实在在的物理屏,描述其物理特性,不同物理屏有不同的属性。逻辑屏则是相对于对物理屏,侧重于同一个物理屏的不同逻辑设置,受应用和WMS模块影响,如显示区域、显示位置坐标、显示方向等。每一个物理屏幕都对应一个逻辑屏幕,可以修改逻辑屏幕参数,做到同一个物理屏的不同显示方式。
由于不同的物理显示屏有不同的属性和处理方式,因此DMS中通过一系列的屏幕适配器(DisplayAdapter)来和分别各种物理显示屏进行连接。
一、DMS模块常见类
1.1 全局管理类
- IDisplayManager: IBinder接口,负责DMS和其他组建的IPC工作;
- DisplayManagerService:继承于SystemService的系统服务,负责整个系统display的控制和管理;
- DisplayManagerService.LocalService: 继承于DisplayManagerInternal,负责system_server内部其他模块和DMS的交互;
- DisplayManagerService.BindService: 继承于IDisplayManager,是IDisplayManager的具体实现类;
- DisplayManagerService.CallbackRecord: DMS内部类,内部持有IDisplayManagerCallback对象,负责执行IDisplayManagerCallback的回调;
- DisplayManager: 暴露给App层的接口,内部持有DisplayManagerGlobal对象引用,利用DisplayManagerGlobal和DMS进行交互;
- IDisplayManagerCallback:一个IBinder接口,DMS中发生display相关动作后,会通过该接口回调通知给DisplayManagerGlobal;
- DisplayManagerGlobal:内部持有IDisplayManager对象引用,App层通过该对象和DMS进行跨IPC交互;
- DisplayManagerGlobal.DisplayManagerCallback: 继承于IDisplayManagerCallback接口,负责接收来自DMS中display事件的回调;
1.2 数据封装类
- DisplayDevice: 屏幕设备对象。
- DisplayDeviceRepository:屏幕设备管理者,内部持有DisplayDevice集合,负责管理屏幕设备对象。
- WifiDisplayDevice:DisplayDevice的子类,代表通过Wifi连接显示的物理屏幕;
- OverlayDisplayDevice:DisplayDevice的子类,开发者选项->模拟辅助显示开启后,创建的就是该类对象;
- VirtualDisplayDevice:DisplayDevice的子类,表示虚拟显示屏幕,用于屏幕录制等;
- LocalDisplayDevice:DisplayDevice的子类,代表内置物理屏幕,DMS启动后会通过SurfaceControl去读取内置屏幕数据,并创建该类对象;
- LogicalDisplay:代表逻辑显示屏,每一个physical display都会对应一个logical display;
- LogicalDisplayMapper:逻辑屏幕设备管理者,内部持有LogicalDisplay对象集合
- DisplayDeviceInfo: DisplayDevice信息封装类,在创建DisplayDevice时会进行创建,与之对应的是Logical display 的DisplayInfo;
- DisplayInfo:LogicalDisplay信息的封装类,基本数据由DisplayDeviceInfo中获得,app可以通过WMS来修改自己的参数;
- DisplayAdapter: 各物理屏和DMS进行连接的适配器;
- LocalDisplayAdapter: 继承于DisplayAdapter, 用于LocalDisplayDevice和DMS的连接;
- WifiDisplayAdapter: 继承于DisplayAdapter,用于WifiDisplayDevice的和DMS的连接;
- OverlayDisplayAdapter:继承于DisplayAdapter,用于OverlayDisplayDevice和DMS的连接;
- VirtualDisplayAdapter:继承于DisplayAdapter,用于VirtualDisplayDevice和DMS的连接;
- DisplayAdapter.Listener:用于通知DisplayDevice发生变化的接口,DMS中对其进行了实现,会接收以下三个事件并根据事件作出全局反应:a.添加了新的DisplayDevice ;b.DisplayDevice状态发生变化; c.移除DisplayDevice。
- DisplayViewport:携带有physical display参数,用于通知IMS display信息。
1.3 基本类结构的对应关系图
1.4 源码位置
包名 | 目录 | 描述 | 例子 |
---|---|---|---|
android.hardware.display | frameworks/base/core/java/android/hardware/display | DMS模块管理 | DisplayManager, DisplayMangaerGlobal, … |
android.view | frameworks/base/core/java/android/view | 逻辑屏配置项相关 | DisplayInfo, DisplayViewport, … |
com.android.server.display | frameworks/base/services/core/java/com/android/server/display | DMS核心 | DMS,DisplayDevice, … |
二、DisplayManagerService的启动流程
系统启动后会启动JVM虚拟机,SystemServer 是虚拟机的第一个进程,由init 进程fork 产生,主要用来启动frameworks层中的服务,DMS服务也是在这里被启动的,下面我们简单列出SystemServer中和DMS启动相关的源码。
frameworks/base/service/java/com/android/server/SystemServer.java
public final class SystemServer {private DisplayManagerService mDisplayManagerService;public static void main(String[] args) {new SystemServer().run();}private void run() {...代码省略...try {t.traceBegin("StartServices");startBootstrapServices(t);//引导服务startCoreServices(t);//核心服务startOtherServices(t);//其他服务} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {t.traceEnd(); // StartServices}...代码省略...}private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {...代码省略...// Display manager is needed to provide display metrics before package manager// starts up.t.traceBegin("StartDisplayManager");mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);//通过反射构建对象实例t.traceEnd();// We need the default display before we can initialize the package manager.t.traceBegin("WaitForDisplay");mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);//调用DMS的onBootPhase方法t.traceEnd();...代码省略...// DisplayManagerService needs to setup android.display scheduling related policies// since setSystemProcess() would have overridden policies due to setProcessGroupmDisplayManagerService.setupSchedulerPolicies();//调用DMS的setupSchedulerPolicies方法...代码省略...}private void startOtherServices(@NonNull TimingsTraceAndSlog t) {...代码省略...t.traceBegin("DisplayManagerWindowManagerAndInputReady");mDisplayManagerService.windowManagerAndInputReady();//调用DMS的windowManagerAndInputReady方法t.traceEnd();...代码省略...t.traceBegin("MakeDisplayManagerServiceReady");try {mDisplayManagerService.systemReady(safeMode, mOnlyCore);//调用DMS的systemReady方法} catch (Throwable e) {reportWtf("making Display Manager Service ready", e);}t.traceEnd();}
}
2.1 构造方法
DisplayManagerService实例对象是通过SystemServiceManager的startService方法获得的,该方法内部先是通过反射构建DisplayManagerService对象实例的,然后还会调用该对象的onStart方法,先来看下构造方法。
frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
public final class DisplayManagerService extends SystemService {private final Context mContext;//android.display线程的Handlerprivate final DisplayManagerHandler mHandler;//android.ui线程Handlerprivate final Handler mUiHandler;//主要负责管理和协调设备的显示模式,包括分辨率、刷新率等。//它优化了系统的显示设置,以平衡性能和电池使用,并确保在多显示器配置下的显示效果一致。private final DisplayModeDirector mDisplayModeDirector;//屏幕设备管理者, 此类内容维护了一个 DisplayDevice 对象的集合,这些对象代表了系统中所有的显示设备。//可以通过这个类跟踪各个显示设备的状态、属性和配置。private final DisplayDeviceRepository mDisplayDeviceRepo;//主要负责逻辑显示设备的映射和管理,确保物理显示设备的状态和配置能够正确映射到逻辑显示设备上。//这个类对于支持多显示器和虚拟显示设备的系统功能至关重要。private final LogicalDisplayMapper mLogicalDisplayMapper;private final Injector mInjector;//负责同步和管理屏幕亮度设置,以确保多个显示设备或显示区域的亮度一致,同时优化用户体验和系统协调。private final BrightnessSynchronizer mBrightnessSynchronizer;public DisplayManagerService(Context context) {this(context, new Injector());}@VisibleForTestingDisplayManagerService(Context context, Injector injector) {super(context);mInjector = injector;mContext = context;//android.display线程handlermHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());//android.ui线程HandlermUiHandler = UiThread.getHandler();//管理所有的屏幕设备mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);//负责逻辑显示设备的映射和管理mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, mDisplayDeviceRepo,new LogicalDisplayListener(), mSyncRoot, mHandler);//负责管理和协调设备的显示模式mDisplayModeDirector = new DisplayModeDirector(context, mHandler);//负责同步和管理屏幕亮度设置mBrightnessSynchronizer = new BrightnessSynchronizer(mContext);Resources resources = mContext.getResources();mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(com.android.internal.R.integer.config_defaultDisplayDefaultColorMode);mDefaultDisplayTopInset = SystemProperties.getInt(PROP_DEFAULT_DISPLAY_TOP_INSET, -1);float[] lux = getFloatArray(resources.obtainTypedArray(com.android.internal.R.array.config_minimumBrightnessCurveLux));float[] nits = getFloatArray(resources.obtainTypedArray(com.android.internal.R.array.config_minimumBrightnessCurveNits));mMinimumBrightnessCurve = new Curve(lux, nits);mMinimumBrightnessSpline = Spline.createSpline(lux, nits);mCurrentUserId = UserHandle.USER_SYSTEM;ColorSpace[] colorSpaces = SurfaceControl.getCompositionColorSpaces();mWideColorSpace = colorSpaces[1];mAllowNonNativeRefreshRateOverride = mInjector.getAllowNonNativeRefreshRateOverride();mSystemReady = false;}
}
2.2 执行onStart方法
public final class DisplayManagerService extends SystemService {private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();@Overridepublic void onStart() {// 加载数据synchronized (mSyncRoot) {mPersistentDataStore.loadIfNeeded();//加载display中的固定数据loadStableDisplayValuesLocked();}// 在android.display线程中创建默认DisplayAdapter,并进行注册mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);// If there was a runtime restart then we may have stale caches left around, so we need to// make sure to invalidate them upon every start.DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();//向ServiceManager注册BinderService,以便其他模块可以跨进程调用publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),true /*allowIsolated*/);//注册Local ServicepublishLocalService(DisplayManagerInternal.class, new LocalService());}}
2.2.1 加载display中的固定数据
frameworks/base/services/core/java/com/android/server/display/PersistentDataStore.java
final class PersistentDataStore {private Injector mInjector;public PersistentDataStore() {this(new Injector());}@VisibleForTestingPersistentDataStore(Injector injector) {mInjector = injector;}public void loadIfNeeded() {if (!mLoaded) {load();mLoaded = true;}}private void load() {clearState();final InputStream is;try {is = mInjector.openRead();} catch (FileNotFoundException ex) {return;}TypedXmlPullParser parser;try {parser = Xml.resolvePullParser(is);loadFromXml(parser);} catch (IOException ex) {Slog.w(TAG, "Failed to load display manager persistent store data.", ex);clearState();} catch (XmlPullParserException ex) {Slog.w(TAG, "Failed to load display manager persistent store data.", ex);clearState();} finally {IoUtils.closeQuietly(is);}}static class Injector {private final AtomicFile mAtomicFile;public Injector() {//display配置的文件路径mAtomicFile = new AtomicFile(new File("/data/system/display-manager-state.xml"), "display-state");}public InputStream openRead() throws FileNotFoundException {return mAtomicFile.openRead();}public OutputStream startWrite() throws IOException {return mAtomicFile.startWrite();}public void finishWrite(OutputStream os, boolean success) {if (!(os instanceof FileOutputStream)) {throw new IllegalArgumentException("Unexpected OutputStream as argument: " + os);}FileOutputStream fos = (FileOutputStream) os;if (success) {mAtomicFile.finishWrite(fos);} else {mAtomicFile.failWrite(fos);}}}
}
利用PersistentDataStore加载display中的固定数据,这些数据都是以xml文件的形式,保存在/data/system/display-manager-state.xml中;
2.2.2 注册屏幕适配器
public final class DisplayManagerService extends SystemService {private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;@Overridepublic void onStart() {...代码省略...// android.display线程中创建默认DisplayAdapter,并进行注册mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);...代码省略...}private final class DisplayManagerHandler extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS://注册默认的屏幕适配器registerDefaultDisplayAdapters();break;case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS://注册额外的屏幕设备适配器registerAdditionalDisplayAdapters();break;...代码省略... }}}private void registerDefaultDisplayAdapters() {synchronized (mSyncRoot) {//注册默认的屏幕适配器registerDisplayAdapterLocked(new LocalDisplayAdapter(mSyncRoot, mContext, mHandler, mDisplayDeviceRepo));//注册虚拟的屏幕适配器mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,mHandler, mDisplayDeviceRepo);if (mVirtualDisplayAdapter != null) {registerDisplayAdapterLocked(mVirtualDisplayAdapter);}}}
}
2.3 执行onBootPhase方法
DisplayManagerService的onStart()方法被执行完毕后,onBootPhase()方法将会被执行。
public final class DisplayManagerService extends SystemService {@Overridepublic void onBootPhase(int phase) {if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {synchronized (mSyncRoot) {//Injector的getDefaultDisplayDelayTimeout默认返回10秒long timeout = SystemClock.uptimeMillis() + mInjector.getDefaultDisplayDelayTimeout();// 超过timeout之后,如果默认屏幕的逻辑显示屏为空,则抛出异常while (mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY) == null|| mVirtualDisplayAdapter == null) {long delay = timeout - SystemClock.uptimeMillis();if (delay <= 0) {throw new RuntimeException("Timeout waiting for default display "+ "to be initialized. DefaultDisplay="+ mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY)+ ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter);}if (DEBUG) {Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);}try {mSyncRoot.wait(delay);} catch (InterruptedException ex) {}}}} else if (phase == PHASE_BOOT_COMPLETED) {mDisplayModeDirector.onBootCompleted();}}
}
PHASE_WAIT_FOR_DEFAULT_DISPLAY阶段是最早的一个启动阶段,当一些引导服务启动完毕后,启动后续服务时,检查DMS是否已经创建默认逻辑屏,如果在10s内没有完成默认LogicalDisplay的创建,则抛出异常。
2.4 执行setupSchedulerPolicies方法
public final class DisplayManagerService extends SystemService {public void setupSchedulerPolicies() {// 给android.display、android.anim、android.anim.lf三个线程设置组和CPU集Process.setThreadGroupAndCpuset(DisplayThread.get().getThreadId(),Process.THREAD_GROUP_TOP_APP);Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(),Process.THREAD_GROUP_TOP_APP);Process.setThreadGroupAndCpuset(SurfaceAnimationThread.get().getThreadId(),Process.THREAD_GROUP_TOP_APP);}}
给以上三个线程设置线程组和调度集,将线程组设为Process.THREAD_GROUP_TOP_APP,以确保更加高效的执行。
2.5 执行windowManagerAndInputReady方法
当SystemServer中启动WindowManagerService和InputManagerService后,将调用此方法通知DMS。
public final class DisplayManagerService extends SystemService {private static final int MSG_REQUEST_TRAVERSAL = 4;//WMS和输入法启动完毕public void windowManagerAndInputReady() {synchronized (mSyncRoot) {mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);//获取设备状态服务并设置回调对象DeviceStateManager deviceStateManager = mContext.getSystemService(DeviceStateManager.class);deviceStateManager.registerCallback(new HandlerExecutor(mHandler), new DeviceStateListener());//通知WMS进行窗口更新流程scheduleTraversalLocked(false);}}private void scheduleTraversalLocked(boolean inTraversal) {if (!mPendingTraversal && mWindowManagerInternal != null) {mPendingTraversal = true;if (!inTraversal) {mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);}}}private final class DisplayManagerHandler extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {...代码省略... case MSG_REQUEST_TRAVERSAL://通知WMS进行窗口更新流程mWindowManagerInternal.requestTraversalFromDisplayManager();break;...代码省略... }}}}
先是获得WMS和IMS各自的LocalService对象,然后将发起显示内容更新流程,请求WMS模块进行窗口更新。DMS和WMS联系非常紧密,通常当DMS中相关属性发生变化后,会通知WMS进行窗口更新,WMS在更新过程中也会通知DMS,应用来自窗口的Display相关属性。
2.6 执行systemReady方法
此方法DMS在SystemServer中被调用的最后一个方法,通知DMS启动完成:
public final class DisplayManagerService extends SystemService {private static final String PROP_DEFAULT_DISPLAY_TOP_INSET = "persist.sys.displayinset.top";private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;//注册物理屏幕适配器、虚拟屏幕适配器private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;//注册其他屏幕适配器public void systemReady(boolean safeMode, boolean onlyCore) {synchronized (mSyncRoot) {mSafeMode = safeMode;mOnlyCore = onlyCore;mSystemReady = true;//启动完成//将默认Display的top inset存储到persist.sys.displayinset.top中recordTopInsetLocked(mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY));updateSettingsLocked();updateUserDisabledHdrTypesFromSettingsLocked();}mDisplayModeDirector.setDesiredDisplayModeSpecsListener(new DesiredDisplayModeSpecsObserver());mDisplayModeDirector.start(mSensorManager);//注册除了物理屏幕适配器、虚拟屏幕适配器以外的其他屏幕适配器mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);mSettingsObserver = new SettingsObserver();mBrightnessSynchronizer.startSynchronizing();}private void recordTopInsetLocked(@Nullable LogicalDisplay d) {if (!mSystemReady || d == null) {return;}int topInset = d.getInsets().top;if (topInset == mDefaultDisplayTopInset) {return;}mDefaultDisplayTopInset = topInset;//将默认Display的top inset存储到persist.sys.displayinset.top中SystemProperties.set(PROP_DEFAULT_DISPLAY_TOP_INSET, Integer.toString(topInset));} private final class DisplayManagerHandler extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS://注册默认的屏幕适配器registerDefaultDisplayAdapters();break;case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS://注册额外的屏幕设备适配器registerAdditionalDisplayAdapters();break;...代码省略... }}}//注册额外的屏幕适配器对象private void registerAdditionalDisplayAdapters() {synchronized (mSyncRoot) {if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {registerOverlayDisplayAdapterLocked();//注册模拟辅助设备屏幕适配器registerWifiDisplayAdapterLocked();//注册WIFI屏幕适配器}}}private void registerOverlayDisplayAdapterLocked() {registerDisplayAdapterLocked(new OverlayDisplayAdapter(mSyncRoot, mContext, mHandler, mDisplayDeviceRepo, mUiHandler));}private void registerWifiDisplayAdapterLocked() {if (mContext.getResources().getBoolean(com.android.internal.R.bool.config_enableWifiDisplay)|| SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {mWifiDisplayAdapter = new WifiDisplayAdapter(mSyncRoot, mContext, mHandler, mDisplayDeviceRepo,mPersistentDataStore);registerDisplayAdapterLocked(mWifiDisplayAdapter);}}private void registerDisplayAdapterLocked(DisplayAdapter adapter) {//将适配器对面添加到适配器集合中mDisplayAdapters.add(adapter);adapter.registerLocked();}
}
此方法该会通过mHandler发起注册其他DeviceAdapter的操作,最终完成四种DisplayAdapter的注册。
三 总结
相关文章:

Android 12系统源码_屏幕设备(一)DisplayManagerService的启动
前言 DisplayManagerService是Android Framework中管理显示屏幕相关的模块,各种Display的连接、配置等,都是通过DMS和来管理控制。 在DMS模块中,对显示屏幕的描述分为物理显示屏(physical display)和逻辑显示屏(logical display),…...
《AI视频类工具之十——D-ID》
一.简介 官网:D-ID | The #1 Choice for AI Generated Video Creation Platform D-ID是一个人工智能生成的视频创建平台,可以轻松快速地从文本输入中创建高质量、高性价比和引人入胜的视频,背后的Al技术是由Stable Difusion和GPT.3提供支持,可以在没有任何技术知识的情况…...

【网络】局域网LAN、广域网WAN、TCP/IP协议、封装和分用
文章目录 局域网 LAN广域网 WAN网络中的重要概念IP 地址端口号 认识协议协议分层是什么OSI 七层网络模型TCP/IP 五层网络模型(或四层)物理层传输层网络层数据链表层应用层网络设备所在分层 封装和分用[站在发送方视角](封装)[站在…...
我司搜索中台的三次演变
本人从入职就开始负责我司的搜索中台了,总共是经历了三个大版本的迭代。 分别是: 基于阿里云智能开放搜索OpenSearch实现的第一代自研,开源canal(数据同步) 底层阿里云elasticsearch 对索引封装 实现的第二代自研&a…...

html+css+js网页设计 电商模版4个页面
htmlcssjs网页设计 电商模版4个页面 带js 网页作品代码简单,可使用任意HTML编辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作)。 获取源码 1&…...

区块链技术在Facebook中的潜力:未来趋势与挑战
数据安全的新高度 区块链技术以其去中心化和不可篡改的特性,正在成为提升数据安全和隐私保护的重要工具。Facebook作为全球最大的社交媒体平台之一,正积极探索如何将区块链技术应用于其平台,以增强用户数据的安全性和隐私保护。Facebook在应…...

dockerfile自定义镜像
目录 概念 基于dockerfile创建 dockerfile的命令 构建容器 FROM ENTRYPOINT和CMD RUN COPY和ADD 工作目录和环境变量以及容器卷(挂载卷) EXPOSE 实战 概念 dockerfile就是自定义镜像,通过dockerfile创建的都是镜像,而…...

【工作状态】如何保持专注?
好的睡眠计划主题化 1、保持足够的睡眠,才能头脑清晰和有精力,工作不是纯拼体力,要用脑力的。 2、脑力主要工作放在午餐前,在脑力充足的时候使用脑力,下午五点后可以安排脑力活动较低的工作,比如听课读书。…...

欧科云链研究院对话:风浪越大鱼越贵—链上数据洞悉加密市场规律
作者 Hedy 出品 OKG Research “我们从来就不是理性人。但可以用最简单的工具——链上数据做‘最猛’的分析。” 在经历了超级宏观周之后,金融市场产生了巨大的震荡,加密市场的表现也越来越受到宏观经济因素的影响。欧科云链研究院OKG Research 集结多…...
SQLite库笔记:日期和时间函数
1. 函数概述 SQLite支持7个日期和时间函数,如下: 1 date(time-value, modifier, modifier, ...) 返回YYYY-MM-DD格式的日期 2 time(time-value, modifier, modifier, ...) 返回HH:MM:SS格式的时间 3 datetime(time-value, modifier, modifier, ...…...
Linux开发板运行报错/system/bin/sh: can‘t create /dev/leds: Permission denied
Linux开发板运行报错/system/bin/sh: cant create /dev/leds: Permission denied 1.问题解决 1.问题解决 /system/bin/sh: can’t create /dev/leds: Permission denied 在linux开发板下运行驱动报错没有权限,需要运行 su,同时也会停止打印 在运行: ch…...
月薪5W的项目经理是如何面试的?这份面试攻略请收好!
面试是项目经理求职必须经历的一关,但很多经验不够丰富的项目经理不知道面试会问些什么问题,也不知道要怎么回答,无疑会直接影响面试企业的判断,使项目经理求职受阳.所以,项目经理想要顺利求职,还是有必要掌…...

接口隔离原则
接口隔离原则 接口隔离原则就是客户端不应该依赖它不需要的接口,或者说类间的依赖关系应该建立在最小的接口上。 我们以搜索美女为例,设计了如下的类图: 源代码如下。美女及其实现类: 搜索程序及其子类源代码如下: 最…...
【C++ 面试 - 基础题】每日 3 题(十六)
✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/fYaBd 📚专栏简介:在这个专栏中,我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏&…...
端到端测试自动化:使用JavaScript打造可靠的Web应用
端到端测试(End-to-End Testing,简称E2E测试)是软件测试的一种形式,用于验证整个应用从端到端的流程是否按预期工作。在JavaScript生态系统中,E2E测试通常使用专门的框架来模拟用户交互,验证应用的业务逻辑…...
『大模型笔记』基于LLM生成真实世界数据的合成问答数据!
基于LLM生成真实世界数据的合成问答数据! 文章目录 一. 基于LLM生成真实世界数据的合成问答数据!1. 概述(Overview)2. 场景(Scenario)2.1. 概述2.1.1. 第1阶段:构建种子数据集(Stage 1. Constructing a seed dataset)2.1.2. 第2阶段:数据增强(可选)(Data Augmentation…...
一个使用Python和`scikit-learn`库实现KMeans聚类算法的简单示例
一个使用Python和scikit-learn库实现KMeans聚类算法的简单示例。首先,请确保您已经安装了scikit-learn库。如果没有安装,可以通过pip安装它: pip install scikit-learn下面是一个简单的例子,展示如何使用scikit-learn中的KMeans进…...
记录一下vue2和vue3中如何配置keep-alive及写法上的差异
应用场景 跳转下一个页面后,返回当前页面,或者在多个页面之间切换,保留页面中的所有状态,常见的就是填写到一半的表单。h5的tabbar页面缓存,避免重复加载数据。 主要实现思路 这个东西很常见,动态路由一…...

面试题:Rabbitmq怎么保证消息的可靠性?
1.消费端消息可靠性保证: 消息确认(Acknowledgements):(自动(默认),手动) 消费者在接收到消息后,默认情况下RabbitMQ会自动确认消息(autoAcktrue)。为保证消息可靠性,可以设置auto…...

性能测试工具之JMeter
JMeter Apache JMeter应用程序是开源软件,是一个100%纯Java应用程序,旨在负载测试功能行为和衡量性能。它最初是为测试Web应用程序而设计的,但后来扩展到其他测试功能。 JMeter是一个免费、开源、跨平台的性能测试工具,于20世纪90年代后期面世。这是一个成熟、健全且具有…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...

Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...

nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...