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

Android显示系统(11)- 向SurfaceFlinger申请Surface

Android显示系统(01)- 架构分析
Android显示系统(02)- OpenGL ES - 概述
Android显示系统(03)- OpenGL ES - GLSurfaceView的使用
Android显示系统(04)- OpenGL ES - Shader绘制三角形
Android显示系统(05)- OpenGL ES - Shader绘制三角形(使用glsl文件)
Android显示系统(06)- OpenGL ES - VBO和EBO和VAO
Android显示系统(07)- OpenGL ES - 纹理Texture
Android显示系统(08)- OpenGL ES - 图片拉伸
Android显示系统(09)- SurfaceFlinger的使用
Android显示系统(10)- SurfaceFlinger内部结构
Android显示系统(11)- 向SurfaceFlinger申请Surface
Android显示系统(12)- 向SurfaceFlinger申请Buffer
Android显示系统(13)- 向SurfaceFlinger提交Buffer

一、前言:

前面已经和SurfaceFlinger建立好了连接,那么,本章介绍下如何去向SurfaceFlinger申请我们的画布(也就是Surface)。

二、获取Surface流程:

上面创建好了Client,也就是创建好了连接,我们要绘制一张图片,首先得拿到画布,这个由CreateSurface完成:

status_t BootAnimation::readyToRun() {// 。。。// 创建SurfaceControl, 参数指定名称 ("BootAnimation")、宽度、高度和像素格式 (PIXEL_FORMAT_RGB_565)sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);SurfaceComposerClient::Transaction t;t.setLayer(control, 0x40000000).apply();// 获得对应的Surface(画布)sp<Surface> s = control->getSurface();// 。。。
}

可以看出,先获取SurfaceControl,然后从SurfaceControl当中取出了Surface,那么,这个API调用,后面都有谁在配合呢?

1、APP侧开始请求:

这个session()里面其实就是返回一个mSession,我们都知道mSessionsp<SurfaceComposerClient>类型,进去看看:

sp<SurfaceControl> SurfaceComposerClient::createSurface(const String8& name, uint32_t w, uint32_t h,PixelFormat format, uint32_t flags,SurfaceControl* parent,LayerMetadata metadata) {sp<SurfaceControl> s;createSurfaceChecked(name, w, h, format, &s, flags, parent, std::move(metadata));return s;
}

再进去看看:

status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,PixelFormat format,sp<SurfaceControl>* outSurface, uint32_t flags,SurfaceControl* parent,LayerMetadata metadata) {sp<SurfaceControl> sur;status_t err = mStatus;if (mStatus == NO_ERROR) {sp<IBinder> handle; // Surfacesp<IBinder> parentHandle;sp<IGraphicBufferProducer> gbp; // SF端Layer的生产者对象if (parent != nullptr) {parentHandle = parent->getHandle();}// 这个mClienterr = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),&handle, &gbp);ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));if (err == NO_ERROR) {// 创建SurfaceControl*outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);}}return err;
}

前面说过,这个mClient其实就是BpSurfaceComposer,所以,这个函数就是先远程调用SF获取了一个Surface(通过handle返回),并且呢,用一个SurfaceControl将这个Surface持有并管理起来。

BpSurfaceComposerClient当中发起远程调用:

 status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format,uint32_t flags, const sp<IBinder>& parent, LayerMetadata metadata,sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) override {return callRemote<decltype(&ISurfaceComposerClient::createSurface)>(Tag::CREATE_SURFACE,name, width, height,format, flags, parent,std::move(metadata),handle, gbp);}

记住这个Tag::CREATE_SURFACE,发起Binder远程调用之后,SF侧就会根据这个id来处理。

2、SurfaceFlinger侧响应:

  • 简单调用逻辑传递:

binder调用部分省略,参考上一章的createConnection,然后就来到了:

status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,uint32_t flags, const sp<IBinder>& parentHandle,LayerMetadata metadata, sp<IBinder>* handle,sp<IGraphicBufferProducer>* gbp) {// We rely on createLayer to check permissions.return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,parentHandle);
}

这就相当于什么?相当于客户端调用了一个createSurface,到了服务端调用了Client::createSurface,里面进行了Layer的创建。

status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,uint32_t h, PixelFormat format, uint32_t flags,LayerMetadata metadata, sp<IBinder>* handle,sp<IGraphicBufferProducer>* gbp,const sp<IBinder>& parentHandle,const sp<Layer>& parentLayer) {sp<Layer> layer;//...switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {// 就是普通Surfacecase ISurfaceComposerClient::eFXSurfaceBufferQueue:result = createBufferQueueLayer(client, uniqueName, w, h, flags, std::move(metadata),format, handle, gbp, &layer);break;case ISurfaceComposerClient::eFXSurfaceBufferState:result = createBufferStateLayer(client, uniqueName, w, h, flags, std::move(metadata),handle, &layer);break;case ISurfaceComposerClient::eFXSurfaceColor:// 。。。case ISurfaceComposerClient::eFXSurfaceContainer:// 。。。default:result = BAD_VALUE;break;}if (primaryDisplayOnly) {layer->setPrimaryDisplayOnly();}bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer,addToCurrentState);if (result != NO_ERROR) {return result;}mInterceptor->saveSurfaceCreation(layer);setTransactionFlags(eTransactionNeeded);return result;
}

对于上面的switch…case,我们为啥走第一个呢?我给你加了注释:

    enum { // (keep in sync with Surface.java)// 表示 Surface 默认状态是隐藏的, 用于需要控制 Surface 显示/隐藏状态的情况,例如临时用来后台渲染内容的 SurfaceeHidden = 0x00000004,// 指示在销毁表面时是否销毁后备缓冲区。不适合需要保留屏幕内容的情况eDestroyBackbuffer = 0x00000020,// 表示 Surface 是安全的,意味着内容只能显示在安全的显示器上(如受保护的 HDMI 输出)eSecure = 0x00000080,// 表示创建的表面使用非预乘的像素格式eNonPremultiplied = 0x00000100,// 如果设置了该标志,Surface 将忽略 alpha 通道,像素总是完全不透明的eOpaque = 0x00000400,// Surface 内容由应用保护。内容通常是敏感数据,应用负责其生命周期eProtectedByApp = 0x00000800,// 表示 Surface 受到 DRM(数字版权管理)保护,通常通过硬件实现。eProtectedByDRM = 0x00001000,// 表示 Surface 用作光标窗口。系统级别的输入指针,比如鼠标指针。eCursorWindow = 0x00002000,// 表明这是一个普通的 BufferQueue Surface(默认设置,无附加特性)。创建普通的 Surface。eFXSurfaceBufferQueue = 0x00000000,// 表示这是一个颜色缓冲区的 Surface,可能用于特殊效果(如着色器)。eFXSurfaceColor = 0x00020000,// 允许使用不同的 buffer 管理策略(如摆脱传统的 BufferQueue 行为)。eFXSurfaceBufferState = 0x00040000,// 表示这是一个 "容器 Surface",用来包裹其他子 Surface。窗口管理器或复杂 Layer。eFXSurfaceContainer = 0x00080000,// 一个掩码 (mask),表示 eFXSurface* 类 Surface 的通用标志。eFXSurfaceMask = 0x000F0000,};

显然,我们就是一个普通的surface;

  • 创建Layer的过程:

    status_t SurfaceFlinger::createBufferQueueLayer(const sp<Client>& client, const String8& name,uint32_t w, uint32_t h, uint32_t flags,LayerMetadata metadata, PixelFormat& format,sp<IBinder>* handle,sp<IGraphicBufferProducer>* gbp,sp<Layer>* outLayer) {// initialize the surfacesswitch (format) {case PIXEL_FORMAT_TRANSPARENT:case PIXEL_FORMAT_TRANSLUCENT:format = PIXEL_FORMAT_RGBA_8888;break;case PIXEL_FORMAT_OPAQUE:format = PIXEL_FORMAT_RGBX_8888;break;}// 创建了一个Layersp<BufferQueueLayer> layer = getFactory().createBufferQueueLayer(LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)));status_t err = layer->setDefaultBufferProperties(w, h, format);if (err == NO_ERROR) {*handle = layer->getHandle();*gbp = layer->getProducer();*outLayer = layer;}ALOGE_IF(err, "createBufferQueueLayer() failed (%s)", strerror(-err));return err;
    }
    

    看到创建Layer成功之后,便将Layer的handle,以及Layer的BufferQueueProducer返回,同时,也将layer本身返回给outLayer。

    那么,这个工厂是如何创建这个Layer的呢?

    看看文件native\services\surfaceflinger\SurfaceFlingerFactory.cpp中:

    sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs& args) override {return new BufferQueueLayer(args);
    }
    

    就是new了一个,返回而已,我们第一个引用Layer时候会发生什么?

    void BufferQueueLayer::onFirstRef() {BufferLayer::onFirstRef();// Creates a custom BufferQueue for SurfaceFlingerConsumer to usesp<IGraphicBufferProducer> producer;sp<IGraphicBufferConsumer> consumer;// 创建BufferQueue的时候,里面会创建生产者和消费者BufferQueue::createBufferQueue(&producer, &consumer, true);// 将消费者做一次封装mProducer = new MonitoredProducer(producer, mFlinger, this);{// Grab the SF state lock during this since it's the only safe way to access RenderEngine// 同样,将生产者做一次封装Mutex::Autolock lock(mFlinger->mStateLock);mConsumer =new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);}mConsumer->setConsumerUsageBits(getEffectiveUsage(0));mConsumer->setContentsChangedListener(this);mConsumer->setName(mName);// BufferQueueCore::mMaxDequeuedBufferCount is default to 1if (!mFlinger->isLayerTripleBufferingDisabled()) {mProducer->setMaxDequeuedBufferCount(2);}if (const auto display = mFlinger->getDefaultDisplayDevice()) {updateTransformHint(display);}
    }
    

    主要就是创建了一个BufferQueueProducerConsumer

  • 刚才看到生产者和消费者都继承自IGraphicBufferProducer,我们看下:

    在这里插入图片描述

    • APP这边的BpGraphicBufferProducer和 Native那边的Client的Layer成员的mProducer,都继承自IGraphicBufferProducer
    • 不过Native最终使用的是IGraphicBufferProducer派生的BnGraphicBufferProducer派生的BnBufferQueueProducer

于是,我们再回去看看APP侧如何处理返回的这些东西。

3、APP侧处理返回值:

直接看代码:

status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,PixelFormat format,sp<SurfaceControl>* outSurface, uint32_t flags,SurfaceControl* parent,LayerMetadata metadata) {sp<SurfaceControl> sur;status_t err = mStatus;if (mStatus == NO_ERROR) {sp<IBinder> handle; // Surfacesp<IBinder> parentHandle;sp<IGraphicBufferProducer> gbp; // SF端Layer的生产者对象if (parent != nullptr) {parentHandle = parent->getHandle();}// 这个mClienterr = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),&handle, &gbp);ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));if (err == NO_ERROR) {// 创建SurfaceControl*outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);}}return err;
}

发现将创建好的handle、gdp全都作为参数用来创建SurfaceControl了。进去看看:

SurfaceControl::SurfaceControl(const sp<SurfaceComposerClient>& client,const sp<IBinder>& handle,const sp<IGraphicBufferProducer>& gbp,bool owned): mClient(client), mHandle(handle), mGraphicBufferProducer(gbp), mOwned(owned)
{
}

发现构造函数直接将gbp保存到mGraphicBufferProducer当中了。啥时候用呢?

当你从SurfaceControl获取Surface的时候:

sp<Surface> SurfaceControl::getSurface() const
{Mutex::Autolock _l(mLock);if (mSurfaceData == nullptr) {return generateSurfaceLocked();}return mSurfaceData;
}

看看这个generateSurfaceLocked

sp<Surface> SurfaceControl::generateSurfaceLocked() const
{// This surface is always consumed by SurfaceFlinger, so the// producerControlledByApp value doesn't matter; using false.mSurfaceData = new Surface(mGraphicBufferProducer, false);return mSurfaceData;
}

发现生成Surface的时候,gbp是入参,也就是说这个Buffer的生产者已经被我们Surface持有了,以后可以通过Surface往SF侧的Layer当中BufferQueue写东西。

三、总结:

至此,Surface获取部分讲解完成,拿到画布之后该往里填数据了吧?

相关文章:

Android显示系统(11)- 向SurfaceFlinger申请Surface

Android显示系统&#xff08;01&#xff09;- 架构分析 Android显示系统&#xff08;02&#xff09;- OpenGL ES - 概述 Android显示系统&#xff08;03&#xff09;- OpenGL ES - GLSurfaceView的使用 Android显示系统&#xff08;04&#xff09;- OpenGL ES - Shader绘制三角…...

OpenCV实验篇:识别图片颜色并绘制轮廓

第三篇&#xff1a;识别图片颜色并绘制轮廓 1. 实验原理 颜色识别的原理&#xff1a; 颜色在图像处理中通常使用 HSV 空间来表示。 HSV 空间是基于人类视觉系统的一种颜色模型&#xff0c;其中&#xff1a; H&#xff08;Hue&#xff09;&#xff1a;色调&#xff0c;表示颜色…...

鸿蒙-应用内悬浮窗

//悬浮窗工具类 import { window } from kit.ArkUI; import { BusinessError } from kit.BasicServicesKit; import { Logger } from mbbase/common-ui; import * as FloatedWindowPage from ./FloatedWindowPage; // 导入命名路由页面 const TAG [FloatedWindowUtils]; ex…...

Ubuntu Linux操作系统

一、Ubuntu简介 Ubuntu Linux是由南非人马克沙特尔沃思(Mark Shuttleworth)创办的基于Debian Linux的操作系统&#xff0c;于2004年10月公布。Ubuntu是一个以桌面应用为主的Linux发行版操作系统。Ubuntu拥有庞大的社区力量&#xff0c;用户可以方便地从社区获得帮助。其官方网…...

Linux下SVN客户端保存账号密码

参考文章&#xff1a;解决&#xff1a;Linux上SVN 1.12版本以上无法直接存储明文密码_linux svn 保存密码-CSDN博客新版本svn使用gpg-agent存储密码-CSDN博客svn之无法让 SVN 存储密码&#xff0c;即使配置设置为允许_编程设计_ITGUEST 方法一&#xff1a;明文方式保存密码 首…...

【DBeaver】连接带kerberos的hive[Apache|HDP]

目录 一、安装配置Kerberos客户端环境 1.1 安装Kerberos客户端 1.2 环境配置 二、基于Cloudera驱动创建连接 三、基于Hive原生驱动创建连接 一、安装配置Kerberos客户端环境 1.1 安装Kerberos客户端 在Kerberos官网下载,地址如下&#xff1a;https://web.mit.edu/kerberos…...

Android-Glide详解

目录 一&#xff0c;介绍 二&#xff0c;使用 三&#xff0c;源码分析思路 四&#xff0c;with源码分析 五&#xff0c;模拟Glide生命周期管理 一&#xff0c;介绍 Glide目前是安卓最主流的加载图片的框架&#xff0c;也是源码最为复杂的框架之一。 要想完完全全吃透Glide的源…...

【容器】k8s学习笔记原理详解(十万字超详细)

Pod详解 Pod介绍 Pod结构 每个Pod中都可以包含一个或者多个容器&#xff0c;这些容器可以分为两类&#xff1a; 用户程序所在的容器&#xff0c;数量可多可少Pause容器&#xff0c;这是每个Pod都会有的一个根容器&#xff0c;它的作用有两个&#xff1a; 可以以它为依据&am…...

SQL Server通过存储过程实现自定义邮件格式并定时发送

在 SQL Server 中,可以通过存储过程实现自定义邮件格式并定时发送。这通常涉及以下几个步骤: 1. 配置 Database Mail:首先需要配置 SQL Server 的 Database Mail 功能。 2. 创建存储过程:编写存储过程来生成自定义邮件格式并发送邮件。 3. 设置 SQL Server 代理作…...

通过增强的 vSphere 集成增强你的 vSphere 监控

作者&#xff1a;来自 Elastic Ishleen Kaur•Lalit Satapathy vSphere 是 VMware 的云计算虚拟化平台&#xff0c;提供一套功能强大的虚拟化资源管理套件。它允许组织创建、管理和优化虚拟环境&#xff0c;提供高可用性、负载平衡和简化资源分配等高级功能。vSphere 可以高效利…...

C++ 并发专题 - C++线程同步的几种方法

一&#xff1a;概述 线程同步是多线程编程中的一个重要概念&#xff0c;它用于控制多个线程之间对共享资源的访问&#xff0c;避免竞态条件&#xff08;race condition&#xff09;和数据不一致的问题。线程同步确保在多线程环境中&#xff0c;多个线程访问共享数据时能够按照某…...

[java]网络编程

java.net.*包下提供了网络编程的解决方案 通信架构 CS架构 客户端 客户端需要开发 用户需要安装 服务端 需要开发 BS架构 浏览器 不需要开发 需要安装浏览器 服务器 需要开发 网络通信三要素 IP地址 是设备在网络中的唯一标识, 全称 互联网协议地址 分类 公网IP 可…...

[C++]类的继承

一、什么是继承 1.定义&#xff1a; 在 C 中&#xff0c;继承是一种机制&#xff0c;允许一个类&#xff08;派生类&#xff09;继承另一个类&#xff08;基类&#xff09;的成员&#xff08;数据和函数&#xff09;。继承使得派生类能够直接访问基类的公有和保护成员&#xf…...

2024安装hexo和next并部署到github和服务器最新教程

碎碎念 本来打算写点算法题上文所说的题目&#xff0c;结果被其他事情吸引了注意力。其实我之前也有过其他博客网站&#xff0c;但因为长期不维护&#xff0c;导致数据丢失其实是我懒得备份。这个博客现在部署在GitHub Pages上&#xff0c;github不倒&#xff0c;网站不灭&…...

【spring】@Qualifier注解

目录 1. 说明2. 用法示例2.1 标注在字段上2.2 标注在方法上2.3 标注在类上2.4 在自定义注解上的应用 3. 注意事项 1. 说明 1.Qualifier是Spring框架中的一个注解&#xff0c;主要用于解决依赖注入时的歧义性问题。2.定义&#xff1a;Qualifier是一个限定符注解&#xff0c;用于…...

uniapp 应用的生命周期、页面的生命周期、组件的生命周期

uniapp 作为一款跨平台的移动应用开发框架&#xff0c;其生命周期分为应用生命周期、页面生命周期和组件生命周期。下面分别介绍这三种生命周期的具体内容&#xff1a; 应用生命周期 应用生命周期仅适用于整个应用&#xff0c;在 App.vue 中可以监听到以下生命周期函数&#…...

热更新解决方案4——xLua热补丁

概述 运行时不在执行C#中的代码&#xff0c;而是执行Lua中的代码&#xff0c;相当于是打了个补丁。 1.第一个热补丁 2.多函数替换 3.协程函数替换 在原HotfixMain脚本中只加个协程函数即可&#xff08;和在Start中启动协程函数&#xff09; 4.索引器和属性替换 在HotfixMain中…...

【MARL】深入理解多智能体近端策略优化(MAPPO)算法与调参

&#x1f4e2;本篇文章是博主强化学习&#xff08;RL&#xff09;领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅…...

3.2.1.2 汇编版 原子操作 CAS

基本原理说明 在 x86 和 ARM 架构上&#xff0c;原子操作通常利用硬件提供的原子指令来实现&#xff0c;比如 LOCK 前缀&#xff08;x86&#xff09;或 LDREX/STREX&#xff08;ARM&#xff09;。以下是一些关键的原子操作&#xff08;例如原子递增和比较交换&#xff09;的汇…...

关于llama2:从原始llama-2-7b到llama-2-7b-hf的权重转换教程

1.首先&#xff0c;我是从各个教程里面选了一个实际操作的教程&#xff08;这样更加靠谱&#xff09;&#xff1a;下载llama2-7b并转hf模型_huggingface 下载llama2-7b-chat-hf-CSDN博客 2.但是&#xff0c;其实我在另外一篇更好的教程里面看到过一个坑&#xff08;这篇好像是腾…...

物理机内网穿透

前言&#xff1a; 本文主要讲述如何使用内网穿透以及其安全性。 将带领大家在公网上搭建几个常用靶场。 一&#xff0c;什么是内网穿透。 大多数情况下&#xff0c;我们的个人电脑都处于内网&#xff0c;即没有可公开访问的独立 IP 地址&#xff0c;因此其他内网用户找不到…...

构建一个rust生产应用读书笔记四(实战1)

我们需要从访客那里收集哪些信息&#xff0c;以便将其登记为电子邮件通讯的订阅者&#xff1f; 电子邮件地址&#xff1a;这是最基本的要求&#xff0c;因为我们需要通过电子邮件地址向订阅者发送内容。姓名&#xff1a;虽然这不是强制性的&#xff0c;但我们希望收集一个名字…...

[LeetCode-Python版]206. 反转链表(迭代+递归两种解法)

题目 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1] 示例 3&#xff1…...

shardingsphere分库分表跨库访问 添加分片规则

shardingsphere分库分表跨库访问 添加分片规则 建立 JDBC 环境 创建表 t_order&#xff1a; CREATE TABLE t_order (tid bigint(20) NOT NULL,tname varchar(255) DEFAULT NULL,goods_id bigint(20) DEFAULT NULL,tstatus varchar(255) DEFAULT NULL,PRIMARY KEY (tid) ) E…...

【NLP 15、深度学习处理文本】

目录 一、反向传播 ​编辑 1.反向传播运算过程 2.前向传播和反向传播的作用 前向传播 反向传播 3.定义模型&#xff08;torch包&#xff09; 4.手动实现 ① 线性层 ② sigmoid激活函数 ③ 手动实现MSE均方差损失函数 ④ 前向传播 ⑤ 手动实现梯度计算 ⑤ 权重的更新&#xff1a…...

Android Studio创建新项目并引入第三方so外部aar库驱动NFC读写器读写IC卡

本示例使用设备&#xff1a;https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.52de2c1bbW3AUC&ftt&id615391857885 一、打开Android Studio,点击 File> New>New project 菜单&#xff0c;选择 要创建的项目模版&#xff0c;点击 Next 二、输入项目名称…...

3D视觉[一]3D计算机视觉

3D视觉[一]3D计算机视觉 3D计算机视觉概述 像机标定 文章目录 3D视觉[一]3D计算机视觉前言一、人类视觉二、计算机视觉2.1 计算机视觉的研究目的2.2 计算机视觉的研究任务2.3 计算机视觉的研究方法2.4 视觉计算理论2.5 马尔框架中计算机视觉表达的四个层次2.5.1 图像&#xff…...

Linux权限(超详细彻底搞懂Linux的权限)

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;Linux &#x1f339;往期回顾&#x1f339;&#xff1a;Linux常见指令(初学者必看) &#x1f516;流水不争&#xff0c;争的是滔滔不 一、Linux下的两种用户超级用户&…...

Ubuntu22.04安装docker desktop遇到的bug

1. 确认已启用 KVM 虚拟化 如果加载了模块&#xff0c;输出应该如下图。说明 Intel CPU 的 KVM 模块已开启。 否则在VMware开启宿主机虚拟化功能&#xff1a; 2. 下一步操作&#xff1a; Ubuntu | Docker Docs 3. 启动Docker桌面后发现账户登陆不上去&#xff1a; Sign in | …...

网新恒天八股总结

Java的基本数据类型 四类八种 整数类型&#xff1a;byte,short,int,long 浮点类型&#xff1a;float,double 字符类型&#xff1a;char 布尔类型&#xff1a;boolean char类型的范围 0 ~ 65535&#xff0c;可以表示16位无符号整数 equals和的区别 &&#xff0c;&&a…...

【AIGC】与模型对话:理解与预防ChatGPT中的常见误解

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;模型的工作原理和用户期望差异人工智能模型的基本工作原理认知上的局限与误解用户期望与模型实际能力的差距精确理解用户意图的重要性实际应用中的建议 &…...

09篇--图片的水印添加(掩膜的运用)

如何添加水印&#xff1f; 添加水印其实可以理解为将一张图片中的某个物体或者图案提取出来&#xff0c;然后叠加到另一张图片上。具体的操作思想是通过将原始图片转换成灰度图&#xff0c;并进行二值化处理&#xff0c;去除背景部分&#xff0c;得到一个类似掩膜的图像。然后…...

Qt 使用modbus协议

Qt 框架下 使用modbus协议 一&#xff0c;使用Qt原生的 QModbusClient &#xff0c;比如QModbusTcpClient 1&#xff0c;因为modbus的读写 需要在同一个线程中&#xff0c;所以需要在主线程中利用moveToThread的方式&#xff0c;将业务逻辑封装到 子线程中。 2&#xff0c;m…...

pip离线安装一个github仓库

要使用pip安装一个本地Git仓库&#xff0c;你可以按照以下步骤操作&#xff1a; 确保你已经克隆了Git仓库到本地。 进入仓库所在的目录。 使用pip安装。 以下是具体的命令&#xff1a; 克隆Git仓库到本地&#xff08;替换下面的URL为你的仓库URL&#xff09; git clone https…...

【ETCD】【源码阅读】深入分析 storeTxnWrite.Put方法源码

该方法是 storeTxnWrite 类型中的核心方法&#xff0c;负责将键值对存储到数据库&#xff0c;同时处理键的元数据&#xff08;如版本、修订号、租约&#xff09;并管理租约关联。 目录 一、完整代码二、方法详解方法签名1. 计算修订号并初始化变量2. 检查键是否已存在3. 生成索…...

桥接模式的理解和实践

桥接模式&#xff08;Bridge Pattern&#xff09;&#xff0c;又称桥梁模式&#xff0c;是一种结构型设计模式。它的核心思想是将抽象部分与实现部分分离&#xff0c;使它们可以独立地进行变化&#xff0c;从而提高系统的灵活性和可扩展性。本文将详细介绍桥接模式的概念、原理…...

【Rust自学】3.2. 数据类型:标量类型

3.2.0. 写在正文之前 欢迎来到Rust自学的第三章&#xff0c;一共有6个小节&#xff0c;分别是: 变量与可变性数据类型&#xff1a;标量类型&#xff08;本文&#xff09;数据类型&#xff1a;复合类型函数和注释控制流&#xff1a;if else控制流&#xff1a;循环 通过第二章…...

【Leetcode Top 100】199. 二叉树的右视图

问题背景 给定一个二叉树的 根节点 r o o t root root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 数据约束 二叉树的节点个数的范围是 [ 0 , 100 ] [0,100] [0,100] − 100 ≤ N o d e . v a l ≤ 100…...

Java并发编程框架之其他并发工具

选错了就选错了&#xff0c;不要一遍一遍的后悔&#xff0c;总是一遍遍的想&#xff0c;当时怎么样就好了&#xff0c;不要欺负当时的自己&#xff0c;当时你一个人站在迷雾中&#xff0c;也很迷茫&#xff0c;就算重新来一遍&#xff0c;以你当时的阅历和心智&#xff0c;还是…...

MinerU:PDF文档提取工具

目录 docker一键启动本地配置下载模型权重文件demo.py使用命令行启动GPU使用情况 wget https://github.com/opendatalab/MinerU/raw/master/Dockerfile docker build -t mineru:latest .docker一键启动 有点问题&#xff0c;晚点更新 本地配置 就是在Python环境中配置依赖和…...

Unity性能优化---使用SpriteAtlas创建图集进行批次优化

在日常游戏开发中&#xff0c;UI是不可缺少的模块&#xff0c;而在UI中又使用着大量的图片&#xff0c;特别是2D游戏还有很多精灵图片存在&#xff0c;如果不加以处理&#xff0c;会导致很高的Batches&#xff0c;影响性能。 比如如下的例子&#xff1a; Batches是9&#xff0…...

wazuh-modules-sca-scan

sca模块主函数wm_sca_main -> wm_sca_start 检查policy文件中的每一个项目wm_sca_check_policy static int wm_sca_check_policy(const cJSON * const policy, const cJSON * const checks, OSHash *global_check_list) {if(!policy) {return 1;}const cJSON * const id c…...

力扣-图论-15【算法学习day.65】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非…...

JS萤石云录像回放拖动进度条无法正常播放

问题描述&#xff1a; 本项目版本&#xff1a;vue2.6.12&#xff0c;webpack3.6.0&#xff0c;ezuikit-js0.7.2 在使用萤石云的JavaScript SDK做监控的直播、录像回放时&#xff0c;遇到部分设备的录像回放&#xff0c;无法根据控制面板的拖动进度条查看某时间段的录像。 官方…...

Spring Boot 启动时间优化全攻略

引言 随着 Spring Boot 的广泛应用&#xff0c;开发者享受到了快速开发和自动化配置的便利。然而&#xff0c;随着项目复杂度的增加&#xff0c;Spring Boot 项目启动时间也变得越来越长&#xff0c;这在开发、调试和部署阶段可能会成为效率瓶颈。如何优化 Spring Boot 的启动…...

ubuntu服务器木马类挖矿程序排查、及安全管理总结

版本 24.04 由于GPU多卡服务器多人使用&#xff0c;需要链接隧道ssh等&#xff0c;容易中招挖矿脚本。 总的思路是&#xff0c;顺着进程的PID回溯最终的程序运行起点&#xff0c;这里可以先看一下日志&#xff1a; journalctl -u PID 通过 PID 精确定位进程的信息&#xff0c…...

redis 使用Lettuce 当redis挂掉重启之后 网络是怎么重新连接

Lettuce是一个高性能的Java Redis客户端&#xff0c;支持同步、异步和反应式编程模式 Lettuce的核心功能包括&#xff1a; ‌高性能‌&#xff1a;通过使用Netty作为底层网络通信框架&#xff0c;实现了非阻塞IO&#xff0c;提高了性能。‌丰富的API‌&#xff1a;提供了丰富…...

【PyTorch】实现在训练过程中自定义动态调整学习率

问题描述&#xff1a; 在使用 PyTorch 训练自定义神经网络时&#xff0c;我们希望能够动态地调整学习率&#xff0c;以便在训练过程中逐渐优化模型&#xff0c;避免过拟合并加速收敛。那么&#xff0c;如何在 PyTorch 中实现这一功能呢&#xff1f; 解决方案&#xff1a; 在训…...

【Flink-scala】DataStream编程模型总结

系列文章目录 1.【Flink-Scala】DataStream编程模型之数据源、数据转换、数据输出 2.【Flink-scala】DataStream编程模型之 窗口的划分-时间概念-窗口计算程序 3.【Flink-scala】DataStream编程模型之窗口计算-触发器-驱逐器 4.【Flink-scala】DataStream编程模型之水位线 5.【…...

语音芯片赋能可穿戴设备:开启个性化音频新体验

在科技日新月异的今天&#xff0c;语音芯片与可穿戴设备的携手合作&#xff0c;正引领我们步入一个前所未有的个性化音频时代。这一创新融合&#xff0c;用户可以享受到更加个性化、沉浸式的音频体验。下面将详细介绍语音芯片与可穿戴设备合作的优点和具体应用。 1. 定制化音效…...