FreeRTOS(事件组)

news2024/11/26 8:41:26

 资料来源于硬件家园:资料汇总 - FreeRTOS实时操作系统课程(多任务管理)

目录

一、事件的概念与应用 

1、事件的概念

2、事件的应用

二、事件的运作机制

1、FreeRTOS中事件组的句柄

2、FreeRTOS 任务间事件标志组的实现

3、FreeRTOS 中断方式事件标志组的实现

三、事件的API函数‍

 1、事件的典型流程与API

2、事件组创建与删除

3、任务内置位事件组

4、中断内置位事件组

5、等待事件组

四、事件的应用 - 任务与任务

1、任务配置

2、创建事件组

3、按键任务部分代码

4、同步任务代码

五、事件的应用 - 中断与任务

1、任务配置

2、开启FreeRTOS软件定时器

3、创建事件组

4、同步任务代码

5、串口回调函数代码

一、事件的概念与应用 

1、事件的概念

事件是实现任务与任务或任务与中断间通信的机制,用于同步,无数据传输。

与信号量不同的是,事件可以实现一对多、多对多的同步,即一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理;也可以是几个事件都发生后才唤醒任务进行事件处理。同样,也可以是多个任务同步多个事件。

FreeRTOS提供的事件具有如下特点:

① 事件相互独立,一个32位的事件集合(EventBitst类型的变量,实际可用于表示事件的只有低24位)用于标识该任务发生的事件类型,其中每一位表示一种事件类型(0表示该事件类型未发生,1表示该事件类型已经发生),一共有 24种事件类型。

②事件仅用于同步,不提供数据传输功能。

③ 事件无排队性,即多次向任务设置同一事件(如果任务还未来得及读取),等效于只设置一次。

④允许多个任务对同一事件进行读写操作。

⑤ 支持事件等待超时机制。

在FreeRTOS 事件中,获取每个事件时,用户可以选择感兴趣的事件,并且选择读取事件信息标记。它有3个属性,分别是逻辑与、逻辑或以及是否清除标记。当任务等待事件同步时,可以通过任务感兴趣的事件位和事件信息标记来判断当前接收的事件是否满足要求,如果满足,则说明任务等到对应的事件,系统将唤醒等待的任务;否则,任务会根据用户指定的阻塞超时时间继续等待下去。

2、事件的应用

FrecRTOS的事件用于任务与任务或任务与中断间的同步。为什么不直接用变量呢?那样岂不是更有效率?若是在裸机编程中,用全局变量是最有效的方法,但是在操作系统中,使用全局变量就要考虑以下问题了:

①如何对全局变量进行保护?如何处理多任务同时对它进行访问的情况?

②如何让内核对事件进行有效管理?

如果使用全局变量,就需要在任务中轮询查看事件是否发送,这会造成CPU 资源的浪费,此外,用户还需要自己去实现等待超时机制。所以,在操作系统中最好还是使用系统提供的通信机制,简单、方便、实用。

在某些场合,可能需要多个事件发生后才能进行下一步操作,比如一些危险机器的启动,需要检查各项指标,当指标不达标时就无法启动。但是检查各个指标时,不会立刻检测完毕,所以需要事件来做统一的等待。当所有的事件都完成了,那么机器才允许启动,这只是事件的应用之一

事件可用于多种场合,能够在一定程度上替代信号量,用于任务与任务间、中断与任务间的同步。一个任务或中断服务例程发送一个事件给事件对象,而后等待的任务被唤醒并对相应的事件进行处理。但是事件与信号量不同的是,事件的发送操作是不可累计的,而信号量的释放动作是可累计的。事件的另外一个特性是,接收任务可等待多种事件,即多个事件对应一个任务或多个任务。同时按照任务等待的参数,可选择是“逻辑或”触发还是“逻辑与”触发。这个特性也是信号量等所不具备的,信号量只能识别单一同步动作,而不能同时等待多个事件的同步。

各个事件可分别发送或一起发送给事件对象,而任务可以等待多个事件,任务仅对感兴趣的事件进行关注。当有它们感兴趣的事件发生并且符合条件时,任务将被唤醒并进行后续的处理动作。

二、事件的运作机制

1、FreeRTOS中事件组的句柄

图片

uxEventBits: 对于STM32,此变量为32位,其中低24位用于事件位,高8位用于其他用途。

图片

2、FreeRTOS 任务间事件标志组的实现

任务间事件标志组的实现是指各个任务之间使用事件标志组实现任务的同步机制。

下面的框图说明FreeRTOS 事件标志的实现:

图片

运行条件: 创建 2 个任务:Task1 和 Task2

运行过程描述如下:

 任务 Task1 运行过程中调用函数 xEventGroupWaitBits,等待事件标志位被设置,任务 Task1 由运行态进入到阻塞态。

 任务 Task2 设置 Task1 等待的事件标志,任务 Task1 由阻塞态进入到就绪态,在调度器的作用下由就绪态又进入到运行态。

上面就是一个简单的 FreeRTOS 任务间事件标志通信过程。

3、FreeRTOS 中断方式事件标志组的实现

FreeRTOS 中断方式事件标志组的实现是指中断函数和 FreeRTOS 任务之间使用事件标志。

下面的框图说明FreeRTOS 事件标志的实现:

图片

运行条件: 创建一个任务和一个串口接收中断

运行过程描述如下:

 任务 Task1 运行过程中调用函数 xEventGroupWaitBits,等待事件标志位被设置,任务 Task1 由运行态进入到阻塞态。

 Task1 阻塞的情况下,串口接收到数据进入到了串口中断服务程序,在串口中断服务程序中设置 Task1等待的事件标志,任务 Task1 由阻塞态进入到就绪态,在调度器的作用下由就绪态又进入到运行态。

上面就是一个简单的 FreeRTOS 中断方式事件标志通信过程。

实际应用中,中断方式的消息机制要注意以下三个问题:

 中断函数的执行时间越短越好,防止其它低于这个中断优先级的异常不能得到及时响应。

 实际应用中,建议不要在中断中实现消息处理,用户可以在中断服务程序里面发送消息通知任务,在任务中实现消息处理,这样可以有效地保证中断服务程序的实时响应。同时此任务也需要设置为高优先级,以便退出中断函数后任务可以得到及时执行。

 中断服务程序中一定要调用专用于中断的事件标志设置函数,即以 FromISR 结尾的函数。

三、事件的API函数‍

 1、事件的典型流程与API

> 创建事件组  xEventGroupCreate()

> 置位事件组  xEventGroupSetBits() , xEventGroupSetBitsFromISR()

> 等待事件组  xEventGroupWaitBits()

> 删除事件组  vEventGroupDelete()

2、事件组创建与删除

>事件组控制块(句柄)

图片

uxEventBits: 对于STM32,此变量为32位,其中低24位用于事件位

xTasksWaitingForBits: 任务等待链表

图片

>创建事件组

函数原型:EventGroupHandle_t xEventGroupCreate( void );

函数描述:函数 xEventGroupCreate 用于创建事件标志组。

 返回值,如果创建成功,此函数返回事件标志组的句柄,如果 FreeRTOSConfig.h 文件中定义的 heap空间不足会返回 NULL

使用举例:

图片

>删除事件组

函数原型:vEventGroupDelete(EventGroupHandle_t xEventGroup);

函数描述:函数 vEventGroupDelete可用于删除事件组。 

3、任务内置位事件组

函数原型:EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,

                                                                                         const EventBits_t uxBitsToSet );

函数描述:函数 xEventGroupSetBits 用于设置指定的事件标志位为 1。

 第 1 个参数是事件标志组句柄。

 第 2 个参数表示 24 个可设置的事件标志位,EventBits_t 是定义的 32 位变量,低 24 位用于事件标志设置。变量 uxBitsToSet 的低 24 位的某个位设置为 1,那么被设置的事件标志组的相应位就设置为 1。变量 uxBitsToSet 设置为 0 的位对事件标志相应位没有影响。比如设置变量 uxBitsToSet = 0x0003 就表示将事件标志的位 0 和位 1 设置为 1,其余位没有变化。

 返回当前的事件标志组数值。

使用这个函数要注意以下问题:

1. 使用前一定要保证事件标志组已经通过函数 xEventGroupCreate 创建了。

2. 此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的是xEventGroupSetBitsFromISR

3. 用户通过参数 uxBitsToSet 设置的标志位并不一定会保留到此函数的返回值中,下面举两种情况:

a. 调用此函数的过程中,其它高优先级的任务就绪了,并且也修改了事件标志,此函数返回的事件标志位会发生变化。

b. 调用此函数的任务是一个低优先级任务,通过此函数设置了事件标志后,让一个等待此事件标志的高优先级任务就绪了,会立即切换到高优先级任务去执行,相应的事件标志位会被函数

xEventGroupWaitBits 清除掉,等从高优先级任务返回到低优先级任务后,函数

xEventGroupSetBits 的返回值已经被修改。

使用举例:

图片

4、中断内置位事件组

函数原型:BaseType_t xEventGroupSetBitsFromISR(EventGroupHandle_t xEventGroup,

                                                                                             const EventBits_t uxBitsToSet, 

                                                                                  BaseType_t *pxHigherPriorityTaskWoken );

函数描述:函数 xEventGroupSetBits 用于设置指定的事件标志位为 1。

 第 1 个参数是事件标志组句柄。

 第 2 个参数表示 24 个可设置的事件标志位,EventBits_t 是定义的 32 位变量,低 24 位用于事件标志设置。变量 uxBitsToSet 的低 24 位的某个位设置为 1,那么被设置的事件标志组的相应位就设置为 1。变量 uxBitsToSet 设置为 0 的位对事件标志相应位没有影响。比如设置变量 uxBitsToSet = 0x0003 就表示将事件标志的位 0 和位 1 设置为 1,其余位没有变化。

 第 3 个参数用于保存是否有高优先级任务准备就绪。如果函数执行完毕后,此参数的数值是 pdTRUE,说明有高优先级任务要执行,否则没有。

 返回值,如果消息成功发送给守护任务(就是FreeRTOS 的定时器服务任务)返回 pdPASS,否则返回 pdFAIL,另外守护任务中的消息队列满了也会返回 pdFAIL。

使用这个函数要注意以下问题:

1. 使用前一定要保证事件标志已经通过函数 xEventGroupCreate 创建了。同时要在 FreeRTOSConfig.h

文件中使能如下三个宏定义:

#define INCLUDE_xEventGroupSetBitFromISR 1

#define configUSE_TIMERS 1

#define INCLUDE_xTimerPendFunctionCall 1

2. 函数 xEventGroupSetBitsFromISR 是用于中断服务程序中调用的,故不可以在任务代码中调用此函数,任务代码中使用的是 xEventGroupSetBits。

3. 函数 xEventGroupSetBitsFromISR 对事件标志组的操作是不确定性操作,因为不知道当前有多少个任务在等待此事件标志。而 FreeRTOS 不允许在中断服务程序和临界段中执行不确定性操作。为了不在中断服务程序中执行,就通过此函数给 FreeRTOS 的守护任务(就是 FreeRTOS 的定时器服务任务,内核自动创建的)发送消息,在守护任务中执行事件标志的置位操作。同时也为了不在临界段中执行此不确定操作,将临界段改成由调度锁来完成。这样不确定性操作在中断服务程序和临界段中执行的问题就都得到解决了。

4. 由于函数 xEventGroupSetBitsFromISR 对事件标志的置位操作是在守护任务里面执行的,如果想让置位操作立即生效,即让等此事件标志的任务能够得到及时执行,需要设置守护任务的优先级高于使用此事件标志组的所有其它任务。

使用举例:

图片

5、等待事件组

函数原型:

EventBits_t xEventGroupWaitBits(

        const EventGroupHandle_t xEventGroup, /* 事件标志组句柄 */

        const EventBits_t uxBitsToWaitFor, /* 等待被设置的事件标志位 */

        const BaseType_t xClearOnExit, /* 选择是否清零被置位的事件标志位 */

        const BaseType_t xWaitForAllBits, /* 选择是否等待所有标

        TickType_t xTicksToWait ); /* 设置等待时间 */

函数描述:

函数 xEventGroupWaitBits 等待事件标志被设置。

 第 1 个参数是事件标志组句柄。

 第 2 个参数表示等待 24 个事件标志位中的指定标志,EventBits_t 是定义的 32 位变量,低 24 位用于事件标志设置。比如设置变量 uxBitsToWaitFor = 0x0003 就表示等待事件标志的位 0 和位 1 设置为 1。此参数切不可设置为 0。

 第 3 个参数选择是否清除已经被置位的事件标志,如果这个参数设置为 pdTRUE,且函数

xEventGroupWaitBits 在参数 xTicksToWait 设置的溢出时间内返回或等到满足任务唤醒的事件时,相应被设置的事件标志位会被清零。如果这个参数设置为 pdFALSE,对已经被设置的事件标志位没有影响。

 第 4 个参数选择是否等待所有的标志位都被设置,如果这个参数设置为 pdTRUE,要等待第 2 个参数 uxBitsToWaitFor 所指定的标志位全部被置 1,函数才可以返回。当然,超出了在参数xTicksToWait 设置的溢出时间也是会返回的。如果这个参数设置为 pdFALSE,第 2 个参数uxBitsToWaitFor 所指定的任何标志位被置 1,函数都会返回,超出溢出时间也会返回。

 第 5 个参数设置等待时间,单位时钟节拍周期。如果设置为 portMAX_DELAY,表示永久等待。

 返回值,由于设置的时间超时或者指定的事件标志位被置 1,导致函数退出时返回的事件标志组数值。

使用这个函数要注意以下问题:

1. 此函数切不可在中断服务程序中调用。

2. 着重说明下这个函数的返回值,通过返回值用户可以检测是哪个事件标志位被置 1 了

 如果由于设置的等待时间超时,函数的返回值可会有部分事件标志位被置 1。

 如果由于指定的事件标志位被置1而返回,并且设置了这个函数的参数xClearOnExit为pdTRUE,那么此函数的返回值是清零前的事件标志组数值。

另外,调用此函数的任务在离开阻塞状态到退出函数 xEventGroupWaitBits 之间这段时间,如果一个高优先级的任务抢占执行了,并且修改了事件标志位,那么此函数的返回值会跟当前的事件标志组数值不同。

使用举例:

图片

四、事件的应用 - 任务与任务

1、任务配置

LED0_Task: 运行指示灯

KEY_Task: 按键,打印任务信息,触发事件

Event_Sync_Task:   等待事件,同步任务

2、创建事件组

定义

/* USER CODE BEGIN Variables */
EventGroupHandle_t MyEvent01Handle=NULL; //不能配置,只能自己写
/* USER CODE END  Variables */

创建

  /* USER CODE BEGIN Init */
  MyEvent01Handle = xEventGroupCreate();
  if(MyEvent01Handle==NULL)
  {
		sprintf(buff,"%s \r\n","创建事件组失败");
		HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);
  }
  else
  {
		sprintf(buff,"%s \r\n","创建事件组成功");
		HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);
  }
  /* USER CODE END Init */

3、设置事件

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define KEY0_EVENT  (EventBits_t)(0x0001 << 0)//设置事件掩码位0
#define KEY1_EVENT  (EventBits_t)(0x0001 << 8)//设置事件掩码位8
/* USER CODE END PD */

4、按键任务部分代码

	  //KEY0
	  if(KeyCode==KEY0)
	  {
		sprintf(buff,"%s \r\n","触发 KEY0 事件");
		HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);
        xEventGroupSetBits(MyEvent01Handle, KEY0_EVENT);
	  }
	  //KEY1
	  if(KeyCode==KEY1)
	  {
			sprintf(buff,"%s \r\n","触发 KEY1 事件");
			HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);
	        xEventGroupSetBits(MyEvent01Handle, KEY1_EVENT);
	  }

5、预编译宏

#define Event_WaitAllBits //预编译,看是否需要等待所有事件

6、同步任务代码

void Event_Sync_Task(void const * argument)
{
	/* USER CODE BEGIN Event_Sync_Task */
	EventBits_t xEvent;
	int  SyncCnt = 0; //同步计数

	/* Infinite loop */
#ifdef Event_WaitAllBits
	for(;;)
	{
		sprintf(buff,"%s \r\n","等待事件同步信号,无限等待");
		HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);
		xEvent = xEventGroupWaitBits(
				MyEvent01Handle, //事件句柄
				KEY0_EVENT|KEY1_EVENT, //事件 按键0,1
				pdTRUE,          //退出时清除事件位
				pdTRUE,         //"逻辑或" - 满足任一事件
				portMAX_DELAY    //无限等待
		);
		if( (xEvent&(KEY0_EVENT|KEY1_EVENT)) == (KEY0_EVENT|KEY1_EVENT))
		{
			sprintf(buff,"成功接受到事件同步信号,次数 = %u\r\n",++SyncCnt);
			HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);
		}
	}
#else
	for(;;)
	{
		sprintf(buff,"%s \r\n","等待事件同步信号,无限等待");
		HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);
		xEvent = xEventGroupWaitBits(
				MyEvent01Handle, //事件句柄
				KEY0_EVENT|KEY1_EVENT, //事件 按键0,1
				pdTRUE,          //退出时清除事件位
				pdFALSE,         //"逻辑或" - 满足任一事件
				portMAX_DELAY    //无限等待
		);
		if(((xEvent&KEY0_EVENT) == KEY0_EVENT) || ((xEvent&KEY1_EVENT) == KEY1_EVENT))
		{
			sprintf(buff,"成功接受到事件同步信号,次数 = %d\r\n",++SyncCnt);
			HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);
		}
	}
#endif
	/* USER CODE END Event_Sync_Task */

	/* USER CODE BEGIN BinarySem_Sync_Task */
}

五、事件的应用 - 中断与任务

1、任务配置

2、开启FreeRTOS软件定时器

 

3、创建事件组

同上任务与任务

4、同步代码

void Event_Sync_ISR_Task(void const * argument)
{
	/* USER CODE BEGIN Event_Sync_Task */
	EventBits_t xEvent;
	char rxBuff[13];

	/* Infinite loop */
	for(;;)
	{
		//通过串口2中断接收12个字符
		HAL_UART_Receive_IT(&huart2, (uint8_t *)rxBuff, 12);

		sprintf(buff,"请通过UART2发送12个字符\r\n");
		HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);

		sprintf(buff,"等待事件同步信号,无限等待\r\n");
		HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);

		xEvent = xEventGroupWaitBits(
				MyEvent01Handle, //事件句柄
				UART2_RecEVENT,  //事件 - 串口3接收
				pdTRUE,          //退出时清除事件位
				pdTRUE,          //"逻辑与" - 满足所有事件
				portMAX_DELAY    //无限等待
		);
		if((xEvent&UART2_RecEVENT) == UART2_RecEVENT)
		{
			sprintf(buff,"接收到的串口数据:%s\r\n\r\n",rxBuff);
			HAL_UART_Transmit(&huart2, (uint8_t*)buff,strlen(buff), HAL_MAX_DELAY);
		}
		HAL_UART_Receive_IT(&huart2, (uint8_t *)rxBuff, 12);
	}
	/* USER CODE END Event_Sync_Task */
}

5、串口回调函数代码

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;

	if(huart->Instance == huart2.Instance)
	{
		xEventGroupSetBitsFromISR(MyEvent01Handle,UART2_RecEVENT,&xHigherPriorityTaskWoken);

		portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
	}
}

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

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

相关文章

vue2学习:reduce方法和computed计算属性用法

reduce reduce可以遍历集合并将集合所有的值汇总为一个。 第一个参数是一个回调函数&#xff0c;函数第一个参数是汇总起来的最终值&#xff0c;默认是集合的第一项&#xff0c;函数第二个参数是集合遍历出来的集合元素&#xff1b; 第二个参数可以指定回调函数中第一个参数汇…

62、华为昇腾开发板Atlas 200I DK A2配置mmpose的hrnet模型推理python/c++

基本思想&#xff1a;适配mmpose模型&#xff0c;记录一下流水帐&#xff0c;环境配置和模型来自&#xff0c;请查看参考链接。 链接: https://pan.baidu.com/s/1IkiwuZf1anyKX1sZkYmD1g?pwdi51s 提取码: i51s 一、转模型 (base) rootdavinci-mini:~/sxj731533730# atc --mo…

优测云服务平台|【压力测试功能升级】轻松完成压测任务

一、本次升级主要功能如下&#xff1a; 1.多份报告对比查看测试结果 2.报告新增多种下载格式 Word格式Excel格式 3.新增多种编排复杂场景的控制器 漏斗控制器并行控制器事务控制器仅一次控制器分组控制器集合点 4.新增概览页面&#xff0c;包含多种统计维度 二、报告对比…

智慧工地源码,互联网+建筑工地,基于微服务+Java+Spring Cloud +Vue+UniApp开发

基于微服务JavaSpring Cloud VueUniApp MySql开发的智慧工地云平台源码 智慧工地概念&#xff1a; 智慧工地就是互联网建筑工地&#xff0c;是将互联网的理念和技术引入建筑工地&#xff0c;然后以物联网、移动互联网技术为基础&#xff0c;充分应用BIM、大数据、人工智能、移…

DoorGym:开源的可拓展的开门仿真环境,用于域随机化的强化学习、深度强化学习

0.概述 目的&#xff1a;创建一个可以改变门把手形状、类型、位置、环境颜色、照明条件、机械臂结构的仿真环境&#xff0c;以训练出鲁棒性更高、更能关注到任务本质特征、容易迁移到现实的模型 网址&#xff1a;环境下载&#xff0c; 1.领域随机化DR 假设很难对目标域进…

在Visual Studio上,使用OpenCV实现人脸识别

1. 环境与说明 本文介绍了如何在Visual Studio上&#xff0c;使用OpenCV来实现人脸识别的功能 环境说明 : 操作系统 : windows 10 64位Visual Studio版本 : Visual Studio Community 2022 (社区版)OpenCV版本 : OpenCV-4.8.0 (2023年7月最新版) 实现效果如图所示&#xff0…

SAP SM30 自动带出描述实现

需求&#xff1a; 在SM30中维护销售订单类型的时候&#xff0c;根据维护的销售订单类型自动带出订单类型描述 事务码&#xff1a; SE11 进入表维护生成器中 创建事件 选择【维护事件】: 05 自定义子例程&#xff1a; SET_DESCRIPTION 点击编辑器按钮进行代码编辑 具体代码…

浅学实战:探索PySpark实践,解锁大数据魔法!

文章目录 Spark和PySpark概述1.1 Spark简介1.2 PySpark简介 二 基础准备2.1 PySpark库的安装2.2 构建SparkContext对象2.3 SparkContext和SparkSession2.4 构建SparkSession对象2.5 PySpark的编程模型 三 数据输入3.1 RDD对象3.2 Python数据容器转RDD对象3.3 读取文件转RDD对象…

【力扣每日一题】1572. 矩阵对角线元素的和 8.11打卡

文章目录 题目思路代码 题目 1572. 矩阵对角线元素的和 难度&#xff1a; 简单 描述&#xff1a; 给你一个正方形矩阵 mat&#xff0c;请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 返回合并后的二叉树。 注意…

(leecode)密码检查

有点感觉&#xff0c;试试看~ 先贴解法&#xff0c;再说题目和思路 题解 #include <stdio.h> #include <string.h> #include <ctype.h>int main() {int N 0;scanf("%d",&N);getchar();while(N--) {char str[101] {0};scanf("%s&…

Android性能优化——内存优化

一、内存问题 内存抖动&#xff0c;锯齿状&#xff0c;GC导致卡顿内存泄漏&#xff0c;可用内存减少&#xff0c;频繁GC 内存溢出&#xff0c;OOM&#xff0c;程序异常 二、内存分析工具 Memory ProfilerMemory Analyzer LeakCanary Memory Profiler 实时图表展示应用内存使…

10分钟极速入门dash应用开发

大家好我是费老师&#xff0c;几天前我发布了由我开源维护的dash通用网页组件库fac的0.2.x全新版本&#xff0c;为大家介绍了其具有的诸多实用特性功能&#xff0c;也吸引了很多对基于dash的Python全栈应用开发感兴趣的朋友&#xff0c;为了方便更多对dash应用开发不甚了解的朋…

stable diffusion 电商应用技术(插图部分重绘)

1.下载inpaint anything插件 2.下载识别模型 3.使用全景分割 4.分割模版,获取蒙版 5.发送到图生图重绘制 6.固定姿势 7.clip反推提示词 8.生成重绘衣服

msvcr110.dll缺失的解决方法分享,多种方法教你修复msvcr110.dll

我们在使用电脑的时候会遇到各种各样的问题&#xff0c;特别是dll文件缺失的这一块更是经常可以看到的&#xff0c;如你在使用电脑的时候&#xff0c;突然弹出一个电脑缺失了msvcr110.dll文件&#xff0c;一些程序无法运行&#xff0c;这时候我们就要针对于这方面来进行一些解决…

【C++】vector容器

0.前言 1.vector构造函数 #include <iostream> using namespace std; #include <vector>void printVector(vector<int>& v) //此处&代表 引用 &#xff1b;若取地址&#xff0c;则是 数据类型* 变量名 {for (vector<int>::iterator it v.begi…

PLUS操作流程、应用与实践,多源不同分辨率数据的处理、ArcGIS的应用、PLUS模型的应用、InVEST模型的应用

PLUS模型是由中国地质大学&#xff08;武汉&#xff09;地理与信息工程学院高性能空间计算智能实验室开发&#xff0c;是一个基于栅格数据的可用于斑块尺度土地利用/土地覆盖(LULC)变化模拟的元胞自动机(CA)模型。PLUS模型集成了基于土地扩张分析的规则挖掘方法和基于多类型随机…

从LeakCanary看Fragment生命周期监控

前文中我们已经了解到LeakCanary中Service生命销毁的监听方式&#xff0c;那么Fragment的生命周期监听又是怎么实现的呢&#xff1f; Activity生命周期监听&#xff0c;在Application里面有ActivityLifecycleCallbacks&#xff0c;那么Fragment是否相似呢&#xff1f;我们的第…

Docker 本地镜像发布到私有仓库

1. 本地镜像发布到私有库流程 2. 是什么 1 官方Docker Hub地址&#xff1a;https://hub.docker.com/&#xff0c;中国大陆访问太慢了且准备被阿里云取代的趋势&#xff0c;不太主流。 2 Dockerhub、阿里云这样的公共镜像仓库可能不太方便&#xff0c;涉及机密的公司不可能提供镜…

使用 NLP 进行文本摘要

一、说明 文本摘要是为较长的文本文档生成简短、流畅且最重要的是准确摘要的过程。自动文本摘要背后的主要思想是能够从整个集合中找到最重要信息的一小部分&#xff0c;并以人类可读的格式呈现。随着在线文本数据的增长&#xff0c;自动文本摘要方法可能会非常有用&#xff0c…

激活函数总结(八):基于Gate mechanism机制的激活函数补充(GLU、SwiGLU、GTU、Bilinear、ReGLU、GEGLU)

激活函数总结&#xff08;八&#xff09;&#xff1a;基于Gate mechanism机制的激活函数补充 1 引言2 激活函数2.1 GLU激活函数2.2 SwiGLU激活函数2.3 GTU激活函数2.4 Bilinear激活函数2.5 ReGLU激活函数2.6 GEGLU激活函数 3. 总结 1 引言 在前面的文章中已经介绍了介绍了一系…