OpenGL DIR

news2024/11/15 19:58:26

 Mesa简介-CSDN博客

Mesa, also called  Mesa3D and   The Mesa 3D Graphics Library, is an   open source software implementation of   OpenGL,  Vulkan, and other   graphics   API specifications. Mesa translates these specifications to vendor-specific graphics hardware drivers.

Mesa 实际上是一个库,它实现了多种图形 API 规范,这其中就包括了最著名的 OpenGL。Mesa 底层直接使用图形硬件驱动。

Mesa implements a translation layer between a graphics API such as OpenGL and the graphics hardware drivers in the operating system kernel.

上面这句话基本上点到了 Mesa 的实质。Mesa 实际上就是一个转换层,它提供了图形 API(比如:OpenGL)到图形硬件(比如:显卡 GPU)驱动之间的一个转换。

它诞生之时,是在 CPU 上进行所有渲染的,后续又发展为通过 display server 非直接的渲染。但其内部架构在设计上支持使用显卡硬件 3D 渲染的。

可以说,在适配 DRI 架构时,正式奠定了 Mesa 的位置:

With adapting to DRI, the Mesa library finally took over the role of the front end component of a full scale OpenGL framework with varying backend components that could offer different degrees of 3D hardware support while not dropping the full software rendering capability.

 Mesa & Gullium3D 介绍 - 掘金

Mesa (或Mesa3D)是一个 OpenGL/Vulkan 的实现,以及为所有开源图形驱动提供各种 GL 的入口点, 它是一个项目的名字。由它编译出来的库是下面这些:

或者这些文件:

其中需要注意的是这几个文件:libGL.so,libEGL.so,libGLESv2.so,根据名字很显然,他们分别实现了对应的API。

Mesa有两个作用:

  1. 对接各种GPU硬件,将应用层对GL API的调用转换到对硬件GPU的调用上;
  2. 各种 GL API 的纯软实现,当没有可用的硬件时,它可以提供传软件的 GL API 的实现;

作者:keyou
链接:https://juejin.cn/post/6844903841096269837
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

mesa解析1 线程本地存储 libGL.so原理_mesa libglapi.so-CSDN博客

TLS机制:

openGL维护了一个状态机,或者叫上下文;gl开头的api函数,如glUniform4fv,会修改这个上下文

系统中,如果有多个基于openGL的程序在运行,则每个程序有一个独立的上下文。每个程序调用gl api都作用于自己的上下文。

但是,libGL.so是一个共享库,每个基于openGL的程序都将其映射到自己的地址空间,共享库的代码段在系统运行期间是不变的。要同一份二进制程序,在不同程序中访问到各程序自己的gl上下文,线程本地存储(TLS / thread local storage)机制就是为了解决这个问题

每个线程有独立的地址空间,并且其中有一块用作线程本地存储(TLS)。操作系统在上下文切换时,会将TLS指针放进一个特殊的寄存器;共享库读取这个寄存器,就可以得到该线程的TLS指针,而上下文在TLS段中具体什么位置,是编译器决定的。

也就是说,约定所有程序的上下文指针都存在TLS段中特定位置,则libGL.so中读取TLS指针,加上特定偏移,就可以得到gl上下文


libGL.so基本原理

应用程序调用gl开头的函数,这些函数的定义都在libGL.so中

每个api函数的入口实现是统一的:读取TLS指针,从TLS段中读取分发表指针,从分发表中特定偏移处读取实际的实现函数的指针,通过这个函数指针进行调用

也就是说,libGL.so这个共享库是一个空壳,一个中介。在使用这个库提供的gl api函数之前,应用程序要先创建上下文和分发表,并将上下文和分发表的指针写进TLS中

上下文和分发表的定义在驱动中,如r600_dri.so,api函数的实际实现,也都在这个驱动中。

应用程序通过egl的接口,来创建gl上下文,设定上下文(将上下文和分发表注册到TLS中),之后,应用程序就可以调用libGL.so中的gl api函数了


细节上,上下文和分发表的注册功能,由libglapi.so完成,所以,libelg是调用libglapi.so中的函数,来设置上下文和分发表,libGL.so是调用libglapi.so中的函数(不过是内联调用),来获取分发表

egl以dlopen的方式,打开驱动,如r600_dri.so,从驱动中以dlsym的方式,获取驱动函数表,调用驱动函数,来创建上下文。


正向的说:egl以dlopen方式打开驱动,获取并调用驱动中的函数,来创建上下文和分发表,用glapi的接口,设置上下文和分发表到TLS;然后用户调用gl的api函数时,libGL.so中api函数会从TLS获取分发表,从分发表读取驱动函数并调用,以实现该api的功能,如glUniform4fv
————————————————
版权声明:本文为CSDN博主「xueshuangbai」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xueshuangbai/article/details/47024505

MESA : GL Dispatch - 知乎

MESA : GL Dispatch

OpenGL函数的分发机制相当复杂,这个文章试图解释其中的一些议题,并且给读者介绍Mesa的分发层实现。

1 GL Dispatch的复杂之处

每一个GL应用至少拥有一个名叫GL context的对象,这个对象是所有GL function隐含的内置参数,储存了所有应用当前状态下的所有GL状态。例如纹理、VBO之类的上下文信息都存放在context对象中。一个应用可以包含多个context,当前时刻哪个context被使用是由一个和窗口相关的函数去指定的(glXMakeContextCurrent)。

例如在使用GLX实现OpenGL With X-Windows的时候,每一个GL的函数指针都是通过glXGetProcAddress函数获得的,获得的函数指针都是contex independent 的,无论是哪个上下文对象被激活,都是相同的函数被调用。

这是GL Dispatch复杂的原因之一!

一个应用包含两个GL contexts。一个context是直接渲染上下文,其中函数调用直接路由到应用程序地址空间中加载的驱动程序(One context is a direct rendering context where function calls are routed directly to a driver loaded within the application’s address space),另外一个context间接渲染上下文,其中函数调用将会被转化为GLX协议并且发送给服务端(The other context is an indirect rendering context where function calls are converted to GLX protocol and sent to a server)。在这两种情况下,类似glVertex3fv这样的gl函数都需要做出相同的正确的事情。

高度优化的驱动或者GLX协议实现会希望更具当前的状态更改GL函数的行为,例如,glFogCoordf函数会根据fog是否enable而产生不同的影响。

在多线程的环境中,每一个线程包含不同的GL context是完全可能的。这个意味着可怜的glVertex3fv函数必须要去知道哪个contex是当前线程的contex,函数在什么时候被调用。

2 Mesa实现的概览

Mesa 每个线程使用两个指针,第一个指针记录了当前线程使用的context地址,第二个指针记录了一个与contex对应的dispatch table地址。dispatch table储存了一个真实实现此功能的函数指针。每个时刻,一个新的context被创建在一个线程中,这两个指针都会被更新。

其实 glVertex3fv这样的函数实现在概念上很简单:

  1. 获取当前的dispatch table指针
  2. 从dispatch table指针中获取确实实现glVertex3fv的函数指针
  3. 调用真实的函数指针

这个函数可以被声明的非常简单,甚至就几行C代码。见src/mesa/glapi/glapitemp.h可以看到类似的代码。

void glVertex3f(GLfloat x, GLfloat y, GLfloat z)
{
    const struct _glapi_table * const dispatch = GET_DISPATCH();

    (*dispatch->Vertex3f)(x, y, z);
}

但是上述这个简单的实现存在问题,他给每次调用此GL函数带来很大的开销。

在多线程的环境里,一个原始的GET_DISPATCH()函数会包含一个调用_glapi_get_dispatch()or_glapi_tls_Dispatch 来优化开销。

3 优化

近一些年产生了很多优化的方法来减少因为GL dispatch带来的性能损失,这个章节将会描述这些优化方法,列出了每种优化的好处,以及在什么时候可以用此优化在什么时候不能。

3.1 ELF TLS

从2.4.20 Linux Kernel以来,每个线程都会被分配一个全局的储存区域,可以使用GCC的一些扩展(ELF TLS)指令使得某些变量存放在此区域。如果可以把dispatch table指针存放在这个区域,那么调用pthread_getspecific 函数和_glapi_Dispatch函数就可以避免了,这些函数会产生大量的软件开销。

mesa不支持2.4.20以前的linux内核,所以理论上完全支持ELF TLS。

dispatch table 指针被存放在一个新的变量中 名为 _glapi_tls_Dispatch。使用一个新的变量名意味着libGL可以实现两种不同的接口,这使得libGL可以使用任意一个接口的直接渲染驱动程序。一旦正确声明了指针,GET_DISPACH 就变成了一个简单的变量引用。

extern __THREAD_INITIAL_EXEC struct _glapi_table *_glapi_tls_Dispatch;

#define GET_DISPATCH() _glapi_tls_Dispatch

https://blog.csdn.net/qq_30599505/article/details/126494369

DRI是包含现代 Linux 图形堆栈的框架,它允许非特权用户空间程序向图形硬件发出命令,而不会与其他程序发生冲突。DRI 的主要用途是为 OpenGL 实现的 Mesa 提供硬件加速,也适用于为没有图形界面的framebuffer console提供OpenGL加速。
DRI实现分散在X Server及其关联的clients库、Mesa 3D和DRM中。所有的源代码都是开源免费的。

概述

在经典的 X Window 系统架构中,X Server 是唯一能够独占访问图形硬件的进程,因此也是在framebuffer进行实际渲染的进程。X clients所做的就是与 X Server通信以分派渲染命令。这些命令是独立于硬件的,这意味着 X11 协议提供了一个提取图形设备的 API,因此 X clients不需要担心底层硬件的细节。任何依赖硬件的代码都位于设备相关 X 中,X Server 中管理video card或显卡驱动的部分,通常也称为视频或图形驱动程序。
3D渲染的兴起把这种框架的缺点暴露了出来。3D图形应用程序倾向于生成大量的命令和数据,这些命令和数据都必须发送到X Server进行渲染。随着 X client和 X Server 之间的进程间通信 (IPC) 数量的增加,3D 渲染性能受到了影响。X 驱动程序开发人员为了利用最新显卡的 3D 硬件功能,需要新的无 IPC 架构。Xclients应该直接访问图形硬件,而不是依赖第三方进程来执行此操作,从而节省所有 IPC 开销,这种方法称为“direct rendering”。DRI最初是为了允许任何X clients使用这种“direct rendering”方法执行3D渲染。

架构

在这里插入图片描述

DRI基础架构包含3个主要组件:

  • DRI client是一个可以直接执行’direct rendering’的X client - 需要一个硬件特定的驱动程序来管理video card或者显卡驱动以便可以在其上可以渲染。这些 DRI 驱动程序通常作为客户端动态链接共享库提供。
  • X Server提供了一个X11扩展协议(DRI扩展),DRI 客户端使用该扩展与窗口系统和 DDX 驱动程序进行协调。作为 DDX 驱动程序的一部分,X Server进程也同样动态链接到与DRI client相同的DRI驱动程序,但是会使用GLX扩展为X clients提供硬件3D加速渲染以进行间接渲染(如远程X clients不能直接使用渲染)。对于2D渲染,DDX 驱动程序还必须考虑使用相同图形设备的 DRI 客户端。
  • 对video card或显卡驱动的访问由DRM内核模块管理。但是X Server DDX驱动和每个X Client DRI驱动必须使用DRM来访问显卡。 DRM 为显卡的共享资源(例如命令队列、卡寄存器、视频内存、DMA 引擎等资源)提供同步,确保多个用户空间进程的并发访问不会互相干扰。 DRM还有安全保护的作用,它不允许任何X客户端访问执行3D渲染所需的硬件。

DRI1阶段

在最初的 DRI 架构中,由于当时video card的内存大小,屏幕back-buffer和front-buffer的单例被DRI client和X Server所共享。渲染的数据会被先写入back-buffer,然后在v-blank间隔时间会与front-buffer进行交换。为了把数据渲染到back-buffer,DRI进程应该确保裁剪渲染数据只保留可视窗口大小。
与 X Server的同步是通过信号和称为 SAREA 的共享内存缓冲区完成的。对 DRM 设备的访问通道是唯一的,因此任何 DRI clients都必须在渲染操作开始时锁定它,其他client期间无法访问,必须等到当前渲染操作结束时释放锁。另一个缺点是在当前 DRI 进程在设备上释放锁后,操作涉及的内存不会常驻,因此上传到显存的任何数据(如纹理)都会丢失,以供即将进行的操作使用,从而对图形性能产生重大影响。

DRI2阶段

由于像 Compiz 这样的合成窗口管理器越来越受欢迎,DRI 必须重新设计以便X client在进行直接渲染时也同样支持重定向到"offscreen-pixmaps"。常规的 X client已经将 X 服务器提供的单独像素图作为渲染目标(所谓的"offscreen-pixmaps"),但 DRI client继续直接在共享的back-buffer中进行渲染,有效地绕过了合成窗口管理器。最终的解决方案是改变DRI处理渲染buffer的方式,这会导致具有一组完全不同的DRI扩展接口,并且DRM也发生了巨大变化。新的扩展名为“DRI2”,虽然它不是更高版本,而是一个不同的扩展,甚至与原始 DRI 不兼容——事实上,两者在 X Server 中共存了很长时间。
在DRI2中,每个DRI client都拥有自己私有的 back-buffer来通过硬件加速渲染器窗口内容,而不是共享back-buffer。然而,DRI client将其与一个假的"front-buffer"进行交换。假的"front-buffer"是合成窗口管理器最终合成屏幕缓冲区的buffer之一,,在 VBLANK 间隔与实际的front-buffer进行交换。
为了处理所有这些新的buffer,DRM必须必须要有新功能,特别是显存管理器。DRI2最初使用的是还不成熟的TTM内存管理器,但是DRM内存管理器还是最终选择了GEM。新的DRI2内部buffer管理模型还解决了最初 DRI 中存在的两个主要性能瓶颈:

  • DRI2 clinet在使用它进行渲染的时候不再锁住整个DRM设备,因为现在每个client都获得了一个独立于其他进程的单独渲染buffer.
  • DRI2 client可以在显存中分配自己的buffer(带有纹理、顶点列表等),并且根据需要可以常驻,从而减少显存带宽消耗。

在DRI2中,为窗口分配私有offscreen-buffers(back-buffer、fake-front-buffer、 depth-buffer、stencil-buffer等)由X Server自己完成。DRI client通过调用 DRI2 扩展中 DRI2GetBuffers 和 DRI2GetBuffersWithFormat 等接口来检索这些buffers以便渲染到窗口中。在内部,DRI2 使用 GEM 名称——一种由 GEM API 提供的全局句柄,允许访问 DRM 设备的两个进程引用同一个缓冲区。
X Server 负责窗口渲染buffer分配的原因是 GLX 扩展允许多个 X client在同一个窗口中协同进行 OpenGL 渲染。 这样,X Server在整个渲染过程中管理渲染buffer的整个生命周期,并知道何时可以安全地回收它们。当调整窗口大小时,X server负责分配新的渲染buffer来匹配新的窗口大小,并使用 InvalidateBuffers 事件通知DRI clinet渲染到窗口中的更改,以便他们检索 GEM新缓冲区的名称。
DRI2 扩展为 DRI client提供了其他核心操作,如DRI2Connect接口可以找出他们应该使用哪个 DRM 设备和驱动程序 或DRI2Authenticate接口通过 X Server进行身份验证以便能够使用 DRM 设备的渲染和缓冲设施。使用 DRI2CopyRegion 和 DRI2SwapBuffers 请求在屏幕中呈现渲染buffer。DRI2CopyRegion 可用于在fake-front-buffer和real-front-buffer之间进行复制,但它不提供与v-black间隔的任何同步,因此会导致撕裂。 另一方面,DRI2SwapBuffers在back-buffer和front-buffer之间执行v-blank同步交换。

DRI3阶段

虽然 DRI2 比DRI 有了显着的改进,不过扩展也引入了一些新的问题。2013年,为了解决新的问题,DRI3作为DRI的第3次迭代被开发了。
DRI3 与 DRI2 相比的主要区别在于:

  • DRI3 client为自己分配渲染缓冲区,而不是依赖 X Server进行分配(这是DRI2 支持的方法)。
  • DRI3 摆脱了旧的基于 GEM 名称(全局 GEM 句柄)的不安全 GEM buffer共享机制(用于在 DRI client和 X Server之间传递buffer对象),转而采用基于 PRIME DMA-BUF(使用文件描述符) 的更安全和通用的机制。

client的缓冲区分配打破了 GLX 的假设,因为多个 GLX 应用程序不再可能在同一个窗口中协同渲染。 从好的方面来说,DRI client在其生命周期内负责自己的缓冲区这一事实带来了许多优势,例如DRI3 client很容易确保渲染buffer的大小始终与窗口的当前大小相匹配,从而消除由于client和server之间缺乏缓冲区大小同步而困扰窗口大小调整。还实现了更好的性能,因为 DRI3 client节省了等待 X server发送渲染buffer的额外耗时。DRI3 client(尤其是合成器窗口管理器)可以利用保留前一帧的buffer区并重用它们仅对渲染窗口中变化的部分进行重绘。DRI3 扩展不再需要修改以支持新的特定缓冲区格式,因为现在直接在 DRI client驱动程序和 DRM kernel驱动程序之间处理。另一方面,文件描述符的使用允许kernel对任何未使用的 GEM buffer对象执行安全清理。
从技术上将,DRI3包含2个扩展:“DRI3”扩展和“Present”扩展。DRI3 扩展的主要目的是实现在 DRI client和 X Server之间共享直接渲染buffer的机制。DRI client分配和使用 GEM buffer对象作为渲染目标,而 X server使用一种称为“pixmap”的 X11 对象表示这些渲染缓冲区。DRI3 提供了两种接口:DRI3PixmapFromBuffer 和 DRI3BufferFromPixmap,前者是从 GEM buffer对象(在“DRI client空间”中)创建pixmap (在“X server空间”中),后者是反向操作。在这些 DRI3 接口中,GEM buffer对象作为 DMA-BUF 文件描述符而不是 GEM 名称传递。DRI3 还提供了一种在 DRI client和 X server之间共享同步对象的方法,允许对共享buffer进行序列化访问。和 DRI2不同,DRI3Open(每个 DRI 客户端必须请求知道要使用哪个 DRM 设备的操作)将已打开的文件描述符返回到设备节点而不是设备节点文件名,并且任何所需的身份验证过程已经提前执行 X sever。
DRI3 没有提供在屏幕上显示渲染缓冲区的机制,而是依赖另一个扩展,即 Present 扩展来做到这一点。Present 之所以如此命名,是因为它的主要任务是在屏幕上“Present ”缓冲区,这意味着它使用client应用程序提供的渲染缓冲区的内容来处理帧缓冲区的更新。屏幕更新必须在适当的时间完成,通常是在 VBLANK 间隔期间,以避免出现撕裂等显示问题。Present 还处理屏幕更新到 VBLANK 间隔的同步。它还使用事件让 X client知道每个缓冲区真正显示在屏幕上的时刻,因此client可以将其渲染过程与当前屏幕刷新率同步。

Present 接受任何 X pixmap 作为屏幕更新的来源.由于pixmap 是标准的 X 对象,Present 不仅可以由执行直接渲染的 DRI3 客户端使用,而且可以由任何 X 客户端以任何方式在pixmap 上渲染。例如大多数基于非 GL 的 GTK+ 和 Qt 应用程序过去使用 XRender 进行双缓冲pixmap 渲染。这些应用程序也可以使用 Present 扩展来实现高效且无撕裂的屏幕更新。这就是 Present 作为独立扩展而不是 DRI3 的一部分的原因。
除了允许非 GL X client与 VBLANK 同步之外,Present 还有其他优势。DRI3 图形性能更好,因为 Present 在交换缓冲区方面比​​ DRI2 更有效。基于 Present 提供的新功能, DRI2 中许多不可用的 OpenGL 扩展被支持。
Present 为 X client提供了两个主要接口:PresentPixmap:使用pixmap 的部分或全部内容更新窗口的区域;PresentSelectInput :设置与client想要通知的窗口的Present事件的类型 。窗口可以通知 X client的三个Present事件:1、当PresentPixmap 的调用完成时(PresentCompleteNotify); 2、当 PresentPixmap 使用的pixmap 准备好被重用时(PresentIdleNotify ); 3、当窗口配置(主要是窗口大小)发生变化时 (PresentConfigureNotify)。PresentPixmap 执行直接复制 (blit) 到front-buffer还是整个back-buffer与front-buffer的交换是 Present 扩展实现的内部细节,而不是 像DRI2那样X cleint的显式选择。

采用

几个开源 DRI 驱动程序,包括用于 ATI Mach64、ATI Rage128、ATI Radeon、3dfx Voodoo3 到 Voodoo5、Matrox G200 到 G400、SiS 300 系列、Intel i810 到 i965、S3 Savage、VIA UniChrome 图形芯片组和 Nvidia的nouveau。一些图形供应商使用的闭源 DRI 驱动程序,包括 ATI 和 PowerVR Kyro。
各种版本的 DRI 已由各种操作系统实现,其中包括 Linux kernel、FreeBSD、NetBSD、OpenBSD 和 OpenSolaris。

历史

该项目由 Precision Insight(由 Silicon Graphics 和 Red Hat 资助)的 Jens Owen 和 Kevin E. Martin 发起,它最初是作为 XFree86 4.0的一部分广泛使用的,现在是 X.Org Server 的一部分。它目前由自由软件社区维护。
DRI2 的工作始于 2007 年 X 开发者峰会,由 Kristian Høgsberg 提出。Høgsberg 自己编写了新的 DRI2 扩展以及对 Mesa 和 GLX 的修改。2008 年 3 月,DRI2 基本完成,但它无法进入 X.Org Server 版本 1.5,不得不从 2009 年 2 月开始等到版本 1.6。DRI2 扩展正式包含在 2009 年 10 月的 X11R7.5 版本中。 DRI2 协议 (2.0) 的第一个公共版本于 2009 年 4 月发布。从那以后进行了多次修订,最近的版本是 2012 年 7 月的 2.8 版。
由于 DRI2 的一些限制,Keith Packard 和 Emma Anholt 在 2012 年 X.Org 开发者大会上提出了一个名为 DRI-Next 的新扩展,该扩展在 Linux.conf.au 2013 上再次被提议为 DRI3000,DRI3 和 Present 扩展是在 2013 年开发的,并于 2013 年 12 月合并到 X.Org Server 1.15 版本中。DRI3 协议 (1.0) 的第一个也是唯一一个版本于 2013 年 11 月发布。下面5个图是DRI框架变化过程:
在这里插入图片描述

图1:2D drivers在X Server

在这里插入图片描述

图2:通过GLX间接渲染

在这里插入图片描述

图3:早期DRI:由X-display-server以root身份执行mode-setting

在这里插入图片描述

图4:所有访问都通过DRM进行

在这里插入图片描述

图5:在Linux内核3.12中引入了渲染节点;DRM 和 KMS 驱动程序被拆分。Wayland 通过 EGL 实现直接渲染

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

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

相关文章

一维数组2和二维数组1

1.一维数组在内存中的储存 在前面创建的数组中,每个元素是怎么储存的呢?我们通过观察元素的地址来看看吧。 %p是用来打印地址的。 结果为: 由此可看出每个地址都相隔一个int类型的距离,可以看出数组在内存中是连续存放的。也就是…

2024美赛数学建模思路 - 案例:最短时间生产计划安排

文章目录 0 赛题思路1 模型描述2 实例2.1 问题描述2.2 数学模型2.2.1 模型流程2.2.2 符号约定2.2.3 求解模型 2.3 相关代码2.4 模型求解结果 建模资料 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 模型…

51单片机驱动点阵屏

目录 1设计目的 2设计方案 2.1材料选择 2.2电源设计 2.3控制设计 3焊接调试 3.1焊接 3.2调试 4程序 1设计目的 此次设计的东西是一个点阵屏,通过点阵屏实现电梯屏幕功能。显示内容包括向上运行箭头和向下运行箭头,以及1-12的楼层。 2设计方案 …

龟兔再跑

欢迎来到程序小院 龟兔再跑 玩法&#xff1a;乌龟跳绳&#xff0c;点击鼠标左键乌龟跳跃&#xff0c;两只乌龟一直不停的甩绳子&#xff0c;另外一只乌龟从中跳过&#xff0c;赶快去跳绳吧^^。开始游戏https://www.ormcc.com/play/gameStart/255 html <div class"mai…

Vue开发者工具是什么?有哪些?

Vue开发者工具是什么&#xff1f; Vue开发者工具是用于Vue.js开发的浏览器扩展&#xff0c;提供了许多有用的功能和工具&#xff0c;帮助开发者更轻松地开发和调试Vue.js应用程序。 Vue开发者工具的功能特点有哪些&#xff1f; 1、组件树视图&#xff1a;Vue开发者工具可以显…

STM32-调用 vTaskStartScheduler API 后出现 HardFault

STM32 移植 FreeRTOS 后调用 vTaskStartScheduler() 后出现 HardFault 异常。 原因分析&#xff1a; FreeRTOS 配置头文件 FreeRTOSConfig.h 中与中断有关的配置和通过系统接口 void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) 设置的中断分组冲突。 /* The lo…

Java NIO (三)NIO Channel类

1 概述 前面提到&#xff0c;Java NIO中一个socket连接使用一个Channel来表示。从更广泛的层面来说&#xff0c;一个通道可以表示一个底层的文件描述符&#xff0c;例如硬件设备、文件、网络连接等。然而&#xff0c;远不止如此&#xff0c;Java NIO的通道可以更加细化。例如&a…

Python并发编程的概念和重要性

并发编程是一种编程方式&#xff0c;它允许在单台处理器上同时处理多个任务或操作。这些任务可以在单个处理器上通过时间分片技术实现&#xff0c;也可以在多核或多处理器系统上真正地并行执行。并发性对于提高系统资源利用率、提升应用程序性能以及改善用户体验都至关重要。 并…

计算机网络-分层结构,协议,接口,服务

文章目录 总览为什么要分层怎样分层正式认识分层概念小结 总览 为什么要分层 发送文件前要做的准备工作很多 把这个准备工作分层小问题解决&#xff0c;也就分层解决 怎样分层 每层相互独立&#xff0c;每层做的工作不同 界面自然清晰&#xff0c;层与层之间的接口能够体现…

JS-日期对象

日期对象&#xff1a;用来表示时间的对象 作用&#xff1a;可以得到当前系统时间 实例化 在代码中发现了new关键字时&#xff0c;一般将这个操作称为实例化 创建一个时间对象并获取时间 1&#xff09;获得当前时间 const datenew Date() 2)获得指定时间 const datenew D…

蓝桥杯理历年真题 —— 数学

1. 买不到的数目 这道题目&#xff0c;考得就是一个日常数学的积累&#xff0c;如果你学过这个公式的话&#xff0c;就是一道非常简单的输出问题&#xff1b;可是如果没学过&#xff0c;就非常吃亏&#xff0c;在考场上只能暴力求解&#xff0c;或是寻找规律。这就要求我们什么…

【window】Windows11:该文件没有与之关联的应用来执行该操作

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff1a;人工智能 之前win10升级win11后&#xff0c;受不了桌面软件图标的的小箭头&#xff0c;所以弄掉了&#xff0c;但是随之而来产…

揭开Spring MVC的真面目

官方对于Spring MVC的描述为&#xff1a; Spring Web MVC是基于Servlet API框架构建的原始Web框架&#xff0c;从一开始就包含在Spring框架中。它的正式名称“Spring Web MVC”来自其源模块的名称&#xff08;Spring-webmvc&#xff09;&#xff0c;但它通常被称为“Spring-MVC…

数学建模--Radar图绘制

1.Radar图简介 最近在数学建模中碰见需要绘制Radar图(雷达图)的情况来具体分析样本的各个特征之间的得分与优劣关系&#xff0c;这样的情况比较符合雷达图的使用场景&#xff0c;一般来说&#xff0c;雷达图适用于展示多个维度的数据&#xff0c;并在一个平面上直观地呈现出不同…

宠物空气净化器推荐哪个好?实惠的猫用猫用净化器牌子测评

作为宠物主人&#xff0c;我们深知养宠物的乐趣和责任&#xff0c;但同时也面临着一些挑战&#xff0c;比如宠物掉毛、异味和空气质量等问题。这就是为什么越来越多的家庭选择宠物空气净化器&#xff0c;为我们创造一个清新、健康的室内环境。 无论我们多么爱我们的毛茸茸伙伴…

如何在 Ubuntu 22.04 上安装 Apache Web 服务器

前些天发现了一个人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;最重要的屌图甚多&#xff0c;忍不住分享一下给大家。点击跳转到网站。 如何在 Ubuntu 22.04 上安装 Apache Web 服务器 介绍 Apache HTTP 服务器是世界上使用最广泛的 Web 服务器。它…

【C++】priority_queue模拟实现过程中值得注意的点

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 前言 本篇文章旨在记录博主在模…

[已解决]mysql关闭SSL功能和永久关闭SSL设置

概述 在搭建服务器连接本地数据库时发现有个报错信息&#xff1a; SQLState - 08S01 com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure The last packet successfully received from the server was 292 milliseconds ago. The last …

如何查看苹果手机的CPU型号?

摘要 本文将介绍如何在苹果手机上查看CPU型号。通过简单的设置操作&#xff0c;您可以轻松地获取您的iPhone的CPU型号信息。此外&#xff0c;我们还将介绍一些克魔助手可以提供的其他功能&#xff0c;如内存监控、GPU性能监控和网络抓包等&#xff0c;以帮助您优化和提升iOS应…

设计模式—行为型模式之观察者模式

设计模式—行为型模式之观察者模式 观察者模式(Observer Pattern)&#xff1a;定义对象间的一种一对多依赖关系&#xff0c;使得每当一个对象状态发生改变时&#xff0c;其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅&#xff08;Publish/Subscribe&#…