Android应用开发(37)LTPO帧率测试基于Surfaceview(暂存)

Android应用开发学习笔记——目录索引

 参考android官网:

  1. Frame rate  |  Android media  |  Android Developers
  2. 多重刷新率  |  Android 开源项目  |  Android Open Source Project
  3. WindowManager.LayoutParams  |  Android Developers

目前市面上旗舰手机基本都是普及了LTPO屏幕,为了验证LTPO屏幕的DDIC(display driver ID)的硬件刷帧行为(屏幕硬件的刷新可以通过屏幕的AVDD电流信号/屏幕硬件内部的Vsync信号检测),写一个可以指定app出图帧率的测试程序(基于Android应用开发(35)SufaceView基本用法 与 Android应用开发(36)帧率API测试基于Surfaceview)。

一、获取屏幕支持的所有帧率

应用程序获取设备实际支持的显示刷新率,可以通过调用 Display.getSupportedModes()获取,Mode.mRefreshRate就是帧率信息,以便安全调用setFrameRate()

// Display.java
Display.Mode[] mSupportedModes = getWindowManager().getDefaultDisplay().getSupportedModes();
for (Display.Mode mode : mSupportedModes) {Log.d(TAG, "getSupportedModes: " + mode.toString());Log.d(TAG, "getRefreshRate: " + mode.getRefreshRate());
}public static final class Mode implements Parcelable {public static final Mode[] EMPTY_ARRAY = new Mode[0];private final int mModeId;private final int mWidth;private final int mHeight;private final float mRefreshRate;@NonNullprivate final float[] mAlternativeRefreshRates;
...
}

二、APP设置帧率的API

setFrameRate( )

Android 公开了多种访问和控制界面的方法,因此有多个版本的setFrameRate()API。每个版本的 API 都采用相同的参数,并且与其他版本的工作方式相同:

  • Surface.setFrameRate()
  • SurfaceControl.Transaction.setFrameRate()
  • ANativeWindow_setFrameRate()
  • ASurfaceTransaction_setFrameRate()

要查看调用 是否会导致setFrameRate()显示刷新率发生更改,请通过调用 DisplayManager.registerDisplayListener() 或 来注册显示更改通知AChoreographer_registerRefreshRateCallback()。 

调用时setFrameRate(),最好传递精确的帧速率,而不是四舍五入为整数。例如,当渲染以 29.97Hz 录制的视频时,请传入 29.97,而不是四舍五入到 30。

对于视频应用程序,传递给的兼容性参数setFrameRate()应设置为Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,以向 Android 平台提供额外提示,即该应用程序将使用pulldown来适应不匹配的显示刷新率(这将导致抖动)。

surface.setFrameRate(contentFrameRate,

    FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,

    CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);

// 调用setFrameRate()时,最好传入准确的帧速率,而不是四舍五入为整数。例如,在渲染以 29.97Hz 录制的视频时,传入 29.97 而不是四舍五入为 30。

参数:Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE仅适用于视频应用程序。对于非视频用途,请使用FRAME_RATE_COMPATIBILITY_DEFAULT.

选择改变帧速率的策略:

google强烈建议应用在显示电影等长时间运行的视频时调用setFrameRate(fps , FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS) ,其中 fps 是视频的帧速率。

当您预计视频播放持续几分钟或更短时间时,我们强烈建议您不要调用应用程序setFrameRate()。CHANGE_FRAME_RATE_ALWAYS

SurfaceControl.Transaction.setFrameRate()

参数和1是一样的

setFrameRate( ) 与 PreferredDisplayModeId

WindowManager.LayoutParams.preferredDisplayModeId 是应用程序向平台指示其帧速率的另一种方式。某些应用程序只想更改显示刷新率,而不是更改其他显示模式设置,例如显示分辨率。一般情况下,使用 setFrameRate()代替preferredDisplayModeId. 该setFrameRate() 功能更易于使用,因为应用程序不需要搜索显示模式列表来查找具有特定帧速率的模式。

setFrameRate()在存在多个以不同帧速率运行的表面的情况下,使平台有更多机会选择兼容的帧速率。例如,考虑这样一种场景:两个应用程序在 Pixel 4 上以分屏模式运行,其中一个应用程序正在播放 24Hz 视频,另一个应用程序向用户显示可滚动列表。设备支持两种显示刷新率:60Hz 和 90Hz。使用preferredDisplayModeIdAPI,视频表面被迫选择 60Hz 或 90Hz。通过使用 setFrameRate()24Hz 调用,视频表面为平台提供了有关源视频帧速率的更多信息,使平台能够选择 90Hz 的显示刷新率,在此场景中这比 60Hz 更好。

然而,有些场景preferredDisplayModeId应该使用 来代替setFrameRate(),例如:

  • 如果应用程序想要更改分辨率或其他显示模式设置,请使用preferredDisplayModeId
  • setFrameRate()如果模式切换是轻量级的并且不太可能被用户注意到,则平台只会响应调用来切换显示模式 。如果应用程序更喜欢切换显示刷新率,即使它需要大量模式切换(例如,在 Android TV 设备上),请使用preferredDisplayModeId.
  • 无法处理以应用程序帧速率倍数运行的显示的应用程序(这需要在每个帧上设置演示时间戳)应使用preferredDisplayModeId.

WindowManager.LayoutParams params = getWindow().getAttributes();

params.preferredDisplayModeId = mSupportedModes[position].getModeId();

Log.d(TAG, "setRefreshRate:" + mSupportedModes[position].getRefreshRate());

getWindow().setAttributes(params);

setFrameRate( ) 与 PreferredRefreshRate

WindowManager.LayoutParams#preferredRefreshRate 在应用程序窗口上设置首选帧速率,并且该速率适用于窗口内的所有表面。无论设备支持的刷新率如何,应用程序都应指定其首选帧速率,类似于 setFrameRate(),以便为调度程序更好地提示应用程序的预期帧速率。

preferredRefreshRate对于使用 的表面将被忽略setFrameRate()。如果可能的话一般使用setFrameRate()

PreferredRefreshRate 与 PreferredDisplayModeId

如果应用程序只想更改首选刷新率,则最好使用 preferredRefreshRate,而不是preferredDisplayModeId

避免过于频繁地调用setFrameRate( )

尽管该setFrameRate()调用在性能方面的成本并不高,但应用程序应避免setFrameRate()每帧调用或每秒调用多次。调用setFrameRate()可能会导致显示刷新率发生变化,从而可能导致转换期间出现帧丢失。您应该提前计算出正确的帧速率并调用 setFrameRate()一次。

用于游戏或其他非视频应用程序

尽管视频是该 API 的主要用例setFrameRate(),但它也可用于其他应用程序。例如,打算不高于 60Hz 运行的游戏(以减少功耗并实现更长的游戏时间)可以调用 Surface.setFrameRate(60, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT). 这样,默认情况下以 90Hz 运行的设备将在游戏处于活动状态时以 60Hz 运行,这将避免游戏以 60Hz 运行而显示器以 90Hz 运行时出现的抖动。

二、代码分析

1、surface.setFrameRate()

// Surface.java (frameworks\base\core\java\android\view)/*** Sets the intended frame rate for this surface.** <p>On devices that are capable of running the display at different refresh rates,* the system may choose a display refresh rate to better match this surface's frame* rate. Usage of this API won't introduce frame rate throttling, or affect other* aspects of the application's frame production pipeline. However, because the system* may change the display refresh rate, calls to this function may result in changes* to Choreographer callback timings, and changes to the time interval at which the* system releases buffers back to the application.</p>** <p>Note that this only has an effect for surfaces presented on the display. If this* surface is consumed by something other than the system compositor, e.g. a media* codec, this call has no effect.</p>** @param frameRate The intended frame rate of this surface, in frames per second. 0* is a special value that indicates the app will accept the system's choice for the* display frame rate, which is the default behavior if this function isn't* called. The <code>frameRate</code> parameter does <em>not</em> need to be a valid refresh* rate for this device's display - e.g., it's fine to pass 30fps to a device that can only run* the display at 60fps.** @param compatibility The frame rate compatibility of this surface. The* compatibility value may influence the system's choice of display frame rate.* This parameter is ignored when <code>frameRate</code> is 0.** @param changeFrameRateStrategy Whether display refresh rate transitions caused by this* surface should be seamless. A seamless transition is one that doesn't have any visual* interruptions, such as a black screen for a second or two. This parameter is ignored when* <code>frameRate</code> is 0.** @throws IllegalArgumentException If <code>frameRate</code>, <code>compatibility</code> or* <code>changeFrameRateStrategy</code> are invalid.*/public void setFrameRate(@FloatRange(from = 0.0) float frameRate,@FrameRateCompatibility int compatibility,@ChangeFrameRateStrategy int changeFrameRateStrategy) {synchronized (mLock) {checkNotReleasedLocked();int error = nativeSetFrameRate(mNativeObject, frameRate, compatibility,changeFrameRateStrategy);if (error == -EINVAL) {throw new IllegalArgumentException("Invalid argument to Surface.setFrameRate()");} else if (error != 0) {throw new RuntimeException("Failed to set frame rate on Surface");}}}/*** Sets the intended frame rate for this surface. Any switching of refresh rates is* most probably going to be seamless.** @see #setFrameRate(float, int, int)*/public void setFrameRate(@FloatRange(from = 0.0) float frameRate, @FrameRateCompatibility int compatibility) {setFrameRate(frameRate, compatibility, CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);}
// android_view_Surface.cpp (frameworks\base\core\jni)
static jint nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat frameRate,jint compatibility, jint changeFrameRateStrategy) {Surface* surface = reinterpret_cast<Surface*>(nativeObject);ANativeWindow* anw = static_cast<ANativeWindow*>(surface);// Our compatibility is a Surface.FRAME_RATE_COMPATIBILITY_* value, and// NATIVE_WINDOW_SET_FRAME_RATE takes an// ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* value. The values are identical// though, so no need to explicitly convert.return anw->perform(surface, NATIVE_WINDOW_SET_FRAME_RATE, double(frameRate), compatibility,int(changeFrameRateStrategy));
}
// Surface.cpp (frameworks\native\libs\gui)
int Surface::perform(int operation, va_list args)
{case NATIVE_WINDOW_SET_FRAME_RATE:res = dispatchSetFrameRate(args);break;int Surface::dispatchSetFrameRate(va_list args) {float frameRate = static_cast<float>(va_arg(args, double));int8_t compatibility = static_cast<int8_t>(va_arg(args, int));int8_t changeFrameRateStrategy = static_cast<int8_t>(va_arg(args, int));return setFrameRate(frameRate, compatibility, changeFrameRateStrategy);
}status_t Surface::setFrameRate(float frameRate, int8_t compatibility,int8_t changeFrameRateStrategy) {ATRACE_CALL();ALOGV("Surface::setFrameRate");if (!ValidateFrameRate(frameRate, compatibility, changeFrameRateStrategy,"Surface::setFrameRate")) {return BAD_VALUE;}return composerService()->setFrameRate(mGraphicBufferProducer, frameRate, compatibility,changeFrameRateStrategy);
}
// ISurfaceComposer.cpp (frameworks\native\libs\gui)status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,int8_t compatibility, int8_t changeFrameRateStrategy) override {..status_t err = remote()->transact(BnSurfaceComposer::SET_FRAME_RATE, data, &reply);}
status_t BnSurfaceComposer::onTransact(
...setFrameRate(surface, frameRate, compatibility, changeFrameRateStrategy);// SurfaceFlinger.cpp (miui\frameworks\native\services\surfaceflinger)
status_t SurfaceFlinger::setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,int8_t compatibility, int8_t changeFrameRateStrategy)layer->setFrameRate(Layer::FrameRate(Fps{frameRate}, Layer::FrameRate::convertCompatibility(compatibility), strategy))

1、surfaceflinger layerinfo保存app传递下来的结构体是FrameRatestruct FrameRate {using Seamlessness = scheduler::Seamlessness;Fps rate;FrameRateCompatibility type;Seamlessness seamlessness;
}enum class FrameRateCompatibility {Default, // 图层没有指定任何具体的处理策略Exact, // 图层需要准确的帧速率。如视频类ExactOrMultiple, // 图层需要精确的帧速率(或它的倍数)来呈现内容。 任何其他值都将导致下拉。NoVote, // 图层对刷新率没有任何要求,不考虑显示刷新率
};// The seamlessness requirement of a Layer.
enum class Seamlessness {// Indicates a requirement for a seamless mode switch.OnlySeamless,// Indicates that both seamless and seamed mode switches are allowed.SeamedAndSeamless,// Indicates no preference for seamlessness. For such layers the system will// prefer seamless switches, but also non-seamless switches to the group of the// default config are allowed.Default
};

2、SurfaceControl.Transaction.setFrameRate()

// SurfaceControl.java (frameworks\base\core\java\android\view)/*** Sets the intended frame rate for this surface. Any switching of refresh rates is* most probably going to be seamless.** @see #setFrameRate(SurfaceControl, float, int, int)*/@NonNullpublic Transaction setFrameRate(@NonNull SurfaceControl sc,@FloatRange(from = 0.0) float frameRate,@Surface.FrameRateCompatibility int compatibility) {return setFrameRate(sc, frameRate, compatibility,Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);}
// android_view_SurfaceControl.cpp (frameworks\base\core\jni)
static void nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject,jfloat frameRate, jint compatibility, jint changeFrameRateStrategy) {auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);const auto ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);// Our compatibility is a Surface.FRAME_RATE_COMPATIBILITY_* value, and// Transaction::setFrameRate() takes an ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* value. The// values are identical though, so no need to convert anything.transaction->setFrameRate(ctrl, frameRate, static_cast<int8_t>(compatibility),static_cast<int8_t>(changeFrameRateStrategy));
}
// SurfaceComposerClient.cpp (frameworks\native\libs\gui)
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameRate(const sp<SurfaceControl>& sc, float frameRate, int8_t compatibility,int8_t changeFrameRateStrategy) {layer_state_t* s = getLayerState(sc);if (!s) {mStatus = BAD_INDEX;return *this;}// Allow privileged values as well here, those will be ignored by SF if// the caller is not privilegedif (!ValidateFrameRate(frameRate, compatibility, changeFrameRateStrategy,"Transaction::setFrameRate",/*privileged=*/true)) {mStatus = BAD_VALUE;return *this;}s->what |= layer_state_t::eFrameRateChanged;s->frameRate = frameRate;s->frameRateCompatibility = compatibility;s->changeFrameRateStrategy = changeFrameRateStrategy;return *this;
}
// SurfaceFlinger.cpp (frameworks\native\services\surfaceflinger)
applyTransactionStatesetClientStateLockeduint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTimelineInfo, const ComposerState& composerState,int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, uint32_t permissions,std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& outListenerCallbacks) {
...if (what & layer_state_t::eFrameRateChanged) {if (ValidateFrameRate(s.frameRate, s.frameRateCompatibility, s.changeFrameRateStrategy,"SurfaceFlinger::setClientStateLocked", privileged)) {const auto compatibility =Layer::FrameRate::convertCompatibility(s.frameRateCompatibility);const auto strategy =Layer::FrameRate::convertChangeFrameRateStrategy(s.changeFrameRateStrategy);if (layer->setFrameRate(Layer::FrameRate(Fps(s.frameRate), compatibility, strategy))) {flags |= eTraversalNeeded;}}}

3、preferredDisplayModeId

// RefreshRatePolicy.java (mframeworks\base\services\core\java\com\android\server\wm)int getPreferredModeId(WindowState w) {// If app is animating, it's not able to control refresh rate because we want the animation// to run in default refresh rate.if (w.isAnimating(TRANSITION | PARENTS)) {return 0;}return w.mAttrs.preferredDisplayModeId;}
// DisplayContent.java (frameworks\base\services\core\java\com\android\server\wm)
会保存到   
private static final class ApplySurfaceChangesTransactionState 的preferredModeIdvoid applySurfaceChangesTransaction() {if (!mWmService.mDisplayFrozen) {mWmService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,mLastHasContent,mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,mTmpApplySurfaceChangesTransactionState.preferredModeId,mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate,mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate,mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing,true /* inTraversal, must call performTraversalInTrans... below */);}
// DisplayManagerService.java (frameworks\base\services\core\java\com\android\server\display)public void setDisplayProperties(int displayId, boolean hasContent,float requestedRefreshRate, int requestedMode, float requestedMinRefreshRate,float requestedMaxRefreshRate, boolean requestedMinimalPostProcessing,boolean inTraversal) {setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,requestedMode, requestedMinRefreshRate, requestedMaxRefreshRate,requestedMinimalPostProcessing, inTraversal);}
setDisplayPropertiesInternal
|--> mDisplayModeDirector.getAppRequestObserver().setAppRequest(displayId, requestedModeId, requestedMinRefreshRate, requestedMaxRefreshRate);// DisplayModeDirector.java (frameworks\base\services\core\java\com\android\server\display)public void setAppRequest(int displayId, int modeId, float requestedMinRefreshRateRange,float requestedMaxRefreshRateRange) {synchronized (mLock) {setAppRequestedModeLocked(displayId, modeId);setAppPreferredRefreshRateRangeLocked(displayId, requestedMinRefreshRateRange,requestedMaxRefreshRateRange);}}setAppRequest 最后通过:
updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE, vote);
还就是最后调用surfaceflinger的:
setDesiredDisplayModeSpecs // surface的标准API接口

三、写一个APP验证API

运行界面介绍

        

 

四、测试程序

完整源码

百度网盘链接:百度网盘 请输入提取码 提取码:test

RefreshRateSurfaceViewTest目录

点此查看Android应用开发学习笔记的完整目录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/33725.shtml

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

相关文章

ad+硬件每日学习十个知识点(26)23.8.6 (DCDC的降压电路、升压电路、降压-升压电路,同步整流,选型考虑同步、隔离)

文章目录 1.DCDC的降压原理2.DCDC的升压原理3.DCDC的升压和降压原理4.什么是肖特基二极管造成的死区电压&#xff1f;5.MOS管有死区电压么&#xff1f;6.DCDC的同步整流&#xff08;用MOS管取代整流二极管&#xff0c;避免死区电压的影响&#xff09;7.DCDC选型——同步与非同步…

近地面无人机植被定量遥感与生理参数反演技术

遥感&#xff08;RS-Remote Sensing&#xff09;——不接触物体本身&#xff0c;用传感器收集目标物的电磁波信息&#xff0c;经处理、分析后&#xff0c;识别目标物&#xff0c;揭示其几何、物理性质和相互关系及其变化规律的现代科学技术。 换言之&#xff0c;即是“遥远的感…

一文读懂什么是Byzer

目录 一、什么是Byzer? 二、Byzer特性 2.1 语法特性 2.2 数据的管理特性 2.3 支持自定义函数拓展Byzer语法 三、Byzer有哪些功能&#xff1f; 3.1 Byzer-Lang语言特性 3.1.1强大的数据处理能力 3.1.2内置机器学习算法 3.2 Byzer-Lang支持权限控制 3.3 Byzer-LLM拓展…

【工程优化问题】基于鲸鱼、萤火虫、灰狼优化算法的张力、压缩弹簧设计问题研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

el-tree-select那些事

下拉菜单树形选择器 用于记录工作及日常学习涉及到的一些需求和问题 vue3 el-tree-select那些事 1、获取el-tree-select选中的任意层级的节点对象 1、获取el-tree-select选中的任意层级的节点对象 1-1数据集 1-2画面 1-3代码 1-3-1画面代码 <el-tree-selectv-model"s…

(6)所有角色数据分析-6

http://t.csdn.cn/KrurEhttp://t.csdn.cn/KrurE &#xff08;5&#xff09;中的页面&#xff0c;倾向于向用户展示所有数据&#xff0c;但却没有对数据进行比较、分析&#xff0c;用户不能直观的感受到各种数据之间的关系与变化幅度&#xff0c;所以&#xff0c;下面将向用户提…

Node.js |(三)Node.js API:path模块及Node.js 模块化 | 尚硅谷2023版Node.js零基础视频教程

学习视频&#xff1a;尚硅谷2023版Node.js零基础视频教程&#xff0c;nodejs新手到高手 文章目录 &#x1f4da;path模块&#x1f4da;Node.js模块化&#x1f407;介绍&#x1f407;模块暴露数据⭐️模块初体验⭐️暴露数据 &#x1f407;导入文件模块&#x1f407;导入文件夹的…

adb 命令行执行单元测试

文章目录 1、配置 adb 环境变量2、adb 执行测试3、官方文档解读 adb 使用&#xff08;1&#xff09;第一条执行测试的adb命令&#xff08;2&#xff09;am instrument 参数&#xff08;3&#xff09;-e 参数 的 key-value键值对&#xff08;4&#xff09;用法用例 4、存在问题 …

Python3 安装、环境变量配置、PyCharm新建Python项目

一、安装包下载 Pyhton官网下载>>最新稳定版的安装包&#xff1a; 找到合适的版本进行下载&#xff1a; 如果下载较慢&#xff0c;此处提供一个3.10.11的稳定版本的安装包&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/16GnWjkGFuSfWfaI9UVX8qA?pwd4u5o 提取…

24聊城大学823软件工程考研

1.软件发展有几个阶段&#xff1f;各有何特征&#xff1f; ①程序设计阶段 硬件特征&#xff1a;价格贵、存储容量小、运行可靠性差。 软件特征&#xff1a;只有程序、程序设计概念&#xff0c;不重视程序设计方法。 ②程序系统阶段。 硬件特征&#xff1a;速度、容量及工作可…

MySQL高阶知识点

MySQL 文章目录 MySQLchar和varchar的区别视图视图的特点 存储过程存储过程的特点 触发器触发器的特点 MySQL引擎索引为什么要有索引呢&#xff1f;什么是索引索引的优势索引的劣势索引类型索引种类组合索引最左前缀原则索引创建原则B树和B树的区别数据库为什么使用B树而不是B树…

Android Https

本质&#xff1a;在客户端和服务端使用非对称加密协商出一套对称密钥&#xff0c;每次发送数据前加密&#xff0c;收到后解密&#xff0c;达到加密传输 http ssl 在http之下增加了安全层&#xff0c;用于保障http的加密传输 HTTPS连接 TLS连接步骤 1.客户端发送 client h…

【Linux】网络基础2

文章目录 网络基础21. 应用层1.1 协议1.2 HTTP 协议1.2.1 URL1.2.2 urlencode和urldecode1.2.3 HTTP协议格式1.2.4 HTTP的方法1.2.5 HTTP的状态码1.2.6 HTTP 常见的header1.2.7 最简单的HTTP服务器 2. 传输层2.1 端口号2.1.1 端口号范围划分2.1.2 认识知名端口号2.1.3 netstat2…

Redis_安装、启动以及基本命令

2.Redis安装 2.1前置处理环境 VMware安装安装centOS的linux操作系统xshellxftp 2.2 配置虚拟机网络 按ctrlaltf2 切换到命令行 cd (/)目录 修改/etc/sysconfig/network-scripts/ifcfg-ens3 vi 命令 按insert表示插入 按ctrlesc退出修改状态 :wq 写入并退出 此文件必须保持一…

10.pod资源限制和健康检查

文章目录 资源限制探针&#xff08;健康检查&#xff09;启动、退出动作总结 资源限制 当定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。 最常见的可设定资源是 CPU 和内存大小&#xff0c;以及其他类型的资源。当为 pod 中的容器指定了 request 资源时&#xff0c…

Redis_持久化(AOF、RDB)

6. Redis AOF 6.1 简介 目前&#xff0c;redis的持久化主要应用AOF&#xff08;Append Only File&#xff09;和RDF两大机制&#xff0c;AOF以日志的形式来记录每个写操作&#xff08;增量保存&#xff09;&#xff0c;将redis执行过的所有指令全部安全记录下来&#xff08;读…

C语言一些有趣的冷门知识

文章目录 概要1.访问数组元素的方法运行结果 2.中括号的特殊用法运行结果 3.大括号的特殊用法运行结果 4.sizeof的用法运行结果 5.渐进运算符运行结果 小结 概要 本文章只是介绍一些有趣的C语言知识&#xff0c;纯属娱乐。这里所有的演示代码我是使用的编译器是Visual Studio …

入门指南 | 如何系统搭建自己的营销战略学习体系成为领域专家?

独自进入一个行业&#xff0c;如果你没有几年的行业经验或者独特的营销方式&#xff0c;很难在行业里站住脚&#xff08;每个行业潜规则都很多&#xff09;。 每个行业都有周期&#xff0c;都有很多竞争对手&#xff0c;你扎进去一个具体的行业&#xff0c;对于各种资源有限的自…

uni-app实现图片上传功能

效果 代码 <uni-forms-item name"ViolationImg" label"三违照片 :"><uni-file-picker ref"image" limit"1" title"" fileMediatype"image" :listStyles"listStyles" :value"filePathsL…

企业举办活动邀请媒体的意义和重要性

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 企业举办活动并邀请媒体的意义和重要性是多方面的&#xff0c;主要有以下一些&#xff1a; 1. 品牌曝光与宣传&#xff1a;邀请媒体参与企业活动可以提高企业的品牌曝光度。媒体报道能够…