windows USB 驱动开发-URB结构

通用串行总线 (USB) 客户端驱动程序无法直接与其设备通信。 相反,客户端驱动程序会创建请求并将其提交到 USB 驱动程序堆栈进行处理。 在每个请求中,客户端驱动程序提供一个可变长度的数据结构,称为 USB 请求块 (URB) ,URB 结构描述请求的详细信息,还包含有关已完成请求状态的信息。 客户端驱动程序通过 URL 执行所有特定于设备的操作,包括数据传输。 在将请求提交到 USB 驱动程序堆栈之前,客户端驱动程序必须使用有关请求的信息初始化 URB。 对于某些类型的请求,Microsoft 提供帮助程序例程和宏,这些例程和宏分配 URB 结构,并使用客户端驱动程序提供的详细信息填充 URB 结构的必要成员。

每个 URB 都以标准固定大小的标头开头, (_URB_HEADER) ,其用途是标识请求的操作类型。 _URB_HEADER 的 Length 成员指定 URB 的大小(以字节为单位)。 Function 成员必须是一系列系统定义的URB_FUNCTION_XXX常量之一,用于确定所请求的操作类型。 例如,在数据传输的情况下,此成员指示传输的类型。 函数代码URB_FUNCTION_CONTROL_TRANSFER、URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER和URB_FUNCTION_ISOCH_TRANSFER分别指示控制、批量/中断和常时等量传输。 USB 驱动程序堆栈使用 Status 成员返回特定于 USB 的状态代码。

为了提交 URB,客户端驱动程序使用 IOCTL_INTERNAL_USB_SUBMIT_URB 请求,该请求通过 I/O 请求数据包 (IRP) 类型IRP_MJ_INTERNAL_DEVICE_CONTROL传递到设备。

USB 驱动程序堆栈处理完 URB 后,驱动程序堆栈将使用 URB 结构的 Status 成员返回特定于 USB 的状态代码。

KMDF 和 UMDF 驱动程序开发人员应使用相应的框架接口来与 USB 设备通信。 

分配和构建 URB

USB 客户端驱动程序可以使用 Windows 驱动程序模型 (WDM) 驱动程序例程来分配 URB 并格式化 URB,然后再将请求发送到 Microsoft 提供的 USB 驱动程序堆栈。

客户端驱动程序使用 URB 打包 USB 驱动程序堆栈中较低级驱动程序处理请求所需的所有信息。 在 Windows 操作系统中,URB 在 URB 结构中描述。

Microsoft 为 USB 客户端驱动程序提供了例程库。 通过使用这些例程,USB 客户端驱动程序可以为某些指定操作生成 URB 请求,并将其转发到 USB 堆栈中。 如果愿意,可以将客户端驱动程序设计为为支持的操作调用库例程,而不是生成自己的 URB 请求。

Windows 7 及更早版本中的 URB 分配

若要使用适用于 Windows 7 及更早版本的 Windows 的 Windows 驱动程序工具包 (WDK) 中包含的例程发送 USB 请求,客户端驱动程序通常会分配和填充 URB 结构,将 URB 结构与新的 IRP 相关联,并将 IRP 发送到 USB 驱动程序堆栈。

对于某些类型的请求,Microsoft 提供 (由分配 URB 结构的Usbd.sys) 导出的帮助程序例程。 例如, USBD_CreateConfigurationRequestEx 例程为 URB 结构分配内存,为选择配置请求设置 URB 格式,并将 URB 结构的地址返回到客户端驱动程序。 但是,帮助程序例程不能用于所有类型的请求。

Microsoft 还提供了为某些类型的请求设置 URL 格式的宏。 对于这些宏,客户端驱动程序必须通过调用 ExAllocatePoolWithTag 来分配 URB 结构,或者在堆栈上分配 结构。 例如,在客户端驱动程序分配 URB 后,驱动程序可以调用 UsbBuildSelectConfigurationRequest 来格式化选择配置请求的 URB 或清除配置。

对于其他请求,客户端驱动程序必须根据请求类型,通过设置 URB 结构的各个成员来手动分配 和格式化 URB 。

USB 请求完成后,客户端驱动程序必须释放 URB 结构。 如果在堆栈上分配 URB,则 URB 在超出范围时释放。 如果在非分页池中分配 URB,则客户端驱动程序必须调用 ExFreePool 才能释放 URB。

Windows 8中的 URB 分配

WDK for Windows 8 提供了一个新的静态库 Usbdex.lib,用于导出用于分配、格式化和释放 URL 的例程。 此外,还有一种将 URB 与 IRP 相关联的新方法。 新的例程可由面向 Windows Vista 和更高版本的 Windows 的客户端驱动程序调用。

在 Windows Vista 及更高版本上运行的客户端驱动程序必须使用新的例程,以便基础 USB 驱动程序堆栈可以利用某些性能和可靠性改进。 这些改进适用于 Windows 8 中为支持 USB 3.0 设备和主机控制器而引入的新 USB 驱动程序堆栈。 对于 USB 2.0 主控制器,Windows 加载不支持改进的驱动程序堆栈的早期版本。 无论基础驱动程序堆栈的版本或主机控制器支持的协议版本如何,都必须始终调用新的 URB 例程。

在调用任何新例程之前,请确保有一个 USBD 句柄,用于向 USB 驱动程序堆栈注册客户端驱动程序。 若要获取 USBD 句柄, 请调用 USBD_CreateHandle。

WDK 提供以下例程,用于Windows 8。 这些例程在 Usbdlib.h 中定义。

  • USBD_UrbAllocate
  • USBD_IsochUrbAllocate
  • USBD_SelectConfigUrbAllocateAndBuild
  • USBD_SelectInterfaceUrbAllocateAndBuild
  • USBD_UrbFree
  • USBD_AssignUrbToIoStackLocation

前面列表中的分配例程返回指向由 USB 驱动程序堆栈分配的新 URB 结构的指针。 根据 Windows 加载的 USB 驱动程序堆栈的版本, URB 结构可以与不透明的 URB 上下文配对。 URB 上下文是有关 URB 的信息块。 无法查看 URB 标头的内容;这些信息旨在由 USB 驱动程序堆栈在内部使用,以改善 URB 跟踪和处理。 URB 上下文仅由 USB 驱动程序堆栈用于Windows 8。 如果 URB 上下文可用,USB 驱动程序堆栈会使用它使 URB 处理更安全、更高效。 例如,USB 驱动程序堆栈必须确保客户端驱动程序不会提交 URB,然后尝试在第一个请求完成之前重复使用同一 URB。 为了检测此类错误,USB 驱动程序堆栈会将状态信息存储在 URB 上下文中。 如果没有状态信息,USB 驱动程序堆栈将不得不将传入的 URB 与当前正在进行的所有 URB 进行比较。 当客户端驱动程序尝试释放 URB 时,USB 驱动程序堆栈也会使用状态信息。 在释放 URB 之前,USB 驱动程序堆栈会验证状态,以确保 URB 未挂起。

URB 上下文提供用于存储额外 URB 信息的官方机制。 使用 URB 上下文比根据需要分配额外的内存或在 URB 结构的保留成员中存储额外信息更可取。 USB 驱动程序堆栈在非分页池中分配 URB 及其关联的 URB 上下文,以便将来如果需要更大的 URB 上下文,唯一需要调整的是池分配的大小。

URB的结构
typedef struct _URB {union {
#if ..._URB_HEADER                                     UrbHeader;
#elsestruct _URB_HEADER                              UrbHeader;
#endif
#if ..._URB_SELECT_INTERFACE                           UrbSelectInterface;
#elsestruct _URB_SELECT_INTERFACE                    UrbSelectInterface;
#endif
#if ..._URB_SELECT_CONFIGURATION                       UrbSelectConfiguration;
#elsestruct _URB_SELECT_CONFIGURATION                UrbSelectConfiguration;
#endif
#if ..._URB_PIPE_REQUEST                               UrbPipeRequest;
#elsestruct _URB_PIPE_REQUEST                        UrbPipeRequest;
#endif
#if ..._URB_FRAME_LENGTH_CONTROL                       UrbFrameLengthControl;
#elsestruct _URB_FRAME_LENGTH_CONTROL                UrbFrameLengthControl;
#endif
#if ..._URB_GET_FRAME_LENGTH                           UrbGetFrameLength;
#elsestruct _URB_GET_FRAME_LENGTH                    UrbGetFrameLength;
#endif
#if ..._URB_SET_FRAME_LENGTH                           UrbSetFrameLength;
#elsestruct _URB_SET_FRAME_LENGTH                    UrbSetFrameLength;
#endif
#if ..._URB_GET_CURRENT_FRAME_NUMBER                   UrbGetCurrentFrameNumber;
#elsestruct _URB_GET_CURRENT_FRAME_NUMBER            UrbGetCurrentFrameNumber;
#endif
#if ..._URB_CONTROL_TRANSFER                           UrbControlTransfer;
#elsestruct _URB_CONTROL_TRANSFER                    UrbControlTransfer;
#endif
#if ..._URB_CONTROL_TRANSFER_EX                        UrbControlTransferEx;
#elsestruct _URB_CONTROL_TRANSFER_EX                 UrbControlTransferEx;
#endif
#if ..._URB_BULK_OR_INTERRUPT_TRANSFER                 UrbBulkOrInterruptTransfer;
#elsestruct _URB_BULK_OR_INTERRUPT_TRANSFER          UrbBulkOrInterruptTransfer;
#endif
#if ..._URB_ISOCH_TRANSFER                             UrbIsochronousTransfer;
#elsestruct _URB_ISOCH_TRANSFER                      UrbIsochronousTransfer;
#endif
#if ..._URB_CONTROL_DESCRIPTOR_REQUEST                 UrbControlDescriptorRequest;
#elsestruct _URB_CONTROL_DESCRIPTOR_REQUEST          UrbControlDescriptorRequest;
#endif
#if ..._URB_CONTROL_GET_STATUS_REQUEST                 UrbControlGetStatusRequest;
#elsestruct _URB_CONTROL_GET_STATUS_REQUEST          UrbControlGetStatusRequest;
#endif
#if ..._URB_CONTROL_FEATURE_REQUEST                    UrbControlFeatureRequest;
#elsestruct _URB_CONTROL_FEATURE_REQUEST             UrbControlFeatureRequest;
#endif
#if ..._URB_CONTROL_VENDOR_OR_CLASS_REQUEST            UrbControlVendorClassRequest;
#elsestruct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST     UrbControlVendorClassRequest;
#endif
#if ..._URB_CONTROL_GET_INTERFACE_REQUEST              UrbControlGetInterfaceRequest;
#elsestruct _URB_CONTROL_GET_INTERFACE_REQUEST       UrbControlGetInterfaceRequest;
#endif
#if ..._URB_CONTROL_GET_CONFIGURATION_REQUEST          UrbControlGetConfigurationRequest;
#elsestruct _URB_CONTROL_GET_CONFIGURATION_REQUEST   UrbControlGetConfigurationRequest;
#endif
#if ..._URB_OS_FEATURE_DESCRIPTOR_REQUEST              UrbOSFeatureDescriptorRequest;
#elsestruct _URB_OS_FEATURE_DESCRIPTOR_REQUEST       UrbOSFeatureDescriptorRequest;
#endif
#if ..._URB_OPEN_STATIC_STREAMS                        UrbOpenStaticStreams;
#elsestruct _URB_OPEN_STATIC_STREAMS                 UrbOpenStaticStreams;
#endif
#if ..._URB_GET_ISOCH_PIPE_TRANSFER_PATH_DELAYS        UrbGetIsochPipeTransferPathDelays;
#elsestruct _URB_GET_ISOCH_PIPE_TRANSFER_PATH_DELAYS UrbGetIsochPipeTransferPathDelays;
#endif};
} URB, *PURB;
URB 例程更新记录

下表汇总了 URB 例程中的更改。

如何提交 URB

客户端驱动程序使用 I/O 控制代码 (IOCTL) IOCTL 与设备通信,这些请求在 I/O 请求数据包 (IRP) 类型为 IRP_MJ_INTERNAL_DEVICE_CONTROL。 对于特定于设备的请求(如选择配置请求),与 IRP 关联的 USB 请求块 (URB) 中介绍了该请求。 将 URB 与 IRP 相关联并将请求发送到 USB 驱动程序堆栈的过程称为提交 URB。 若要提交 URB,客户端驱动程序必须使用 IOCTL_INTERNAL_USB_SUBMIT_URB 作为设备控制代码。 IOCTL 是提供 I/O 接口的“内部”控制代码之一,客户端驱动程序使用该接口来管理其设备和设备连接到的端口。 用户模式应用程序无权访问这些内部 I/O 接口。 

先决条件

在将请求发送到通用串行总线 (USB) 驱动程序堆栈之前,客户端驱动程序必须根据请求的类型分配 URB 结构和格式,如下步骤:

  • 通过调用 IoAllocateIrp 例程为 URB 分配 IRP。 必须提供接收 IRP 的设备对象的堆栈大小。 在对 IoAttachDeviceToDeviceStack 例程的上一次调用中,你收到了指向该设备对象的指针。 堆栈大小存储在 DEVICE_OBJECT 结构的 StackSize 成员中;
  • 通过调用 IoGetNextIrpStackLocation 获取指向 IRP 的第一个堆栈位置 (IO_STACK_LOCATION) 的指针;
  • 将 IO_STACK_LOCATION 结构的 MajorFunction 成员设置为IRP_MJ_INTERNAL_DEVICE_CONTROL;
  • 将 IO_STACK_LOCATION 结构的 Parameters.DeviceIoControl.IoControlCode 成员设置为IOCTL_INTERNAL_USB_SUBMIT_URB;
  • 将 IO_STACK_LOCATION 结构的 Parameters.Others.Argument1 成员设置为初始化的 URB 结构的地址。 若要将 IRP 关联到 URB,也可以仅当 URB 由 USBD_UrbAllocate、USBD_SelectConfigUrbAllocateAndBuild 或 USBD_SelectInterfaceUrbAllocateAndBuild 分配时才调用 USBD_AssignUrbToIoStackLocation;
  • 通过调用 IoSetCompletionRoutineEx 设置完成例程。如果异步提交 URB,请传递指向调用方实现的完成例程及其上下文的指针。 调用方在其完成例程中释放 IRP。如果要同步提交 IRP,请实现一个完成例程,并在调用 IoSetCompletionRoutineEx 时传递指向该例程的指针。 调用还需要 Context 参数中的初始化 KEVENT 对象。 在完成例程中,将 事件设置为信号状态;
  • 调用 IoCallDriver 将填充的 IRP 转发到设备堆栈中的下一个下一个设备对象。 对于同步调用,在调用 IoCallDriver 后,通过调用 KeWaitForSingleObject 来等待事件对象以获取事件通知;
  • 完成 IRP 后,检查 IRP 的 IoStatus.Status 成员并评估结果。 如果 IoStatus.Status STATUS_SUCCESS,则表示请求成功;
USB 同步提交

以下示例演示如何同步提交 URB。

// The SubmitUrbSync routine submits an URB synchronously.
//
// Parameters:
//      DeviceExtension: Pointer to the caller's device extension. The
//                       device extension must have a pointer to
//                       the next lower device object in the device stacks.  
//
//      Irp: Pointer to an IRP allocated by the caller.
//
//      Urb: Pointer to an URB that is allocated by  USBD_UrbAllocate,
//           USBD_IsochUrbAllocate, USBD_SelectConfigUrbAllocateAndBuild,
//           or USBD_SelectInterfaceUrbAllocateAndBuild.//      CompletionRoutine: Completion routine.
//
// Return Value:
//
//      NTSTATUS  NTSTATUS SubmitUrbSync( PDEVICE_EXTENSION DeviceExtension,PIRP Irp,PURB Urb,  PIO_COMPLETION_ROUTINE SyncCompletionRoutine)  {NTSTATUS  ntStatus;  KEVENT    kEvent;PIO_STACK_LOCATION nextStack;// Get the next stack location.nextStack = IoGetNextIrpStackLocation(Irp);  // Set the major code.nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;  // Set the IOCTL code for URB submission.nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;  // Attach the URB to this IRP.// The URB must be allocated by USBD_UrbAllocate, USBD_IsochUrbAllocate,// USBD_SelectConfigUrbAllocateAndBuild, or USBD_SelectInterfaceUrbAllocateAndBuild.USBD_AssignUrbToIoStackLocation (DeviceExtension->UsbdHandle, nextStack, Urb);KeInitializeEvent(&kEvent, NotificationEvent, FALSE);ntStatus = IoSetCompletionRoutineEx ( DeviceExtension->NextDeviceObject,  Irp,  SyncCompletionRoutine,  (PVOID) &kEvent,  TRUE,TRUE,TRUE);if (!NT_SUCCESS(ntStatus)){KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "IoSetCompletionRoutineEx failed. \n" ));goto Exit;}ntStatus = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);  if (ntStatus == STATUS_PENDING){KeWaitForSingleObject ( &kEvent,Executive,KernelMode,FALSE,NULL);}ntStatus = Irp->IoStatus.Status;Exit:if (!NT_SUCCESS(ntStatus)){// We hit a failure condition,// We will free the IRPIoFreeIrp(Irp);Irp = NULL;}return ntStatus;
}// The SyncCompletionRoutine routine is the completion routine
// for the synchronous URB submit request.
//
// Parameters:
//
//      DeviceObject: Pointer to the device object.
//      Irp:          Pointer to an I/O Request Packet.
//      CompletionContext: Context for the completion routine.
//
// Return Value:
//
//      NTSTATUS  NTSTATUS SyncCompletionRoutine ( PDEVICE_OBJECT DeviceObject,PIRP           Irp,PVOID          Context)
{PKEVENT kevent;kevent = (PKEVENT) Context;if (Irp->PendingReturned == TRUE){KeSetEvent(kevent, IO_NO_INCREMENT, FALSE);}KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Request completed. \n" ));return STATUS_MORE_PROCESSING_REQUIRED;
}

USB 异步提交
以下示例演示如何异步提交 URB。

// The SubmitUrbASync routine submits an URB asynchronously.
//
// Parameters:
//
// Parameters:
//      DeviceExtension: Pointer to the caller's device extension. The
//                       device extension must have a pointer to
//                       the next lower device object in the device stacks.  
//
//      Irp: Pointer to an IRP allocated by the caller.
//
//      Urb: Pointer to an URB that is allocated by  USBD_UrbAllocate,
//           USBD_IsochUrbAllocate, USBD_SelectConfigUrbAllocateAndBuild,
//           or USBD_SelectInterfaceUrbAllocateAndBuild.//      CompletionRoutine: Completion routine.
//
//      CompletionContext: Context for the completion routine.
//
//
// Return Value:
//
//      NTSTATUSNTSTATUS SubmitUrbASync ( PDEVICE_EXTENSION DeviceExtension,PIRP Irp,PURB Urb,  PIO_COMPLETION_ROUTINE CompletionRoutine,  PVOID CompletionContext)  
{// Completion routine is required if the URB is submitted asynchronously.// The caller's completion routine releases the IRP when it completes.NTSTATUS ntStatus = -1;  PIO_STACK_LOCATION nextStack = IoGetNextIrpStackLocation(Irp);  // Attach the URB to this IRP.nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;  // Attach the URB to this IRP.nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;  // Attach the URB to this IRP.(void) USBD_AssignUrbToIoStackLocation (DeviceExtension->UsbdHandle, nextStack, Urb);  // Caller's completion routine will free the irp when it completes.ntStatus = IoSetCompletionRoutineEx ( DeviceExtension->NextDeviceObject,Irp,  CompletionRoutine,  CompletionContext,  TRUE,TRUE,TRUE);if (!NT_SUCCESS(ntStatus)){goto Exit;}(void) IoCallDriver(DeviceExtension->NextDeviceObject, Irp);Exit:if (!NT_SUCCESS(ntStatus)){// We hit a failure condition,// We will free the IRPIoFreeIrp(Irp);Irp = NULL;}return ntStatus;
}

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

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

相关文章

从理论到实践的指南:企业如何建立有效的EHS管理体系?

企业如何建立有效的EHS管理体系?对于任何企业,没有安全就谈不上稳定生产和经济效益,因此建立EHS管理体系是解决企业长期追求的建立安全管理长效机制的最有效手段。良好的体系运转,可以最大限度地减少事故发生。 这篇借着开头这个…

年轻人「入侵」厂货电商:泼天的富贵or甜蜜的烦恼?

【潮汐商业评论/原创】 “明天我们带个黑色塑料袋,假装是批发拿货的,看看能不能淘到好货。这个批发‘黑话’你也学一下,别到时候露馅。” Paula正兴冲冲地跟Grace计划去服装批发市场“消费”。 只不过,与以往普通进店客人身份不…

ArcGIS中将测绘数据投影坐标(平面坐标)转地理坐标(球面经纬度坐标)

目录 前言1.测绘数据预览1.1 确定带号1.2 为什么是对Y轴分带,而不是对X轴分带? 2 测绘数据转shp2.1 添加数据2.2 显示XY数据2.3 添加经纬度字段2.4 计算经纬度 3.shp数据重投影4.总结 前言 最近在刚好在做一个小功能,将测绘数据转为经纬度坐标…

人脸特征68点识别 C++

1、加载一张图片 main函数&#xff1a; cv::Mat img cv::imread("5.jpg");vector<Point2f> points_vec dectectFace68(img);2、人脸68特征识别函数 在这里vector<Point2f> dectectFace68(Mat src) {vector<Point2f> points_vec;int* pResults …

TIA博途WinCC通过VB脚本从 Excel中读取数据的具体方法介绍

TIA博途WinCC通过VB脚本从 Excel中读取数据的具体方法介绍 添加 一个PLC,设置PLC的IP地址,如下图所示, 添加全局DB块,新建几个变量,如下图所示, 在数据块中添加了 tag1 …… tag6 ,共 6 个浮点数类型的变量,用来接收通过 WinCC 从 Excel 文件中读取的数据。 添加 HMI…

量取无忧 —— PP容量瓶,实验室的透明选择

PP容量瓶&#xff0c;即聚丙烯&#xff08;Polypropylene&#xff0c;简称PP&#xff09;材质的容量瓶&#xff0c;是一种实验室常用的量器&#xff0c;用于准确量取一定体积的液体。以下是PP容量瓶的一些主要特性和应用&#xff1a; 主要特性&#xff1a; 1. 耐化学性&#x…

甄选版“论软件系统架构评估”,软考高级论文,系统架构设计师论文

论文真题 对于软件系统,尤其是大规模的复杂软件系统来说,软件的系统架构对于确保最终系统的质量具有十分重要的意义,不恰当的系统架构将给项目开发带来高昂的代价和难以避免的灾难。对一个系统架构进行评估,是为了:分析现有架构存在的潜在风险,检验设计中提出的质量需求,…

5G(NR) NTN 卫星组网架构

5G(NR) NTN 卫星组网架构 参考 3GPP TR 38.821 5G NTN 技术适用于高轨、低轨等多种星座部署场景&#xff0c;是实现星地网络融合发展的可行技术路线。5G NTN 网络分为用户段、空间段和地面段三部分。其中用户段由各种用户终端组成&#xff0c;包括手持、便携站、嵌入式终端、车…

JAVA-Redis数据结构—跳跃表(Skiplist)【包含Java实现详情代码】

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

PostgreSQL开发

在 PostgreSQL 中&#xff0c;你可以在表中创建数组类型的列 CREATE TABLE articles ( id SERIAL PRIMARY KEY, title VARCHAR(200), content TEXT, tags TEXT[], data JSONB ); 在上面的例子中&#xff0c;tags 列是一个文本数组&#xff0c;可以存储多个标签。 data 列是一…

探索IT世界的第一步:高考后的暑期学习指南

目录 前言1. IT领域概述1.1 IT领域的发展与现状1.2 IT领域的主要分支1.2.1 软件开发1.2.2 数据科学1.2.3 网络与安全1.2.4 系统与运维 2. 学习路线图2.1 基础知识的学习2.1.1 编程语言2.1.2 数据结构与算法 2.2 实战项目的实践2.2.1 个人项目2.2.2 团队项目 2.3 学习资源的利用…

前端技术栈学习:Vue2、Vue cli脚手架、ElementUI组件库、Axios

1 基本介绍 &#xff08;1&#xff09;Vue 是一个前端框架, 易于构建用户界面 &#xff08;2&#xff09;Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;还便于与第三方库或项目整合 &#xff08;3&#xff09;支持和其它类库结合使用 &#xff08;4&#…

2024最新源代码加密软件丨五款企业级软件评测

程序源代码作为企业的核心成果&#xff0c;一旦泄密将产生重大的损失&#xff0c;加密源代码至关重要。 可以防止他人未经授权使用、复制或修改源代码&#xff0c;保护开发者的劳动成果。 可以防止源代码被黑客或竞争对手获取和分析&#xff0c;减少漏洞被发现和利用的风险。…

网络基础-RIP协议

RIP&#xff08;Routing Information Protocol&#xff09;是一个基于距离矢量的动态路由协议&#xff0c;常用于小型到中型网络。RIP是较早的路由协议之一&#xff0c;具有简单易用的特点。以下是关于RIP协议的详细介绍&#xff1a; RIP的主要特点 ①使用跳数&#xff08;ho…

git基本使用(一):git的基本概念

Git 是一种分布式版本控制系统&#xff0c;最初由 Linus Torvalds 于 2005 年为 Linux 内核开发。它主要用于跟踪文件的更改&#xff0c;特别是在软件开发过程中&#xff0c;可以帮助团队成员协同工作。它在实际项目开发中&#xff0c;应用非常广泛&#xff0c;我们这一节来掌握…

C++ STL unique_ptr智能指针源码剖析

由于上一篇博客将shared_ptr,weak_ptr,enable_shared_form_this的源码实现整理了一遍,想着cpp智能指针还差个unique_ptr故写下此篇博客,以供学习 源码剖析 一,模板参数 首先,我们先看unique_ptr的模板参数,第一个参数_TP自是不用说表示对象类型,第二个模板参数定义了unique_p…

高电压技术-冲击高压发生器MATLAB仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 冲击电压发生器是产生冲击电压波的装置&#xff0c;用于检验电力设备耐受大气过电压和操作过电压的绝缘性能&#xff0c;冲击电压发生器能产生标准雷电冲击电压波形&#xff0c;雷电冲击电压截波,标准操作冲击…

优盘“盘符显示0字节”深度解析与全方位恢复指南

一、现象揭秘&#xff1a;优盘盘符下的“数字黑洞” 在数字化生活的洪流中&#xff0c;优盘作为便携存储的佼佼者&#xff0c;承载着无数人的重要数据与记忆。然而&#xff0c;当您满怀期待地将优盘插入电脑&#xff0c;却愕然发现其盘符下赫然标注着“0字节”&#xff0c;这份…

【Kali-linux for WSL】图形化界面安装

文章目录 前言图形化界面安装 前言 之前在WSL中安装了Kali 启动之后发现什么都没有&#xff01;&#xff01;&#xff01; 那我还怎么学习渗透技术&#xff1f;&#xff1f;&#xff1f; 看来&#xff0c;得改进下我的kali-linux for wsl&#xff0c;安装个图形化界面 图形化…

leetcode-19-回溯-组合问题(剪枝、去重)

引自代码随想录 一、[77]组合 给定两个整数 n 和 k&#xff0c;返回 1 ... n 中所有可能的 k 个数的组合。 示例: 输入: n 4, k 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4]] 1、大致逻辑 k为树的深度&#xff0c;到叶子节点的路径即为一个结果 开始索引保证不…