STM32F1+HAL库+FreeTOTS学习14——数值信号量

news2024/9/29 14:59:11

STM32F1+HAL库+FreeTOTS学习13——数值信号量

  • 1. 数值信号量
  • 2. 相关API函数
    • 2.1 创建计数信号量
    • 2.2 获取信号量
    • 2.3 释放信号量
    • 2.4 删除信号量
    • 2.5 获取信号量的计数值
  • 3. 操作实验
    • 1. 实验内容
    • 2. 代码实现:
    • 运行结果

上一期我们学习了二值信号量 ,这一期学习计数信号量

1. 数值信号量

和二值信号量类似的,数值信号量也是队列的一种特殊情况。只不过二值信号量是队列长度为1的队列,而数值信号量则是队列长度大于0的队列(可以为1,但是这样的话就和二值信号量无异),数值信号量能够容纳多个资源,其资源最大数在创建时就已经确定,一般适用于一下两个场合:

  1. 事件计数

在这种场合下,每次事件发生后,在事件处理函数中释放计数信号量(资源数+1),其他等待事件发生的任务获取计数信号量(资源数-1),等待事件发生的任务就可以在成功获取到计数信号量之后执行相应的动作。在这种场合下,计数信号量的资源数一般在创建时设置为0。

  1. 资源管理

在这种场合下,计数信号量的资源数代表共享资源的可用数量,一个任务想要访问共享资源,就必须先获取这个共享资源的计数信号量,获取成功之后,才可以对这个共享资源进行操作,在使用完这个共享资源之后,也需要释放它,在这中场合下,计数信号量的资源数一般在创建时设置为其管理的资源最大数。

2. 相关API函数

计数信号量的使用过程:创建计数信号量->释放信号量-> 获取信号量 -> 删除信号量 ( 可选 ),下面我们围绕几个步骤介绍计数信号量的相关API函数
常用的二值信号量API函数如下表:

函数描述
xSemaphoreCreateCounting()使用动态方式创建数值信号量
xSemaphoreCreateCountingStatic()使用静态方式创建数值信号量
xSemaphoreTake()获取信号量
xSemaphoreTakeFromISR()在中断中获取信号量
xSemaphoreGive()释放信号量
xSemaphoreGiveFromISR()在中断中释放信号量
vSemaphoreDelete()删除信号量
uxSemaphoreGetCount()获取信号量的计数值

【注】:获取和释放信号量的函数和前面二值信号量的获取和释放是一模一样的。

2.1 创建计数信号量

  1. xSemaphoreCreateCounting()

此函数用于动态方式创建计数信号量,创建所需要的内存,有FreeRTOS自动分配,该函数实际上是一个宏定义,在semphr.h文件中有定义,具体的代码如下:

#define xSemaphoreCreateCounting( uxMaxCount, \
								 uxInitialCount ) \
 xQueueCreateCountingSemaphore( ( uxMaxCount ), \
								 ( uxInitialCount ))

可以看到xSemaphoreCreateCounting() 内部是调用了xQueueCreateCountingSemaphore() ,由于该函数不经常使用,我们这里不赘述。所以我们直接把xSemaphoreCreateCounting() 当作一个函数介绍(实际上是一个宏,我们当作函数来使用,FreeRTOS的官方文档也是这样的),下面是函数原型:

/**
 * @brief       xSemaphoreCreateCounting
 * @param       uxMaxCount:计数信号量的资源数最大值
 * @param       uxInitialCount:计数信号量创建时分配的资源数
 * @retval      返回值为NULL,表示创建失败,其他值表示为创建数值信号量的句柄
 */
SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount,
                                            UBaseType_t uxInitialCount);
  1. xSemaphoreCreateCountingStatic()

此函数用于静态方式创建数值信号量,创建二值信号量所需要的内存,需要用户手动分配,该函数实际上是一个宏定义,在semphr.h文件中有定义,具体的代码如下:

#define xSemaphoreCreateCountingStatic( uxMaxCount, \
										 uxInitialCount, \
										 pxSemaphoreBuffer) \
 xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), \
										 ( uxInitialCount ), \
										 ( pxSemaphoreBuffer ))

可以看到xSemaphoreCreateCountingStatic() 内部是调用了xQueueCreateCountingSemaphoreStatic() ,有用该函数不经常使用,我们这里不赘述。所以我们直接把xSemaphoreCreateCountingStatic() 当作一个函数介绍(实际上是一个宏,我们当作函数来使用,FreeRTOS的官方文档也是这样的),下面是函数原型:

/**
 * @brief       xSemaphoreCreateCountingStatic
 * @param       uxMaxCount:计数信号量的资源数最大值
 * @param       uxInitialCount:计数信号量创建时分配的资源数
 * @param       pxSemaphoreBuffer:指向StaticSemaphore_t 类型的指针,存放创建后的信号量结构体
 * @retval      返回值为NULL,表示创建失败,其他值表示为创建数值信号量的句柄
 */
SemaphoreHandle_t xSemaphoreCreateCountingStatic(
                                 UBaseType_t uxMaxCount,
                                 UBaseType_t uxInitialCount
                                 StaticSemaphore_t *pxSemaphoreBuffer );

2.2 获取信号量

  1. xSemaphoreTake()

此函数用于获取信号量,如果信号量处于没有资源的状态,那么可以选择将任务进入阻塞状态,如果成功获取到了信号量,那么信号的资源数减1,该函数实际上是一个宏定义,在semphr.h文件中有定义,具体的代码如下:

#define xSemaphoreTake( xSemaphore, \
						 xBlockTime) \
 xQueueSemaphoreTake( ( xSemaphore ), \
 					  ( xBlockTime ))

可以看到xSemaphoreTake() 内部是调用了xQueueSemaphoreTake() ,关于xQueueSemaphoreTake函数的定义和使用,我们这里不赘述。所以我们直接把xSemaphoreTake() 当作一个函数介绍(实际上是一个宏,我们当作函数来使用,FreeRTOS的官方文档也是这样的),下面是函数原型:

/**
 * @brief       xSemaphoreTake
 * @param       xSemaphore:需要获取信号量的句柄
 * @param       xTicksToWait:阻塞时间
 * @retval      返回值为pdTRUE,表示获取成功,如果返回值为pdFALSE,表示获取失败。
 */
 BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore,
                 TickType_t xTicksToWait );
  1. xSemaphoreTakeFromISR()

此函数用于在中断中获取信号量,该函数实际上是一个宏定义,在semphr.h文件中有定义,具体的代码如下:

#define xSemaphoreTakeFromISR( xSemaphore, \
							   pxHigherPriorityTaskWoken) \
 xQueueReceiveFromISR( ( QueueHandle_t ) \
 						( xSemaphore ), \
 					   	 NULL, \
 					   ( pxHigherPriorityTaskWoken ))

可以看到xSemaphoreTakeFromISR() 内部是调用了xQueueReceiveFromISR() ,关于xQueueReceiveFromISR函数的定义和使用,我们这里不赘述。所以我们直接把xSemaphoreTakeFromISR() 当作一个函数介绍(实际上是一个宏,我们当作函数来使用,FreeRTOS的官方文档也是这样的),下面是函数原型:

/**
 * @brief       xSemaphoreTakeFromISR
 * @param       xSemaphore:需要获取信号量的句柄
 * @param       pxHigherPriorityTaskWoken:获取信号量之后是否需要任务切换,需要切换则 *pxHigherPriorityTaskWoken = pdTRUE
 * @retval      返回值为pdTRUE,表示获取成功,如果返回值为pdFALSE,表示获取失败。
 */
BaseType_t xSemaphoreTakeFromISR ( SemaphoreHandle_t xSemaphore, signed BaseType_t *pxHigherPriorityTaskWoken );

需要注意的是:

  • xSemaphoreTake()可以用来获取二值信号量、计数信号量、互斥信号量。
  • xSemaphoreTakeFromISR() 只能用来获取二值信号量和计数信号量,不能用于互斥信号量。

2.3 释放信号量

  1. xSemaphoreGive()

此函数用于释放信号量,如果信号量处于资源满的状态,那么可以选择将任务进入阻塞状态,如果成功释放了信号量,那么信号的资源数加1,该函数实际上是一个宏定义,在semphr.h文件中有定义,具体的代码如下:

#define xSemaphoreGive( xSemaphore) \
 xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), \
					 NULL, \
 					 semGIVE_BLOCK_TIME, \
					 queueSEND_TO_BACK)

可以看到xSemaphoreGive() 内部是调用了xQueueGenericSend() ,该函数在 STM32F1+HAL库+FreeTOTS学习12——队列 中有介绍,我们这里不赘述。所以我们直接把xSemaphoreGive() 当作一个函数介绍(实际上是一个宏,我们当作函数来使用,FreeRTOS的官方文档也是这样的),下面是函数原型:

/**
 * @brief       xSemaphoreGive
 * @param       xSemaphore:需要释放信号量的句柄
 * @retval      返回值为pdTRUE,表示释放成功,如果返回值为pdFALSE,表示释放失败。
 */
 BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );
  1. xSemaphoreGiveFromISR()

此函数用于在中断中释放信号量,该函数实际上是一个宏定义,在semphr.h文件中有定义,具体的代码如下:

#define xSemaphoreGiveFromISR( xSemaphore, \
							   pxHigherPriorityTaskWoken) \
		 xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), \
							 ( pxHigherPriorityTaskWoken ))

可以看到xSemaphoreGiveFromISR() 内部是调用了xQueueGiveFromISR() ,关于xQueueGiveFromISR函数的定义和使用,我们这里不赘述。所以我们直接把xSemaphoreGiveFromISR() 当作一个函数介绍(实际上是一个宏,我们当作函数来使用,FreeRTOS的官方文档也是这样的),下面是函数原型:

/**
 * @brief       xSemaphoreGiveFromISR
 * @param       xSemaphore:需要释放信号量的句柄
 * @param       pxHigherPriorityTaskWoken:释放信号量之后是否需要任务切换,需要切换则 *pxHigherPriorityTaskWoken = pdTRUE
 * @retval      返回值为pdTRUE,表示释放成功,如果返回值为pdFALSE,表示释放失败。
 */
BaseType_t xSemaphoreGiveFromISR ( SemaphoreHandle_t xSemaphore, signed BaseType_t *pxHigherPriorityTaskWoken )

需要注意的是:

  • xSemaphoreGive()可以用来释放二值信号量、计数信号量、互斥信号量。
  • xSemaphoreGiveFromISR () 只能用来释放二值信号量和计数信号量,不能用于互斥信号量。因为互斥信号量会有优先级继承的处理,而中断不属于任务,没有办法进行优先级继承。

2.4 删除信号量

  1. vSemaphoreDelete()
    此函数用于删除已创建的信号量。该函数实际上是一个宏定义,在 semphr.h 文件中有定义,具体的代码如下所示
#define vSemaphoreDelete(xSemaphore) \
 		vQueueDelete ( QueueHandle_t ) \
					 ( xSemaphore ))

可以看到vSemaphoreDelete() 内部是调用了vQueueDelete () ,关于vQueueDelete 函数的定义和使用,我们这里不赘述。所以我们直接把vSemaphoreDelete() 当作一个函数介绍(实际上是一个宏,我们当作函数来使用,FreeRTOS的官方文档也是这样的),下面是函数原型:

/**
 * @brief       vSemaphoreDelete
 * @param       xSemaphore :需要删除信号量的句柄
 * @retval      无
 */
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );

2.5 获取信号量的计数值

  1. uxSemaphoreGetCount()
    此函数用于获取信号量的计数值。该函数实际上是一个宏定义,在 semphr.h 文件中有定义,具体的代码如下所示
#define uxSemaphoreGetCount( xSemaphore )                uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) )

可以看到uxSemaphoreGetCount() 内部是调用了uxQueueMessagesWaiting() ,关于uxQueueMessagesWaiting函数的定义和使用,我们这里不赘述。所以我们直接把uxSemaphoreGetCount() 当作一个函数介绍(实际上是一个宏,我们当作函数来使用,FreeRTOS的官方文档也是这样的),下面是函数原型:

/**
 * @brief       uxSemaphoreGetCount
 * @param       xSemaphore :需要查询的信号量句柄
 * @retval      计数信号量返回当前的计数值,二值信号量返回0表示信号量可以,返回1表示不可用
 */
UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );

3. 操作实验

1. 实验内容

在STM32F103RCT6上运行FreeRTOS,通过按键控制,完成对应的数值信号量操作,具体要求如下:

  • 定义一个数值信号量,资源数最大为100,初始为0
  • 定义任务1:每次按下按键0,释放数值信号量
  • 定义任务2:每1s获取1次数值信号量

2. 代码实现:

  • 由于本期内容涉及到按键扫描,会用到: STM32框架之按键扫描新思路 ,这里不做过多介绍。我们直接来看代码:
  1. freertos_demo.c


#include "freertos_demo.h"
#include "main.h"
#include "queue.h" 		//需要包含队列和任务相关的头文件
#include "task.h"
#include "key.h"		//包含按键相关头文件

/*FreeRTOS*********************************************************************************************/

/******************************************************************************************************/
/*FreeRTOS配置*/



/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 
 */
#define TASK1_PRIO      1                  /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);					/*任务函数*/

/* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 
 */
#define TASK2_PRIO      2                  /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
void task2(void *pvParameters);					/*任务函数*/

SemaphoreHandle_t SemaphoreCount;				/* 定义数值信号量 */
 
/******************************************************************************************************/

/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{
	
	taskENTER_CRITICAL();           /* 进入临界区,关闭中断,此时停止任务调度*/

	SemaphoreCount = xSemaphoreCreateCounting(100,0);
	if(SemaphoreCount == NULL)
	{
		printf("数值信号量创建失败\r\n");
	}
	else
	{
		printf("数值信号量创建成功\r\n");
	}
	
	
    /* 创建任务1 */
    xTaskCreate((TaskFunction_t )task1,
                (const char*    )"task1",
                (uint16_t       )TASK1_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK1_PRIO,
                (TaskHandle_t*  )&Task1Task_Handler);
    /* 创建任务2 */
    xTaskCreate((TaskFunction_t )task2,
                (const char*    )"task2",
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler);

    taskEXIT_CRITICAL();            /* 退出临界区,重新开启中断,开启任务调度 */
    vTaskStartScheduler();		//开启任务调度
}

/**
* @brief       task1:用于按键扫描,检测按键0按下时,释放计数型信号量(资源数+1)
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void task1(void *pvParameters)
{
    
    while(1)
    {
		Key_One_Scan(Key_Name_Key0,Key0_Up_Task,Key0_Down_Task);		/* 按键0扫描,按下后释放数值信号量 */

       
    }
}	
/**
* @brief       task2:每1s获取计数信号量(资源数-1),当获取成功后,打印信号量的计数值(资源数)
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void task2(void *pvParameters)	
{	
	

	BaseType_t errMessage;		/* 错误信息 */
	
	while(1)
    {	
	
		errMessage = xSemaphoreTake(SemaphoreCount,portMAX_DELAY);		/* 获取计数信号量 */
		if(errMessage == pdTRUE)	
		{
			printf("信号量的计数值为:%d\r\n",(int)uxSemaphoreGetCount(SemaphoreCount));
		}
		else
		{
			printf("获取信号量失败\r\n");
		}
		vTaskDelay(1000);

    }
}
  1. key.c
/* USER CODE BEGIN 2 */

#include "freertos_demo.h"
#include "key.h"
#include "usart.h"

extern QueueHandle_t SemaphoreCount;				/* 声明外部的计数信号量 */

void Key0_Down_Task(void)
{
	BaseType_t errMessage;		/* 错误信息 */
	
	errMessage = xSemaphoreGive(SemaphoreCount);	/* 释放计数信号量 */
	if(errMessage == pdTRUE)
	{
		printf("数值信号量释放成功\r\n");
	}
	else
	{
		printf("数值信号量释放失败\r\n");
	}
}
void Key0_Up_Task(void)
{
	
}
void Key1_Down_Task(void)
{
	
}
void Key1_Up_Task(void)
{
	
}
void Key2_Down_Task(void)
{

}
void Key2_Up_Task(void)
{

}
void WKUP_Down_Task(void)
{

}
void WWKUP_Up_Task(void)
{

}

void Key_One_Scan(uint8_t KeyName ,void(*OnKeyOneUp)(void), void(*OnKeyOneDown)(void))
{
   static uint8_t Key_Val[Key_Name_Max];    //按键值的存放位置
   static uint8_t Key_Flag[Key_Name_Max];   //KEY0~2为0时表示按下,为1表示松开,WKUP反之
    
   Key_Val[KeyName] = Key_Val[KeyName] <<1;  //每次扫描完,将上一次扫描的结果左移保存
   
    switch(KeyName)
    {
        case Key_Name_Key0:  Key_Val[KeyName] = Key_Val[KeyName] | (HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin));    //读取Key0按键值
            break;
        case Key_Name_Key1:  Key_Val[KeyName] = Key_Val[KeyName] | (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin));   //读取Key1按键值
            break;
        case Key_Name_Key2:  Key_Val[KeyName] = Key_Val[KeyName] | (HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin));   //读取Key2按键值
            break;
//        case Key_Name_WKUP:  Key_Val[KeyName] = Key_Val[KeyName] | (HAL_GPIO_ReadPin(WKUP_GPIO_Port, WKUP_Pin));   //读取WKUP按键值
//            break; 
        default:
            break;
    }
//    if(KeyName == Key_Name_WKUP)     //WKUP的电路图与其他按键不同,所以需要特殊处理
//    {
//        //WKUP特殊情况
//        //当按键标志为1(松开)是,判断是否按下,WKUP按下时为0xff
//        if(Key_Val[KeyName] == 0xff && Key_Flag[KeyName] == 1)
//        {
//            (*OnKeyOneDown)();
//           Key_Flag[KeyName] = 0;
//        }
//        //当按键标志位为0(按下),判断按键是否松开,WKUP松开时为0x00
//        if(Key_Val[KeyName] == 0x00 && Key_Flag[KeyName] == 0)
//        {
//            (*OnKeyOneUp)();
//           Key_Flag[KeyName] = 1;
//        } 
//    }
//    else                               //Key0~2按键逻辑判断
//    {
        //Key0~2常规判断
          //当按键标志为1(松开)是,判断是否按下
        if(Key_Val[KeyName] == 0x00 && Key_Flag[KeyName] == 1)
        {
            (*OnKeyOneDown)();
           Key_Flag[KeyName] = 0;
        }
        //当按键标志位为0(按下),判断按键是否松开
        if(Key_Val[KeyName] == 0xff && Key_Flag[KeyName] == 0)
        {
            (*OnKeyOneUp)();
           Key_Flag[KeyName] = 1;
        }  
    }
     
   
//}
/* USER CODE END 2 */

运行结果

在这里插入图片描述
运行结果如上图,我们来简单的解释一下,为什么是这样:

  1. 数值信号量创建成功后,打印对应信息
  2. 任务2优先级大于任务1,但是由于信号量资源数初始化为0,所以无法获取信号量,任务2进入阻塞,执行任务1。
  3. 执行任务1的过程中,按键0按下(我这里是连续按下3次按键0),在识别到第一次按下(还没来得及大于释放成功的信息),信号量资源数+1,任务2恢复就绪态并执行。
  4. 任务2执行获取信号量,并且打印计数值为0,后再次进入阻塞态,切换回任务1,打印第一次数值信号量释放成功。
  5. 紧接着第二、三次按键按下,打印第二、三次数值信号量释放成功。
  6. 1s后,切换会任务2,释放幸好了,打印计数值为1。
  7. 再过1s,打印计数值为0。

以上就是本期使用到的核心代码,其他部分我这里就不做展示,直接去看我往期的内容,源代码都有的。至于按键的配置,可以参考:夜深人静学32系列9——GPIO驱动数码管/蜂鸣器/按键/LED

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

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

相关文章

锅圈食品业绩承压显著:门店减少255家,押注肴肴领鲜打入农贸市场?

《港湾商业观察》廖紫雯 日前&#xff0c;锅圈食品&#xff08;上海&#xff09;股份有限公司&#xff08;以下简称&#xff1a;锅圈&#xff0c;02517.HK&#xff09;发布2024年上半年业绩运营情况。作为“在家吃饭第一股”&#xff0c;锅圈于2023年11月成功登陆港交所&#…

关于BSV区块链覆盖网络的常见问题解答(上篇)

​​发表时间&#xff1a;2024年9月20日 在BSV区块链上的覆盖网络服务为寻求可扩展、安全、高效交易处理解决方案的开发者和企业家开辟了新的视野。 作为开创性的曼达拉升级的一部分&#xff0c;覆盖网络服务提供了一个强大的框架&#xff0c;用于管理特定类型的交易和数据访问…

署名文章 | 对桂花AP2/ERFs的比较转录组分析揭示了OfERF017介导的有机酸代谢途径在花衰老中的作用

发表期刊&#xff1a;Frontiers in plant science 发表日期&#xff1a;2024年9月26日 影响因子&#xff1a;4.1 发表单位&#xff1a;湖北科技学院 研究背景 “玉露沾衣冷&#xff0c;金风拂面凉。桂花香满袖&#xff0c;秋色入诗囊。”桂花&#xff0c;中国十大名花之一…

Linux 网络配置 (深入理解)

前言 前期我比较迷惑Ubuntu 的网络配置。 我接触比较多的 Linux 发行版都是 Ubuntu &#xff0c;我按照网上的一些教程配置网络发现&#xff0c;没有相关网络配置文件夹。然后我发现不是我的问题而是不同版本的配置方式和工具是不一样的。然后有些配置已经弃用了。 常见的网络…

国庆节快乐|中国何以成为中国

华夏之土&#xff0c;广袤无垠&#xff1b;中华之史&#xff0c;源远流长。自古以来&#xff0c;中原大地物华天宝&#xff0c;人杰地灵&#xff0c;遂成一国&#xff0c;是谓中国。然中国之所以为中国&#xff0c;非徒地大物博、历史悠久也&#xff0c;更有其深厚之文化底蕴、…

实例讲解电动汽车冷却系统控制策略及Simulink建模方法

电动汽车的电机、电机控制器、DCDC、OBC在工作时都会大量发热&#xff0c;尤其是电机和电机控制器&#xff0c;功率大发热量大&#xff0c;且温度过高后会影响其正常功能&#xff0c;导致车辆故障无法正常行车&#xff0c;因此电动汽车冷却系统的控制也是一个非常重要的问题。本…

三维可视化技术的应用现状和发展前景

三维可视化技术的应用现状 工程建模 在工程领域&#xff0c;三维可视化技术被广泛应用于建筑设计、城市规划和工业制造等方面。通过三维建模软件&#xff0c;工程师可以创建逼真的模型&#xff0c;进行设计评估、碰撞检测和动态模拟&#xff0c;提高工程项目的效率与质量。 …

【傻呱呱】ESXI挂载USB移动硬盘给黑裙扩容

前期准备 ssh连接工具&#xff08;这里我用finalshell&#xff09; 删除移动硬盘分区&#xff08;此操作会删除硬盘内所有数据&#xff0c;注意备份&#xff01;&#xff01;&#xff01;&#xff09; 将需要挂载的usb移动硬盘连接到电脑上&#xff0c;使用分区工具&#xff…

1、Spring Boot 3.x 集成 Eureka Server/Client

一、前言 基于 Spring Boot 3.x 版本开发&#xff0c;因为 Spring Boot 3.x 暂时没有正式发布&#xff0c;所以很少有 Spring Boot 3.x 开发的项目&#xff0c;自己也很想了踩踩坑&#xff0c;看看 Spring Boot 3.x 与 2.x 有什么区别。自己与记录一下在 Spring Boot 3.x 过程…

安全类面试题-填空题

填空题 1、Linux下&#xff0c;复制/root/soure 到当前目录的命令是 cp -r /root/soure ./ 2、Linux下&#xff0c;解压缩bz2格式文件的命令是 bzip2 -d FileName 3、Linux下&#xff0c;查看网络连接状态的命令是 netstat 4、数据库触发器能监控的触发事件有&#xff1a; upda…

操作系统_名词_文件下载_反弹SHELL_防火墙绕过

操作系统 操作系统-用途&命令&权限&用户&防火墙 1、个人计算机&服务器用机 2、windows&Linux常见命令 3、文件权限&服务权限&用户权限 4、系统用户&用户组&服务用户等分类 5、自带防火墙出站&入站规则策略协议 实用案例1&#x…

如何在 Amazon EMR 中运行 Flink CDC Pipeline Connector

如何在Amazon EMR 中运行 Flink CDC Pipeline Connector 由于 Amazon EMR 最新的 Flink 版本中没有原生支持 Flink CDC&#xff0c;因此这里介绍一种通过 FlinkCDC Pipeline Connector 同步数据的例子(MySQL->Kafka) 环境准备 启动一个 Amazon EMR 集群 启动成功之后&#…

聚势启新 智向未来 | 重庆华阳通用科技有限公司揭牌成立

助推两江新区汽车产业高质量发展 (以下文字内容转载自两江新区网&#xff09; 9月26日&#xff0c;重庆华阳通用科技有限公司&#xff08;华阳通用重庆子公司&#xff09;在两江新区揭牌成立&#xff0c;将致力于智能座舱、智能驾驶两大领域&#xff0c;不断加大技术研发投入…

「系列投研|01」建立自己的移动比特币银行——赛道概况

ZJUBCA 09/28/2024 01&#xff5c;BTCfi赛道概况 BTCFi&#xff1a;建立自己的移动比特币银行 ——从Lending到Staking的全面解读 作者&#xff1a; Freya & Knight& Ausdin from ZJUBCA Elaine & Youyu from Satoshi Lab 关键词 BTCFi&#xff0c;稳定币&#xff…

DePIN 代表项目 CESS 受邀出席国会山活动,向议员展示创新 DePIN 技术

我们非常激动地宣布&#xff0c;CESS 已受邀参加由美国区块链协会主办的国会山活动&#xff0c;将于当地时间 2024 年 10 月 2 日向一众国会议员展示创新的 DePIN 技术&#xff01;本次关于去中心化物理基础设施网络&#xff08;DePIN&#xff09;的重要会议中&#xff0c;CESS…

windows下 Winobj.exe工具使用说明c++

1、winobj.exe工具下载地址 WinObj - Sysinternals | Microsoft Learn 2、接下来用winobj.exe查看全局互斥&#xff0c;先写一个小例子 #include <iostream> #include <stdlib.h> #include <tchar.h> #include <string> #include <windows.h>…

别再误用useMemo了!这才是最佳实践的正确打开方式

useMemo是react用作性能优化的一个hook&#xff0c;但有一个现象&#xff0c;不知道的人一次不用&#xff0c;知道的人随时随地到处都用。本文就带你真正搞懂什么情况下可以使用useMemo。 useMemo 是一个 React Hook&#xff0c;它在每次重新渲染的时候能够缓存计算的结果 useM…

【py】字符串切片

下面是一个简单的Python脚本&#xff0c;它读取输入的学号和姓名&#xff0c;然后按照要求拆分并输出&#xff1a; # 从键盘输入学号和姓名 input_str input("请输入学号和姓名&#xff1a;") # 学号和姓名的长度&#xff0c;可以根据实际情况调整 grade_length …

Linux下V4L2实时显示摄像头捕捉画面(完整QT+C++代码)

目录 一、V4L2 1、简介 2、编程与应用 二、示例演示 1、例子说明&#xff1a; 2、关键的代码演示 3、完整的例子的代码 一、V4L2 1、简介 V4L2&#xff0c;即Video for Linux Two&#xff0c;是Linux下关于视频设备的内核驱动框架&#xff0c;为驱动和应用程序提供了一…

前端vue-form表单的验证

form表单验证的完整步骤