WDF驱动开发-I/O目标与专用USBI/O目标

Windows 驱动程序框架 (WDF) 驱动程序转发 I/O 请求或创建新请求并将其发送到另一个驱动程序就被称为 I/O 目标。

当 功能驱动程序、Filter驱动程序、微型端口驱动程序 收到 I/O 请求时,驱动程序可能能够单独处理请求,或者可能需要其他驱动程序的帮助。 如果驱动程序需要帮助,它可以将请求转发给另一个驱动程序,也可以创建一个或多个新请求并将其发送到另一个驱动程序。

在 Kernel-Mode Driver Framework 中, I/O 目标 表示作为 I/O 请求目标的设备对象。 函数、筛选器或微型端口驱动程序可以使用 I/O 目标将 I/O 请求发送到另一个驱动程序。 这些驱动程序通常会将其 I/O 请求发送到驱动程序堆栈中下一个较低的驱动程序。 因此,每个基于框架的函数、筛选器和微型端口驱动程序都有每个设备的 本地 I/O 目标 ,这是设备的下一个较低驱动程序。

有时,驱动程序必须将 I/O 请求发送到另一个目标,即不同驱动程序堆栈的顶部,或者发送驱动程序堆栈中的某些其他驱动程序。 因此,该框架还提供 远程 I/O 目标,这些目标由除本地 I/O 目标以外的所有 I/O 目标组成。

每个 I/O 目标由一个 I/O 目标对象表示。 每个 I/O 目标对象主要是一个队列,用于控制何时将请求传递到目标设备对象。 当驱动程序向 I/O 目标发送请求时,框架会将请求存储在队列中,直到它可以将请求传递到目标设备对象。

框架支持常规 I/O 目标和专用 I/O 目标:

  • 常规 I/O 目标 可由所有函数、筛选器和微型端口驱动程序使用,但它们不支持任何特定于设备的特殊数据格式;
  • 专用 I/O 目标使函数、筛选器和微型端口驱动程序能够轻松发送需要特定于目标的特殊数据格式的 I/O 请求。 目前,该框架只支持USB I/O 目标;

如果框架提供支持设备数据格式的专用 I/O 目标,则驱动程序应使用专用 I/O 目标。 否则,驱动程序应使用常规 I/O 目标。

常规 I/O 目标不支持特定于设备的特殊数据格式,例如 USB 请求块。 在驱动程序将数据发送到常规 I/O 目标之前,它们必须以 I/O 目标可以解释的格式将数据放入写入缓冲区。 同样,当驱动程序从常规 I/O 目标读取数据时,驱动程序必须能够解释从目标接收的数据缓冲区的内容。

常规 I/O 目标为本地或远程:

  • 本地 I/O 目标:每个基于框架的功能驱动程序、Filter驱动程序、微型端口驱动程序都有每个驱动程序设备的本地 I/O 目标。 设备的本地 I/O 目标始终是驱动程序堆栈中下一个较低的驱动程序;
  • 远程 I/O 目标: 远程 I/O 目标表示不同驱动程序堆栈的顶部, (很少) 当前驱动程序堆栈中的不同驱动程序;

USB I/O 目标

从版本 2 开始,Kernel-Mode Driver Framework (KMDF) 和 User-Mode Driver Framework (UMDF) 驱动程序可以和通用串行总线 (USB) 设备进行交互。

每个 USB 设备和 USB 设备接口支持的每个管道都有单独的 I/O 目标。 控制 USB 设备句柄发送到设备的 I/O 目标传输。 特定管道句柄的 I/O 传输将发送到该管道的 I/O 目标。

框架通过发送 USB 请求块 (URB) 来与 USB 设备的 I/O 目标通信。 框架提供对象方法,用于从驱动程序中隐藏 URL,以便驱动程序不必自行生成和发送它们。 如果希望驱动程序生成 URL,KMDF 驱动程序可以使用一组额外的对象方法来生成和发送 URL。

使用 USB 设备

下面介绍从版本 2 开始,Kernel-Mode驱动程序框架 (KMDF) 或User-Mode驱动程序框架 (UMDF) 驱动程序可以使用 Windows 驱动程序框架 (WDF) 提供的 USB 设备对象方法执行的操作。它包含以下部分:

创建 USB 设备对象
配置 USB 设备
获取设备信息
获取 USB 描述符
发送控制传输
重置和Power-Cycling设备的端口
将 URB 发送到设备。

创建 USB 设备对象

若要使用框架的 USB I/O 目标对象 (WDFUSBDEVICE、WDFUSBINTERFACE 和 WDFUSBPIPE) ,客户端驱动程序必须首先调用 WdfUsbTargetDeviceCreateWithParameters 来创建 USB 设备对象。 通常,驱动程序从其 EvtDevicePrepareHardware 回调函数调用 WdfUsbTargetDeviceCreateWithParameters。

当驱动程序调用 WdfUsbTargetDeviceCreateWithParameters 时,框架会创建一个 WDFUSBDEVICE 对象,并将其与表示 USB 设备的 FDO 相关联。 方法返回新的框架 USB 设备对象的句柄,USB 客户端驱动程序随后可以使用该句柄与物理设备通信。

调用 WdfUsbTargetDeviceCreateWithParameters 后,驱动程序可以调用 WdfUsbTargetDeviceGetDeviceDescriptor 和 WdfUsbTargetDeviceRetrieveConfigDescriptor 从设备获取 USB 描述符。 这些描述符包含有关设备的第一个配置、其接口设置及其定义的终结点的信息。 USB 描述符在官方 USB 规范中定义。

配置 USB 设备

WdfUsbTargetDeviceCreateWithParameters 方法还会为设备的第一个配置包含的每个 USB 接口创建框架 USB 接口对象。

调用 WdfUsbTargetDeviceCreateWithParameters 后,客户端驱动程序必须调用 WdfUsbTargetDeviceSelectConfig 来选择配置。 此方法为所选配置中接口的每个备用设置创建框架接口对象。

方法还创建管道对象,这些对象表示在所选配置的每个接口的每个备用设置中定义的终结点。

选择配置后,可以根据需要更改配置接口的 备用设置 。

还可以调用 WdfUsbTargetDeviceSelectConfig 来取消配置设备。

获取设备信息

配置设备后,客户端驱动程序可以调用以下方法来获取有关 USB 设备的信息:

  • WdfUsbTargetDeviceQueryUsbCapability:确定主控制器和 USB 驱动程序堆栈是否支持特定功能。 在调用 WdfUsbTargetDeviceQueryUsbCapability 之前,驱动程序必须调用 WdfUsbTargetDeviceCreateWithParameters;
  • WdfUsbTargetDeviceGetIoTarget:返回与 USB 设备关联的 I/O 目标对象的句柄。 驱动程序可以将此句柄传递给 WdfRequestSend 或 WdfIoTargetStop;
  • WdfUsbTargetDeviceRetrieveInformation:检索与 USB 设备关联的版本和功能信息;
  • WdfUsbTargetDeviceIsConnectedSynchronous (仅KMDF ):确定设备是否已连接;
  • WdfUsbTargetDeviceRetrieveCurrentFrameNumber (仅 KMDF):检索当前 USB 帧编号;

获取 USB 描述符

若要获取 USB 设备描述符中包含的 Unicode 字符串,驱动程序可以调用以下任一方法:

  • WdfUsbTargetDeviceGetDeviceDescriptor:获取设备的 USB 设备描述符;
  • WdfUsbTargetDeviceRetrieveConfigDescriptor:获取设备的 USB 配置描述符、接口描述符和终结点描述符;
  • WdfUsbTargetDeviceQueryString:将 Unicode 字符串复制到驱动程序提供的缓冲区;
  • WdfUsbTargetDeviceAllocAndQueryString:将 Unicode 字符串复制到框架提供的缓冲区;
  • WdfUsbTargetDeviceFormatRequestForString:设置 Unicode 字符串请求的格式。 驱动程序可以调用 WdfRequestSend 以同步或异步方式发送请求;

发送控制传输

驱动程序可以调用以下方法来发送 I/O 请求,该请求描述标准、特定于设备类或特定于供应商的 USB 控制传输。

  • WdfUsbTargetDeviceSendControlTransferSynchronously:同步发送 USB 控制传输请求;
  • WdfUsbTargetDeviceFormatRequestForControlTransfer:设置 USB 控制传输请求的格式。 驱动程序可以调用 WdfRequestSend 以同步或异步方式发送请求;

重置和Power-Cycling设备的端口

驱动程序可以调用以下方法来重置设备连接到的 USB 端口或重启电源:

  • WdfUsbTargetDeviceResetPortSynchronously:同步发送重置设备的 USB 端口的请求;
  • WdfUsbTargetDeviceCyclePortSynchronously (仅KMDF):同步发送请求以对设备的 USB 端口进行电源循环;
  • WdfUsbTargetDeviceFormatRequestForCyclePort (仅 KMDF):设置对设备 USB 端口进行电源循环的请求的格式。 驱动程序必须调用 WdfRequestSend 以同步或异步方式发送请求;

将 URB 发送到设备

如果 KMDF 驱动程序通过发送包含 URB 的 I/O 请求与其 USB 设备通信,则驱动程序可以调用以下方法:

  • WdfUsbTargetDeviceCreateUrb (仅KMDF):分配 USB 请求块 (URB) 。 在调用 WdfUsbTargetDeviceCreateUrb 之前,驱动程序必须调用 WdfUsbTargetDeviceCreateWithParameters;
  • WdfUsbTargetDeviceCreateIsochUrb (仅KMDF):分配常时等量 USB 请求块 (URB) 。 在调用 WdfUsbTargetDeviceCreateIsochUrb 之前,驱动程序必须调用 WdfUsbTargetDeviceCreateWithParameters;
  • WdfUsbTargetDeviceSendUrbSynchronously (仅KMDF):同步发送包含 URB 的 I/O 请求;
  • WdfUsbTargetDeviceFormatRequestForUrb (仅KMDF):设置包含 URB 的 I/O 请求的格式。 驱动程序必须调用 WdfRequestSend 以同步或异步方式发送请求;
  • WdfUsbTargetDeviceWdmGetConfigurationHandle (仅KMDF):返回设备的 USBD 配置句柄。 某些 URL 需要此句柄;

使用 USB 接口

框架将每个 USB 接口表示为 框架 USB 接口对象。 当驱动程序 创建框架 USB 设备对象时,框架会为设备的第一个 USB 配置包含的每个 USB 接口创建框架 USB 接口对象。

大多数 USB 设备只有一个接口,该接口只有一个备用设置。 此类设备的驱动程序通常不需要使用框架的 USB 接口对象定义的对象方法。

如果驱动程序支持提供多个接口或备用设置的 USB 设备,则接口对象方法使驱动程序能够执行以下操作:

  • 获取接口信息;
  • 选择 USB 接口的备用设置;

获取接口信息

驱动程序调用 WdfUsbTargetDeviceCreateWithParameters 后,它可以调用 WdfUsbTargetDeviceGetInterface 以获取表示设备 USB 接口之一的框架 USB 接口对象的句柄。 然后,驱动程序可以调用 USB 接口对象定义的几种方法来获取有关 USB 接口的信息。

驱动程序可以在调用 WdfUsbTargetDeviceCreateWithParameters 后随时调用以下方法:

  • WdfUsbInterfaceGetInterfaceNumber返回与 USB 接口对象关联的 USB 接口编号;
  • WdfUsbInterfaceGetDescriptor检索与 USB 接口的备用设置之一关联的 USB 接口描述符;
  • WdfUsbInterfaceGetNumEndpoints返回与 USB 接口的备用设置之一关联的终结点数;
  • WdfUsbInterfaceGetEndpointInformation检索有关终结点及其关联管道的信息;

驱动程序在调用 WdfUsbTargetDeviceSelectConfig 后,可以调用以下方法:

  • WdfUsbInterfaceGetConfiguredSettingIndex返回一个索引值,该值标识当前为 USB 接口选择的备用设置;
  • WdfUsbInterfaceGetNumConfiguredPipes返回为指定的 USB 设备接口配置的管道数;
  • WdfUsbInterfaceGetConfiguredPipe返回与指定的 USB 设备接口和管道索引关联的框架管道对象的句柄;

为 USB 接口选择备用设置

驱动程序调用 WdfUsbTargetDeviceCreateWithParameters 后,驱动程序可以调用 WdfUsbInterfaceGetNumSettings 以获取 USB 接口支持的备用设置数。

驱动程序调用 WdfUsbTargetDeviceSelectConfig 为 USB 设备选择配置后,驱动程序可以调用 WdfUsbInterfaceSelectSetting ,为配置的 USB 接口之一选择备用设置。

设备的备用设置必须连续编号,从零开始。

使用 USB 管道

框架将 USB 接口中的每个管道表示为框架 USB 管道对象。 当驱动程序 配置 USB 设备时,框架会为每个所选接口中的每个管道创建一个框架 USB 管道对象。 管道对象方法使驱动程序能够执行以下操作:

  • 获取管道信息;
  • 从管道读取;
  • 写入管道;
  • 停止或重置管道;
  • 将 URB 发送到管道;

获取管道信息

调用 WdfUsbInterfaceGetConfiguredPipe 以获取框架 USB 管道对象的句柄后,驱动程序可以调用 USB 管道对象为获取有关 USB 管道的信息而定义的以下方法:

  • WdfUsbTargetPipeGetIoTarget:返回与 USB 管道关联的 I/O 目标对象的句柄。 驱动程序可以将此句柄传递给 WdfRequestSend;
  • WdfUsbTargetPipeGetInformation:检索有关 USB 管道及其终结点的信息;
  • WdfUsbTargetPipeGetType:返回 USB 管道的类型;
  • WdfUsbTargetPipeIsInEndpoint:确定 USB 管道是否连接到输入终结点;
  • WdfUsbTargetPipeIsOutEndpoint:确定 USB 管道是否连接到输出终结点;
  • WDF_USB_PIPE_DIRECTION_IN:确定 USB 终结点是否为输入终结点;
  • WDF_USB_PIPE_DIRECTION_OUT:确定 USB 终结点是否为输出终结点;

从管道读取

若要从 USB 输入管道读取数据,驱动程序可以使用以下三种技术中的任何 (或所有) :

1. 同步读取数据:若要从 USB 输入管道同步读取数据,驱动程序可以调用 WdfUsbTargetPipeReadSynchronously 方法。 此方法生成并发送读取请求,并在 I/O 操作完成后返回。

2. 异步读取数据:若要从 USB 输入管道异步读取数据,驱动程序可以调用 WdfUsbTargetPipeFormatRequestForRead 方法来生成读取请求。 然后,驱动程序可以调用 WdfRequestSend 以异步 (或同步) 发送请求。

3. 以异步方式连续读取数据:连续读取器是一种框架提供的机制,用于确保读取请求始终可用于 USB 管道。 此机制保证驱动程序始终准备好从提供异步、未经请求的输入流的设备接收数据。 例如,网络接口卡 (NIC) 的驱动程序可能会使用连续读取器来接收输入数据。

若要为输入管道配置连续读取器,驱动程序的 EvtDevicePrepareHardware 回调函数必须调用 WdfUsbTargetPipeConfigContinuousReader 方法。 此方法将一组读取请求排队到设备的 I/O 目标。

此外,驱动程序的 EvtDeviceD0Entry 回调函数必须调用 WdfIoTargetStart 才能启动连续读取器,驱动程序的 EvtDeviceD0Exit 回调函数必须调用 WdfIoTargetStop 来停止连续读取器。

每次从设备获取数据时,I/O 目标都将完成读取请求,框架将调用以下两个回调函数之一: EvtUsbTargetPipeReadComplete(如果 I/O 目标成功读取数据),如果 I/O 目标报告错误,则调用 EvtUsbTargetPipeReadersFailed。

如果不提供可选的 EvtUsbTargetPipeReadersFailed 回调,框架将通过发送另一个读取请求来响应失败的读取尝试。 因此,如果总线处于不接受读取的状态,框架会不断发送新的请求,以从失败的读取中恢复。

驱动程序调用 WdfUsbTargetPipeConfigContinuousReader 后,驱动程序无法使用 WdfUsbTargetPipeReadSynchronously 或 WdfRequestSend 将 I/O 请求发送到管道,除非调用了驱动程序的 EvtUsbTargetPipeReadersFailed 回调函数并返回 FALSE。

默认情况下,如果驱动程序指定的读取缓冲区不是管道最大数据包大小的倍数,框架将报告错误。 驱动程序可以调用 WdfUsbTargetPipeSetNoMaximumPacketSizeCheck 来禁用读取缓冲区大小的此测试。

写入管道

若要将数据写入 USB 输出管道,驱动程序可以使用一 (或两者) 以下技术:

  • 同步写入数据:若要将数据同步写入 USB 输出管道,驱动程序可以调用 WdfUsbTargetPipeWriteSynchronously 方法。 此方法生成并发送写入请求,并在 I/O 操作完成后返回;
  • 异步写入数据:若要将数据异步写入 USB 输入管道,驱动程序可以调用 WdfUsbTargetPipeFormatRequestForWrite 方法来生成写入请求。 然后,驱动程序可以调用 WdfRequestSend 以异步发送请求;

停止和重置管道

驱动程序可以调用以下方法来停止或重置 USB 管道:

  • WdfUsbTargetPipeAbortSynchronously:同步发送停止 USB 管道的请求;
  • WdfUsbTargetPipeFormatRequestForAbort:设置停止 USB 管道的请求的格式。 驱动程序可以调用 WdfRequestSend 以同步或异步方式发送请求;
  • WdfUsbTargetPipeResetSynchronously:同步发送重置 USB 管道的请求;
  • WdfUsbTargetPipeFormatRequestForReset:设置重置 USB 管道的请求的格式。 驱动程序必须调用 WdfRequestSend 以同步或异步方式发送请求;

如果驱动程序的 USB 目标以错误状态值 完成 I/O 请求,则驱动程序应执行以下操作:

  • 1. 如果目标尚未完成请求,请停止管道并取消驱动程序已发送到 USB 目标的任何其他 I/O 请求,调用 设置了 WdfIoTargetCancelSentIo 标志的 WdfIoTargetStop ;
  • 2. 向管道同步发送中止请求:调用 WdfUsbTargetPipeAbortSynchronously,或调用 WdfUsbTargetPipeFormatRequestForAbort ,后跟 WdfRequestSend 并设置 WDF_REQUEST_SEND_OPTION_SYNCHRONOUS 标志;
  • 3. 同步向管道发送重置请求:调用 WdfUsbTargetPipeResetSynchronously,或调用 WdfUsbTargetPipeFormatRequestForReset ,然后调用 WdfRequestSend 并设置 WDF_REQUEST_SEND_OPTION_SYNCHRONOUS 标志;
  • 4. 重启管道:调用 WdfIoTargetStart;
  • 5. 重新发送失败的 I/O 请求,以及失败请求后的所有 I/O 请求;

多次失败后,驱动程序应尝试通过执行以下操作来重置 USB 端口:

  • 1. 如果目标尚未完成,请停止所有活动管道,并取消驱动程序发送到每个管道的 USB 目标的任何其他 I/O 请求。对于每个活动管道,调用 设置了 WdfIoTargetCancelSentIo 标志的 WdfIoTargetStop ;
  • 2. 同步发送重置 USB 端口的请求。调用 WdfUsbTargetDeviceResetPortSynchronously;
  • 3. 重启管道。为驱动程序停止的每个管道调用 WdfIoTargetStart ;
  • 4. 重新发送失败的最后一个 I/O 请求,以及失败请求后的所有 I/O 请求;

将 URB 发送到管道

如果 KMDF 驱动程序通过发送包含 URB 的 I/O 请求与 USB 管道通信,则驱动程序可以调用以下方法:

  • WdfUsbTargetPipeSendUrbSynchronously (仅KMDF):同步发送包含 URB 的 I/O 请求;
  • WdfUsbTargetPipeFormatRequestForUrb (仅 KMDF):设置包含 URB 的 I/O 请求的格式。 驱动程序可以调用 WdfRequestSend 以同步或异步方式发送请求;
  • WdfUsbTargetPipeWdmGetPipeHandle (仅KMDF ):返回设备的 USBD 管道句柄。 某些 URB 需要此句柄;

 

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

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

相关文章

【Ni板卡使用方法和连接SOC】

NI(National Instruments)板卡是一种用于数据采集、控制和测试的应用设备。以下是关于NI板卡的基本使用方法和连接SOC(System on Chip,系统级芯片)的步骤: 一、NI板卡的基本使用方法 了解板卡型号和规格&…

vivado TILE

TILE是包含一个或多个SITE对象的设备对象。可编程逻辑TILE 包括各种各样的对象,如SLICE/CLB、BRAM、DSP、I/O块、时钟资源,以及 GT块。从结构上讲,每个瓦片都有许多输入和输出,并且可编程 互连以将瓦片的输入和输出连接到任何其他…

实现一个简易动态线程池

项目完整代码:https://github.com/YYYUUU42/Yu-dynamic-thread-pool 如果该项目对你有帮助,可以在 github 上点个 ⭐ 喔 🥰🥰 1. 线程池概念 2. ThreadPoolExecutor 介绍 2.1. ThreadPoolExecutor是如何运行,如何同时…

elementUI的el-table自定义表头

<el-table-column label"昨日仪表里程(KM)" align"left" min-width"190" :render-header"(h, obj) > renderHeader(h, obj, 参数)" > <template slot-scope"scope"> <span>{{ scope.row.firstStartMil…

流程图工具评测:十大热门软件对比

流程图是一种用图形符号和箭头表示工作流程的图形表示方法。它展示了一系列相互关联的步骤&#xff0c;以显示过程中数据或物质的流动、决策点和操作步骤。流程图广泛用于各种领域&#xff0c;包括业务流程、软件开发、工程等&#xff0c;以帮助人们更好地理解和分析工作流程。…

MongoDB中自动增长ID详解:实现、应用及优化

在MongoDB中&#xff0c;自动增长的功能主要通过使用数据库的ObjectId或自定义的序列来实现。ObjectId是MongoDB默认的主键类型&#xff0c;它是唯一的并且具有一定的排序特性。然而&#xff0c;在某些场景下&#xff0c;可能需要使用自定义的自动增长ID&#xff0c;例如在某些…

大模型应用开发实践:RAG与Agent

RAG planning是任务拆解的一些方法。 Agent RAG现在基本上推荐LangChain开发框架。而Agent目前没有一个通用的好的开发框架/范式。 学习路径

程序员做电子书产品变现的复盘(10)

前面提到了我对竞争对手发起的投诉&#xff0c;没想到这竟然引发了一场规模庞大的战争&#xff0c;意外地促进了我国版权合规化的进步 。 以前&#xff0c;每当收到版权方的通知&#xff0c;无论APP有多受欢迎&#xff0c;我都会立即下架&#xff0c;一方面是为了避免法律风险…

达梦8 兼容MySQL语法支持非分组项作为查询列

MySQL 数据库迁移到达梦后&#xff0c;部分GROUP BY语句执行失败&#xff0c;报错如下&#xff1a; 问题原因&#xff1a; 对于Oracle数据库&#xff0c;使用GROUP BY时&#xff0c;SELECT中的非聚合列必须出现在GROUP BY后面&#xff0c;否则就会报上面的错误&#xff0c;达梦…

使用宝塔面板搭建Flask项目保姆级喂饭教程

目录 零.前言 一.准备工作 1.1创建requirements.txt文件 1.2将项目打包为压缩文件 1.3租一台服务器 1.4部署宝塔面板 二.宝塔面板(服务器)上的操作 2.1将本地Flask项目上传到服务器 2.2添加Python项目 2.3配置Python项目 2.4配置Nginx 2.5宝塔面板放行端口 2.6在服…

【html5的video标签在移动端的使用】【微信内部浏览器video自动播放】【vue-video-player】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、使用步骤1. html部分2.js部分 二、使用插件vue-video-player1、下载插件2、使用3、在组件中使用 三、最终的版本&#xff08;自用版本&#xff09;四、vide…

linux运维工作常用命令

命令 --help //可以快速查看命令的用法及其各种选项 cat /etc/passwd //查看所有用户 who //查看已登录用户 sudo useradd 用户名 …

首个AI高考评测结果出炉,GPT-4o排名第二

近日&#xff0c;上海人工智能实验室利用其自主研发的“司南”评测体系OpenCompass&#xff0c;对国内外多个知名大模型进行了一场特殊的“高考”。这些来自阿里巴巴、智谱AI、Mistral等机构&#xff0c;以及OpenAI的GPT-4o等“考生”&#xff0c;接受了新课标I卷“语数外”的全…

百万级 QPS 接入层网关架构方案演进

文章目录 前言1、单机架构2、DNS 轮询3、Nginx 单机4、Nginx 主备 Keepalived5、LVS 主备 Keepalived Nginx 集群6、LVS 主备 Keepalived Nginx 集群 DNS 轮询 前言 随着PC、移动互联网的快速发展&#xff0c;越来越多的人通过手机、电脑、平板等设备访问各种各样APP、网…

找不到com.fasterxml.jackson.core.exc.StreamWriteException的类文件

1. 前言: 使用springboot搭建的项目, 需要使用 jackson 更改json文件的内容; maven管理jar包, 导入jar包版本信息如下: <!-- 读写json文件所需依赖 --> <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databin…

C++语法06 格式化输出及保留小数点后指定位数

格式化输出 格式化输出所用的函数为 printf&#xff0c;它可以输出任意位数的小数。 使用格式&#xff1a;printf(“%.nf”,a)。这句话的作用是将变量a保留n位小数输出。 注意事项&#xff1a; 1、这里的n&#xff0c;需要具体化为一个数字&#xff0c;保留几位小数&#x…

【ARMv8/v9 GIC 系列 3 -- GIC 的 类型寄存器 GICD_TYPER】

文章目录 GIC 类型寄存器 GICD_TYPERESPI_Range, 位[31:27]RSS, 位[26]No1N, 位[25]A3V, 位[24]IDBits, 位[23:19]DVIS, 位[18]LPIs, 位[17]MBIS, 位[16]NUM_LPIs, 位[15:11]SecurityExtn, 位[10]NMI, 位[9]ESPI, 位[8]CPUNumber, 位[7:5]ITLinesNumber, 位[4:0]GIC 类型寄存器…

GDB调试助手用法详解

什么是GDB GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许&#xff0c;各位比较喜欢那种图形界面方式的&#xff0c;像VC、BCB等IDE的调试&#xff0c;但如果你是在 UNIX平台下做软件&#xff0c;你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能…

朗科HD10M2Pr震撼上市,自带风扇极速降温,匹敌私有云

近日,存储领域的领军企业朗科旗下全资子公司朗科创新宣布,其最新款磁吸硬盘盒HD10M2Pr正式上市。这款产品凭借超薄设计、极速降温、高速传输等多项优势,迅速成为了行业内的讨论焦点。 随着移动设备使用的普及和短视频内容的日益丰富,对于存储空间不断增长的需求逐渐成为日常生活…

liquibase 错误: 无法打开扩展控制文件 “c:/postgresql/14/share/extension/timescaledb.control“

背景 运行springboot项目时&#xff0c;在一开始运行liquibase部分报错&#xff0c;报错信息如题所示&#xff0c;经查&#xff0c;是因为安装postgresql时没有安装这个名为timescaledb的扩展&#xff0c;所以接下来就是安装timescaledb扩展。 安装timescaledb扩展 我的电脑…