【TaskBasics】- KRTS C++示例精讲(3)

news2024/12/29 4:40:25

TaskBasics示例讲解


目录

    • TaskBasics示例讲解
      • 结构说明


项目打开请查看【BaseFunction精讲】。

结构说明

在这里插入图片描述

  • TaskBasics:应用层程序,主要用于人机交互、数据显示、内核层数据交互等;

    1. TaskBasics.h : 数据定义
    2. TaskBasics.cpp:用户应用层源码
  • TaskBasics_64: 内核层程序(实时层程序),主要用于实时数据处理;

    1. TaskBasics.h : 数据定义
    2. TaskBasics_dll.cpp : 内核层源码
  • 其余文件说明请查看【BaseFunction精讲】中的结构说明。
    ps : 内核层中的数据、结构体需要一字节对齐,需要以MT方式构建
    在这里插入图片描述

TaskBasics.h : 应用层与内核层共用一个头文件

/* Copyright (c) 2007-2024 by Kithara Software GmbH. All rights reserved. */

//##############################################################################################################
//
// 文件:         TaskBasics.h
//
// 模块: Task 模块
//
// 描述: 用户应用程序和内核 DLL 之间共享定义的示例,展示如何使用任务模块调度实时任务。
//
// 创建人:      r.gro 2007-11-26
//
//##############################################################################################################

   /*=====================================================================*\
   |                    *** 免责声明 ***                     			   |
   |                                                                       |
   |       本代码仅是示例程序,您可以随意使用,我们不承担任何法律责任!		   |
   |																	   |
   \*=====================================================================*/

//##############################################################################################################
//
// 目的:
//
// 此示例展示了任务模块的基本功能。
// 我们创建了三个具有不同优先级的任务,它们相互恢复和挂起。
// 每个任务都会将字符放入数据管道。
// 最后显示数据管道的内容,以展示单个任务的执行顺序。
//
//##############################################################################################################


#ifndef __SMP_TASKBASICS_H
#define __SMP_TASKBASICS_H

#include "../_KitharaSmp/_KitharaSmp.h"


//--------------------------------------------------------------------------------------------------------------
// SharedData 是一个用户定义的参数结构,用于在内核 DLL 和用户应用程序之间使用共享内存进行信息交换。
// 您可以自由定义任何与系统位大小无关的参数。
//--------------------------------------------------------------------------------------------------------------

struct SharedData {
  KSHandle hKernel;                                     // 内核操作句柄
  KSHandle hTaskA;                                      // 任务 A
  KSHandle hTaskB;                                      // 任务 B
  KSHandle hTaskC;                                      // 任务 C
  KSHandle hCallbackA;                                  // 任务 A 回调
  KSHandle hCallbackB;                                  // 任务 B 回调
  KSHandle hCallbackC;                                  // 任务 C 回调
  KSHandle hPipe;                                       // 数据传输的管道
};

#endif // __SMP_TASKBASICS_H

TaskBasics.cpp

/* Copyright (c) 2007-2024 by Kithara Software GmbH. All rights reserved. */

//##############################################################################################################
//
// 文件:         TaskBasics.cpp
//
// 模块: Task 模块
//
// 描述: 用户应用程序和内核 DLL 之间共享定义的示例,展示如何使用任务模块调度实时任务。
//
// 创建人:      r.gro 2007-11-26
//
//##############################################################################################################

   /*=====================================================================*\
   |                    *** 免责声明 ***                     			   |
   |                                                                       |
   |       本代码仅是示例程序,您可以随意使用,我们不承担任何法律责任!		   |
   |																	   |
   \*=====================================================================*/

//##############################################################################################################
//
// 目的:
//
// 此示例展示了任务模块的基本功能。
// 我们创建了三个具有不同优先级的任务,它们相互恢复和挂起。
// 每个任务都会将字符放入数据管道。
// 最后显示数据管道的内容,以展示单个任务的执行顺序。
//
//##############################################################################################################


//--------------------------------------------------------------------------------------------------------------
// 为了在主程序(用户层)和内核 DLL 之间共享数据结构的定义,我们使用了一个通用的头文件。
//--------------------------------------------------------------------------------------------------------------

#include "TaskBasics.h"

//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// 别忘了输入你的序列号(6位客户编号),这是打开驱动程序所必需的。
// 
// 如果你使用Demo版本,也可以使用“DEMO”代替。
// 如果你使用Beta版本,也可以使用“BETA”代替。
//
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

// 如上说所,定义的客户号 
const char _pCustomerNumber[] = "DEMO";


// 主程序入口
void runSample() {
  outputTxt("***** Kithara example program 'TaskBasics' *****");

  // 错误码定义,KSError 是 Kithara API 所有函数的返回类型,通过 【KSError】 可以查询接口的返回错误信息。
  KSError ksError;

  //------------------------------------------------------------------------------------------------------------
  // 打开驱动程序的第一步,所有KRTS程序必须进行的操作。
  // 只要该函数调用成功后,我们可以使用其他函数。如果打开失败,则无法调用其他函数。
  // 此函数接受您的客户编号作为参数,其中包含 Kithara(如果适用可以为“DEMO”或“BETA”)。
  //------------------------------------------------------------------------------------------------------------
  
  ksError = KS_openDriver(
              _pCustomerNumber);                        // 客户序列号
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_openDriver", "Unable to open the driver!");
    return;
  }

  //------------------------------------------------------------------------------------------------------------
  // 创建共享内存
  // 为实时层中的DLL和此用户层应用程序之间的通信。
  //------------------------------------------------------------------------------------------------------------

  KSHandle hSharedMemory;
  ksError = KS_createSharedMemEx(
              &hSharedMemory,                           // 返回创建的共享内存句柄
              "",                                       // 共享内存的名称
              sizeof(SharedData),                       // 共享内存的大小
              KSF_NO_FLAGS);                            // 无标记,此选项可以进行一些特殊设定
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_createSharedMemEx", "Unable to create shared memory!");
    KS_closeDriver();
    return;
  }


  // 要访问共享内存,应用程序需要使用刚创建的共享内存的句柄来获取指向分配的共享内存的指针。
  SharedData* pApp = NULL;								// 自定义的共享内存结构体
  ksError = KS_getSharedMemEx(
              hSharedMemory,                            // 共享内存的句柄
              (void**)&pApp,                            // 指向共享内存的结构的指针
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_getSharedMemEx", "Unable to map shared memory!");
    KS_closeDriver();
    return;
  }

  // 确定操作系统的位数大小以决定是加载32位还是64位内核DLL。
  KSSystemInformation systemInfo;                       // 获取系统信息的结构体
  systemInfo.structSize = sizeof(KSSystemInformation);  // 不要忘记设备结构体大小
  ksError = KS_getSystemInformation(
              &systemInfo,                              // 结构体指针用于获取结构体数据
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_getSystemInformation", "Unable to get system information to distinguish bitsize!");
    KS_closeDriver();
    return;
  }


  //------------------------------------------------------------------------------------------------------------
  // 想要在内核级别上使用DLL中的函数,必须加载dll,在调用里面的函数!
  // 注意!加载程序必须找到DLL,因此它应该放在搜索路径的目录中!
  // 因为我们想要在共享内存中传递加载的内核的句柄,所以我们不使用加载内核时的初始化函数,
  // 而是在填充内核句柄和初始化内核所需的所有信息之后,显式调用初始化函数。
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_loadKernel(
              &pApp->hKernel,                           // 返回内核操作句柄
              systemInfo.isSys64Bit ?                   // 根据系统位数加载内核Dll
                "TaskBasics_64.dll" :                  
                "TaskBasics_32.dll",                    
              NULL,                                     // 需要支持的函数名称(未使用)
              NULL,                                     // 函数参数 (未使用)
              KSF_KERNEL_EXEC);                         // 内核空间中加载(实时层运行)
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_loadKernel", "Unable to load DLL! Is the DLL in the search path?");
    KS_closeDriver();
    return;
  }

  //------------------------------------------------------------------------------------------------------------
  // 显式调用初始化函数。
  // 调用内核的【_initFunction】函数,并传递共享内存的句柄,这样内核就可以从句柄中检索到共享内存的指针,
  // 并根据共享内存中存储的信息进行所有必要的资源分配。
  // 更为详细的内核初始化操作可以查看内核层【_initFunction】函数
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_execKernelFunctionEx(
              pApp->hKernel,                            // 内核句柄
              "_initFunction",                          // 函数名称
              hSharedMemory,                            // 共享内存的句柄
              KS_INVALID_HANDLE,                        // 上下文
              KSF_NO_FLAGS);                            // 未使用
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_execKernelFunctionEx", "Unable to initialize the kernel DLL!");
    KS_closeDriver();
    return;
  }

  // 等待内核层初始化完成
  waitTime(1 * s);
  outputTxt(" ");
  outputTxt("The tasks completed their work.");

  char pBuf[10];                                        // 管道中的9个字符 + 终止字符的1个
  int length;

  // 获取管道中的数据
  ksError = KS_getPipe(
              pApp->hPipe,                              // 管道句柄
              pBuf,                                     // 缓冲区,用于将管道数据写入
              9,                                        // 从管道获取的数据大小
              &length,                                  // 写入接收到的数据长度
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_getPipe", "Unable to read data from the pipe!");
    KS_closeDriver();
    return;
  }

  pBuf[length] = '\0';                                  // 分隔字符串,以供输出

  outputTxt("Expected output : ABBBCBBAC");
  outputTxt("Actual output   : ", false);
  outputTxt(pBuf);
  outputTxt(" ");


  //------------------------------------------------------------------------------------------------------------
  // 清理内核DLL中分配的资源。
  //------------------------------------------------------------------------------------------------------------
  ksError = KS_execKernelFunctionEx(
              pApp->hKernel,                            // 内核句柄
              "_exitFunction",                          // 内核层退出函数
              KS_INVALID_HANDLE,                        // 传参
              KS_INVALID_HANDLE,                        // 上下文
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_execKernelFunctionEx", "Error while deallocating resources on kernel level!");
    KS_closeDriver();
    return;
  }


  //------------------------------------------------------------------------------------------------------------
  // 使用共享句柄卸载内核DLL。
  // 尽管KS_closeDriver()释放了所有分配的资源(如共享内存和加载的内核),
  // 明确释放您分配的资源是很好的习惯。
  //------------------------------------------------------------------------------------------------------------
  
  // 释放内核
  ksError = KS_freeKernel(
              pApp->hKernel);                           // 内核句柄
  if (ksError != KS_OK)
    outputErr(ksError, "KS_freeKernel", "Unable to unload the kernel!");


  // 清理共享内存
  ksError = KS_freeSharedMemEx(
              hSharedMemory,                            // 共享内存句柄
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK)
    outputErr(ksError, "KS_freeSharedMemEx", "Unable to remove shared memory!");

  // 关闭设备清理所有资源
  ksError = KS_closeDriver();
  if (ksError != KS_OK)
    outputErr(ksError, "KS_closeDriver", "Unable to close the driver!");

  waitTime(500 * ms);
  outputTxt(" ");
  outputTxt("End of program 'TaskBasics'.");
}

TaskBasics_dll.cpp

/* Copyright (c) 2007-2024 by Kithara Software GmbH. All rights reserved. */

//##############################################################################################################
//
// 文件:         TaskBasics_dll.cpp
//
// 模块: Task 模块
//
// 描述: 用户应用程序和内核 DLL 之间共享定义的示例,展示如何使用任务模块调度实时任务。
//
// 创建人:      r.gro 2007-11-26
//
//##############################################################################################################

   /*=====================================================================*\
   |                    *** 免责声明 ***                     			   |
   |                                                                       |
   |       本代码仅是示例程序,您可以随意使用,我们不承担任何法律责任!		   |
   |																	   |
   \*=====================================================================*/

//##############################################################################################################
//
// 目的:
//
// 此示例展示了任务模块的基本功能。
// 我们创建了三个具有不同优先级的任务,它们相互恢复和挂起。
// 每个任务都会将字符放入数据管道。
// 最后显示数据管道的内容,以展示单个任务的执行顺序。
//
//##############################################################################################################


//--------------------------------------------------------------------------------------------------------------
// 为了在主程序(用户层)和内核 DLL 之间共享数据结构的定义,我们使用了一个通用的头文件。
//--------------------------------------------------------------------------------------------------------------

#include "TaskBasics.h"


// 共享内存用于在内核层 DLL 和用户层的应用程序之间共享数据。
SharedData* _pSys = NULL;

// 前置声明,在此文件末尾定义的不同任务的3个回调函数。
KSError __stdcall callBackA(void* /*pArgs*/, void* /*pContext*/);
KSError __stdcall callBackB(void* /*pArgs*/, void* /*pContext*/);
KSError __stdcall callBackC(void* /*pArgs*/, void* /*pContext*/);



//--------------------------------------------------------------------------------------------------------------
// 这是初始化函数。
// 它在加载内核后被调用,并将共享内存的句柄作为参数传递。
//
// 注意!请记住,所有函数都应声明为 'extern "C"'!
// 否则它们的名字可能无法被加载器找到。
// 必须通过 '__declspec(dllexport)' 导出它们。
//--------------------------------------------------------------------------------------------------------------

extern "C" KSError __declspec(dllexport) __stdcall _initFunction(void* pArgs, void* /*pContext*/) {
  KSError ksError;


  // 共享内存的指针通过 KS_execKernelFunctionEx() 作为 'pArgs' 参数传递。
  _pSys = (SharedData*)pArgs;

  // 创建管道,为了从内核级别向用户级别传输数据。
  ksError = KS_createPipe(
              &_pSys->hPipe,                            // 返回一个管道操作句柄
              "MyTaskBasicsPipe",                       // 名称
              sizeof(char),                             // 单个数据大小,此处字符大小
              9,                                        // 数据个数
              KS_INVALID_HANDLE,                        // 对象信号(此处未使用)
              KSF_NO_FLAGS);                            // 无标记
  if (ksError != KS_OK)
    return ksError;


  //------------------------------------------------------------------------------------------------------------
  // 现在,我们为3个任务创建3个回调函数。
  // 回调函数使用标志KSF_DIRECT_EXEC创建,以便在内核级别执行。
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_createCallBack(
              &_pSys->hCallbackA,                       // 返回一个回调操作句柄
              callBackA,                                // 回调函数
              NULL,                                     // 参考参数到回调(未使用)
              KSF_DIRECT_EXEC,                          // 在内核中执行
              0);                                       // 优先级(仅用于用户空间)
  if (ksError != KS_OK)
    return ksError;

  ksError = KS_createCallBack(
              &_pSys->hCallbackB,                       // 返回一个回调操作句柄
              callBackB,                                // 回调函数
              NULL,                                     // 参考参数到回调(未使用)
              KSF_DIRECT_EXEC,                          // 在内核中执行
              0);                                       // 优先级(仅用于用户空间)
  if (ksError != KS_OK)
    return ksError;

  ksError = KS_createCallBack(
              &_pSys->hCallbackC,                       // 返回一个回调操作句柄
              callBackC,                                // 回调函数
              NULL,                                     // 参考参数到回调(未使用)
              KSF_DIRECT_EXEC,                          // 在内核中执行
              0);                                       // 优先级(仅用于用户空间)
  if (ksError != KS_OK)
    return ksError;


  //------------------------------------------------------------------------------------------------------------
  // 创建3个任务
  // 这些任务创建时带有KSF_DONT_START标志,因此它们只有在被明确触发后才会开始执行。
  //------------------------------------------------------------------------------------------------------------


  //------------------------------------------------------------------------------------------------------------
  // 创建优先级为200的任务A。
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_createTask(
              &_pSys->hTaskA,                           // 返回任务操作句柄
              _pSys->hCallbackA,                        // 回调句柄
              200,                                      // 优先级
              KSF_DONT_START);                          // 不立即执行
  if (ksError != KS_OK)
    return ksError;


  //------------------------------------------------------------------------------------------------------------
  // 创建优先级为250的任务B。
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_createTask(
              &_pSys->hTaskB,                           // 返回任务操作句柄
              _pSys->hCallbackB,                        // 回调句柄
              250,                                      // 优先级
              KSF_DONT_START);                          // 不立即执行
  if (ksError != KS_OK)
    return ksError;


  //------------------------------------------------------------------------------------------------------------
  // 创建优先级为150的任务C。
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_createTask(
              &_pSys->hTaskC,                           // 返回任务操作句柄
              _pSys->hCallbackC,                        // 回调句柄
              150,                                      // 优先级
              KSF_DONT_START);                          // 不立即执行
  if (ksError != KS_OK)
    return ksError;


  //------------------------------------------------------------------------------------------------------------
  // 触发任务A,进而触发其他任务。
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_triggerTask(
              _pSys->hTaskA);                           // 任务 A 句柄
  if (ksError != KS_OK)
    return ksError;

  return KS_OK;
}


//--------------------------------------------------------------------------------------------------------------
// 这是清理函数,用于删除3个任务、3个回调和数据管道。
//--------------------------------------------------------------------------------------------------------------

extern "C" KSError __declspec(dllexport) __stdcall _exitFunction(void* /*pArgs*/, void* /*pContext*/) {
  if (_pSys == NULL)                                    // 共享内存未映射!
    return KSERROR_FUNCTION_NOT_AVAILABLE;              // _initFunction未被调用?

  KSError ksError;

  // 删除任务。
  ksError = KS_removeTask(
              _pSys->hTaskA);                           // 任务 A
  if (ksError != KS_OK)
    return ksError;

  ksError = KS_removeTask(
              _pSys->hTaskB);                           // 任务 B
  if (ksError != KS_OK)
    return ksError;

  ksError = KS_removeTask(
              _pSys->hTaskC);                           // 任务 C
  if (ksError != KS_OK)
    return ksError;


  // 移除回调
  ksError = KS_removeCallBack(
              _pSys->hCallbackA);                       // 任务回调 A
  if (ksError != KS_OK)
    return ksError;

  ksError = KS_removeCallBack(
              _pSys->hCallbackB);                       // 任务回调 B
  if (ksError != KS_OK)
    return ksError;

  ksError = KS_removeCallBack(
              _pSys->hCallbackC);                       // 任务回调 C
  if (ksError != KS_OK)
    return ksError;


  //------------------------------------------------------------------------------------------------------------
  // 移除数据管道
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_removePipe(
              _pSys->hPipe);                            // 管道句柄
  if (ksError != KS_OK)
    return ksError;

  return KS_OK;
}


// callBackA 是任务 A 执行的回调,它在创建后不会启动,运行优先级为 200。
KSError __stdcall callBackA(void* /*pArgs*/, void* /*pContext*/) {

  const char chr = 'A';
  // 向管道中填充数据
  KS_putPipe(
    _pSys->hPipe,                                       // 管道句柄
    &chr,                                               // 要放入管道中的数据包地址
    1,                                                  // 一项
    NULL,                                               // 传输的字节数(未使用)
    KSF_NO_FLAGS);                                      // 无标记

  KS_triggerTask(                                       // 触发执行任务 B
    _pSys->hTaskB);                                    

  KS_putPipe(_pSys->hPipe, &chr, 1, NULL, 0);

  return KS_OK;
}


// callBackB 是任务 B 执行的回调,它在创建后不会启动,运行优先级为 250。
KSError __stdcall callBackB(void* /*pArgs*/, void* /*pContext*/) {

  const char chr = 'B';

  KS_putPipe(_pSys->hPipe, &chr, 1, NULL, 0);

  KS_triggerTask(                                       // 触发执行任务 C
    _pSys->hTaskC);                                     

  KS_putPipe(_pSys->hPipe, &chr, 1, NULL, 0);

  KS_suspendTask(                                       // 暂停任务 A
    _pSys->hTaskA);                                    

  KS_putPipe(_pSys->hPipe, &chr, 1, NULL, 0);

  KS_suspendTask(                                       //  暂停任务 B
    KS_INVALID_HANDLE);                                 // 当前任务的处理手柄,KS_INVALID_HANDLE

  KS_putPipe(_pSys->hPipe, &chr, 1, NULL, 0);

  KS_resumeTask(                                        // 继续任务 A
    _pSys->hTaskA);                                     

  KS_putPipe(_pSys->hPipe, &chr, 1, NULL, 0);

  return KS_OK;
}


// callBackC 是任务 C 执行的回调,它在创建后不会启动,运行优先级为 150。
KSError __stdcall callBackC(void* /*pArgs*/, void* /*pContext*/) {

  const char chr = 'C';

  KS_putPipe(_pSys->hPipe, &chr, 1, NULL, 0);

  KS_resumeTask(                                        // 继续任务 B
    _pSys->hTaskB);                                   

  KS_putPipe(_pSys->hPipe, &chr, 1, NULL, 0);

  return KS_OK;
}


//--------------------------------------------------------------------------------------------------------------
// 需要实现 DllMain 函数,该函数在 DLL 加载时不会被执行。
//
// 对于初始化,请定义一个特殊的 init 函数,并在调用 KS_loadKernel()时将其名称作为参数传递给它,
// 或者在加载内核的句柄以后在加载的 DLL 调用函数(如本例所示)时使用,
// 请不要在加载内核时执行的 init 函数,而是在加载内核后自己明确地调用它,并根据需要传递参数,如本例所示。
//--------------------------------------------------------------------------------------------------------------

#define WIN32_LEAN_AND_MEAN
#pragma pack(push, 8)
#include <windows.h>
#pragma pack(pop)

BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD reason, LPVOID pReserved) {
  return TRUE;
}

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

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

相关文章

jenkins集成工具(一)部署php项目

目录 什么是CI 、CD Jenkins集成工具 一、Jenkins介绍 二、jenkins的安装和部署 环境部署 安装jenkins 安装gitlab 配置镜像源进行安装 修改密码 安装git工具 上传测试代码 Jenkins部署php项目wordpress 发布php代码 安装插件 测试代码发布 实现发布成功发送邮件…

在交叉编译中,常见的ELF(elf)到底是什么意思?

ELF 是 Executable and Linkable Format 的缩写&#xff0c;中文翻译为“可执行与可链接格式”。它是一种通用的文件格式&#xff0c;主要用于存储可执行文件、目标文件&#xff08;编译后的中间文件&#xff09;、动态库&#xff08;.so 文件&#xff09;以及内存转储文件&…

图神经网络_图嵌入_Struc2Vec

0 背景 之前的node embedding方式&#xff0c;都是基于近邻关系&#xff0c;但是有些节点没有近邻&#xff0c;也有结构相似性。如图中的u、v节点。 struc2vec算法适用于捕获结构相似性。 1 相似度&#xff08;距离&#xff09;计算 1.1 公式 f k ( u , v ) f k − 1 ( u …

Linux内核中Typec CC检测原理及主从模式切换原理

一&#xff0c;Typec CC引脚定义 可以看到&#xff0c;数据传输主要有TX/RX两组差分信号&#xff0c;CC1和CC2是两个关键引脚&#xff0c;作用很多&#xff1a; • 探测连接&#xff0c;区分正反面&#xff0c;区分DFP和UFP&#xff0c;也就是主从 • 配置Vbus&#xff0c;有US…

uniapp通过v-if进行判断时,会出现闪屏?【已解决】

1.问题&#xff1a;按钮切换时&#xff0c;通过v-if来判断&#xff0c;会出现闪烁情况&#xff0c;影响用户体验 2.v-if 闪烁问题可能的原因 ‌条件切换频繁‌&#xff1a;如果 v-if 指令的条件在短时间内频繁切换&#xff0c;会导致元素不断被销毁和重新创建&#xff0c;从而…

webrtc获取IceCandidate流程

在WebRTC(Web Real-Time Communication)中,ICECandidate是一个关键概念,它用于描述在建立点对点(P2P)连接时可以考虑的潜在通信端点。以下是关于WebRTC中ICECandidate的详细解释: 一、ICECandidate的定义 ICECandidate对象通常包含以下关键属性: foundation:用于唯一…

计算机网络习题(第1章 概论 第2章 数据通信基础)

第1章 概论 1、计算机网络 2、互联网 3、计算机网络体系结构 分层模型 OSI/RM 7层模型 TCP/IP 5层模型 协议、PDU、SDU、SAP等术语 数据封装&#xff08;计算&#xff09; 第2章 数据通信基础 1、数据通信系统组成 2、主要性能指标 数据传输速率 码元速率 时延 3…

Springboot项目下面使用Vue3 + ElementPlus搭建侧边栏首页

Springboot项目下面、在html 页面 Vue3 ElementPlus 搭建侧边栏首页 1、效果图 2、static 文件下面的项目结构 3、代码实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>首页</title><…

【C++11】可变参数模版

目录 一、可变参数模版 1.1 基本语法及原理 1.2 包拓展 1.3 empalce系列接口 一、可变参数模版 之前我们在C语言中就学过可变参数&#xff0c;但是模版类型是固定的&#xff0c;怎么变呢&#xff1f;这里c11就给出了可变参数模版 1.1 基本语法及原理 C11支持可变参数模…

FFmpeg在python里推流被处理过的视频流

链式算法处理视频流 视频源是本地摄像头 # codinggbk # 本地摄像头直接推流到 RTMP 服务器 import cv2 import mediapipe as mp import subprocess as sp# 初始化 Mediapipe mp_drawing mp.solutions.drawing_utils mp_drawing_styles mp.solutions.drawing_styles mp_holis…

我的秋招总结

我的秋招总结 个人背景 双非本&#xff0c;985硕&#xff0c;科班 准备情况 以求职为目的学习Java的时间大概一年。 八股&#xff0c;一开始主要是看B站黑马的八股文课程&#xff0c;背JavaGuide和小林coding还有面试鸭。 算法&#xff0c;250&#xff0c;刷了3遍左右 项目&…

C++:单例模式

创建自己的对象&#xff0c;同时确保对象的唯一性。 单例类只能有一个实例☞静态成员static☞静态成员 必须类外初始化 单例类必须自己创建自己的唯一实例 单例类必须给所有其他对象提供这一实例 静态成员类内部可以访问 构造函数私有化☞构造函数私有外部不能创建&#x…

RBTree(红黑树)

目录 红黑树的概念 红黑树的性质 红黑树节点的定义 红黑树的插入 1. 按照二叉搜索的树规则插入新节点 2. 检测新节点插入后&#xff0c;红黑树的性质是否造到破坏 红黑树的检测 红黑树的删除 红黑树和AVL树的比较 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&…

linux自动化一键批量检查主机端口

1、准备 我们可以使用下面命令关闭一个端口 sudo iptables -A INPUT -p tcp --dport 端口号 -j DROP我关闭的是22端口&#xff0c;各位可以关其它的或者打开其它端口测试&#xff0c;谨慎关闭22端口&#xff01;不然就会像我下面一样握手超时&#x1f62d;&#x1f62d;&…

Python大数据可视化:基于python大数据的电脑硬件推荐系统_flask+Hadoop+spider

开发语言&#xff1a;Python框架&#xff1a;flaskPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 价格区间界面 用户信息界面 品牌管理 笔记本管理 电脑主机…

AEO海关认证的注意事项

AEO海关认证的注意事项繁多且至关重要&#xff0c;企业需细致准备&#xff0c;确保万无一失。 首先&#xff0c;企业需深入研读相关政策文件&#xff0c;如《中华人民共和国海关注册登记和备案企业信用管理办法》及《海关高级认证企业标准》&#xff0c;以政策为指引&#xff0…

MySQL如何只取根据某列连续重复行的第一条记录

前言 MySQL如何只取根据某列连续重复行的第一条记录&#xff0c;条件&#xff1a;某列、连续、验重 建表准备 DROP TABLE IF EXISTS test; CREATE TABLE test (id bigint NOT NULL,time datetime NULL DEFAULT NULL,price int NULL DEFAULT NULL,PRIMARY KEY (id) USING BT…

c++编译过程初识

编译过程 预处理&#xff1a;主要是执行一些预处理指令&#xff0c;主要是#开头的代码&#xff0c;如#include 的头文件、#define 定义的宏常量、#ifdef #ifndef #endif等条件编译的代码&#xff0c;具体包括查找头文件、进行宏替换、根据条件编译等操作。 g -E example.cpp -…

JS中的闭包和上下文

变量提升 和 函数提升 这里要提到一个提升的概念&#xff0c;即在JS中&#xff0c;在解析代码之前还有一个预处理的过程&#xff0c;这个过程中会把部分变量和函数声明提前到代码的最顶部&#xff0c; 会在其他所有代码之前执行。虽然当我们按照规范&#xff08;严格模式或者T…

GitLab 将停止为中国区用户提供服务,60天迁移期如何应对? | LeetTalk Daily

“LeetTalk Daily”&#xff0c;每日科技前沿&#xff0c;由LeetTools AI精心筛选&#xff0c;为您带来最新鲜、最具洞察力的科技新闻。 GitLab作为一个广受欢迎的开源代码托管平台&#xff0c;近期宣布将停止服务中国大陆、澳门和香港地区的用户提供服务。根据官方通知&#x…