STM32第二十课:FreeRTOS任务管理和信号量

目录

  • 一、任务管理方式
  • 二、任务堆栈溢出检测
  • 三、二值信号量(任务同步)
  • 四、计数信号量
  • 五、互斥信号量
  • 六、队列


一、任务管理方式

在这里插入图片描述
1.任务创建成功后会添加到就绪链表中,开启调度器,此时任务调度器会去就绪链表中找优先级最高的任务执行。若优先级一样则按照创建任务的先后来执行。
2.任务被执行时就会变为运行态时,该任务就会从就绪链表删除,若此时执行到任务中的vTaskDelay等函数时,该任务就会被挪到阻塞链表中。调度器此时会去执行其他任务。
3.当阻塞解除时,该任务会从阻塞链表中删掉,移动到就绪链表中。若解除任务的优先级很高,那么此时该任务会直接打断cpu正在执行的任务,抢占位置去执行自己。

二、任务堆栈溢出检测

详情见FreeRTOS中的任务堆栈溢出检测机制
主要作用就是方便调试,工程做完之后没问题了就关掉
写检测函数之前需要更改宏定义,我们采用的是第二种堆栈检测方法。
![

void vApplicationStackOverflowHook( TaskHandle_t xTask,char *pcTaskName )
{printf("任务:%s->栈溢出\r\n",pcTaskName);printf("任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(xTask));while(1)//栈溢出时卡死到钩子函数中{}
}

本质上就是一个钩子函数,在任务上下文切换的时候做检测,具有一定的滞后性,需要在任务发生上下文切换时才会进行,任务堆栈溢出时并不能马上检测到问题。
但大多常见情况下这种检测机制依然是非常实用的功能,可以帮助用户减少代码中的错误并提高应用程序代码的质量。

三、二值信号量(任务同步)

任务同步:任务B需要等待任务A执行完再去执行。
二值信号量也一样,谁拥有谁执行,比如任务B需要获得信号量才能执行,那么他就要等待A给他一个信号量然后再去执行。

1.添加头文件

#include "semphr.h"

2.创建一个SemaphoreHandle_t 类型的二值信号量句柄

SemaphoreHandle_t Binary;

3.主函数创建二值信号量,返回值为该信号量的句柄

	//创建一个二值信号量Binary = xSemaphoreCreateBinary();

4.使用函数xSemaphoreGive给出二值信号量,参数为二值信号量的句柄

xSemaphoreGive(Binary)

5.使用xSemaphoreTake函数接收二值信号量,参数为句柄和超时时间(也可填写portMAX_DELAY,表示死等)
若返回值为pdTRUE,则表示获取到该信号量。

if(xSemaphoreTake(Binary,1000) == pdTRUE) {printf("按键按下,获取到信号量\r\n");}

完整代码

//包含支持stm32f1系列的头文件
#include  "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
#include "key.h"
#include "adc.h"
#include "kqm.h"
#include "dht11.h"//使用FreeRTOS相关头文件之前先包含FreeRTOS.h
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/********************信号量句柄***********************/
SemaphoreHandle_t Binary;//传感器任务
TaskHandle_t Sensor_TaskHandle;
void Sensor_Task(void *p)
{while(1){taskENTER_CRITICAL();//进入临界区Dht11ReadData();//DHT11读取函数不能被打断taskEXIT_CRITICAL();//退出临界区KQMDealData();//该函数的调用时间小于等于1秒ADC_DataFliter();//ADC均值滤波vTaskDelay(1000);//阻塞1秒}
}//任务本体 闪灯任务
TaskHandle_t LED_TaskHandle;
void LED_Task(void *p)
{uint8_t i=0;while(1){if(xSemaphoreTake(Binary,1000) == pdTRUE) {printf("按键按下,获取到信号量\r\n");}else{printf("获取到信号量等待超时\r\n");}i++;printf("i=%d\r\n",i);Led_Toggle(1);//printf("LED任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(NULL));
//		Delay_nms(200);//也能延时,但是会一直占用CPU//也是延时200ms,但是FreeRTOS提供的函数,有阻塞机制,能够让任务从运行态变为阻塞态vTaskDelay(200);}
}
//任务本体 按键任务
TaskHandle_t KEY_TaskHandle;
void KEY_Task(void *p)
{while(1){switch(key_getvalue()){case 1:vTaskSuspend(LED_TaskHandle);break;case 2:vTaskResume(LED_TaskHandle);break;case 3:xSemaphoreGive(Binary);break;case 4:break;}vTaskDelay(10);//MS级别的延时,带有阻塞性质,任务会从运行态变为阻塞态}
}	int main()
{Led_Init();//初始化LEDKey_init();//初始化按键Usart1_Config();//初始化串口1ADC_Config();//初始化ADCKqm_U4Config();//初始化KQMDHT11_Mode();//初始化DHT11BaseType_t Ret = pdPASS;//创建一个二值信号量Binary = xSemaphoreCreateBinary();//1,如何创建一个任务?Ret = xTaskCreate(Sensor_Task,"Sensor_Task",200,NULL,1,&Sensor_TaskHandle);Ret = xTaskCreate(LED_Task, //创建任务的任务函数名"LED1_Toggle",//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL3,//任务优先级&LED_TaskHandle);//任务的句柄,用于后边删除,挂起任务if(Ret == pdPASS){printf("LED_Task创建完成\r\n");}Ret = xTaskCreate(KEY_Task, //创建任务的任务函数名"KEY_Task",//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL2,//任务优先级&KEY_TaskHandle);//任务的句柄,用于后边删除,挂起任务if(Ret == pdPASS){printf("KEY_Task创建完成\r\n");}printf("开启FreeRTOS调度器\r\n");//调度器启动完成之后,FreeRTOS会获取CPU控制权,会按照任务优先级执行创建的任务vTaskStartScheduler();while(1){	}
}void vApplicationStackOverflowHook( TaskHandle_t xTask,char *pcTaskName )
{printf("任务:%s->栈溢出\r\n",pcTaskName);printf("任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(xTask));while(1)//栈溢出时卡死到钩子函数中{}
}

四、计数信号量

一般在资源有限的情况下使用,如:停车场,坐位,传感器的访问等。
计数信号量测试:按键和灯,按键按下几次,灯翻转几次。
1.创建计数信号量的句柄

SemaphoreHandle_t Count_Handle;//计数信号量句柄

2.创建计数信号量
返回值为该信号量的句柄,参数为最大信号量为多少和初始信号量有几个。

Count_Handle = xSemaphoreCreateCounting(10,5);//创建计数信号量

3.给出信号量
参数为计数信号量的句柄

xSemaphoreGive(Count_Handle);

4.消耗信号量
参数和二值信号量一样,一个是对应的句柄,一个是超时。
成功返回pdTRUE。

if(xSemaphoreTake(Count_Handle,portMAX_DELAY) == pdTRUE) 

完整代码

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "delay.h"
#include "string.h"
#include "pwm.h"
#include "adc.h"
#include "su03t.h"
#include "dht11.h"
#include "kqm.h"
#include "usart.h"
#include "key.h"//使用FreeRtos相关头文件之前,一定要先包含这个#include "FreeRtos.h"
#include "FreeRtos.h"
#include "task.h"
#include "semphr.h"
#include "queue.h"TaskHandle_t Deal_TaskHandle;//数据处理
SemaphoreHandle_t Binary;//二值信号量句柄
SemaphoreHandle_t Count_Handle;//计数信号量句柄
TaskHandle_t LED_TaskHandle;//任务本体 闪灯任务
TaskHandle_t KEY_TaskHandle;//任务本体 按键任务
void Data_Task(void *p)
{while(1){Get_Smoke_Light_MidValue();DHT11_ReadData();vTaskDelay(300);KQM_DealData();Su03tDealData();}
}void KEY_Task(void *p)
{while(1){switch(key_getvalue()){case 1:vTaskSuspend(LED_TaskHandle);break;case 2:vTaskResume(LED_TaskHandle);break;case 3:xSemaphoreGive(Count_Handle);printf("给一个计数信号量\r\n");break;case 4:break;}vTaskDelay(10);//MS级别的延时,带有阻塞性质,任务会从运行态变为阻塞态}
}	
void LED_Task(void *p)
{uint8_t i=0;while(1){if(xSemaphoreTake(Count_Handle,portMAX_DELAY) == pdTRUE) {printf("消耗计数信号量\r\n");i++;printf("i=%d\r\n",i);Led_Toggle(1);vTaskDelay(1000);}}
}int main()
{RGBpwm_Config();Kqm_U4Config();Su03t_U5Config();DHT11_Config();	 Adc_Config();Led_Init();key_Init();Usart1_Config();BaseType_t Ret = pdPASS;
//	Ret = xTaskCreate(Data_Task,"DealData",300,NULL,2,&Deal_TaskHandle);
//	if(Ret==pdPASS)
//	{
//		printf("数据创建成功!\r\n");
//	}Binary = xSemaphoreCreateBinary();//计数信号量最大值   初始时有多少个信号量可用Count_Handle = xSemaphoreCreateCounting(10,5);//创建计数信号量Ret = xTaskCreate(LED_Task, //创建任务的任务函数名"LED1_Toggle",//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL3,//任务优先级&LED_TaskHandle);//任务的句柄,用于后边删除,挂起任务if(Ret == pdPASS){printf("LED_Task创建完成\r\n");}Ret = xTaskCreate(KEY_Task, //创建任务的任务函数名"KEY_Task",//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL2,//任务优先级&KEY_TaskHandle);//任务的句柄,用于后边删除,挂起任务if(Ret == pdPASS){printf("KEY_Task创建完成\r\n");}printf("开启FreeRTOS调度器成功\r\n");vTaskStartScheduler();while(1){}
}void vApplicationStackOverflowHook( TaskHandle_t xTask,char *pcTaskName )
{printf("任务:%s->栈溢出\r\n",pcTaskName);printf("任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(xTask));while(1)//栈溢出时卡死到钩子函数中{}
}

五、互斥信号量

用于共享资源的保护
资源A是共享资源,此时如果被任务1使用,那么就不能被其他任务使用。
(任务1:小A,你让我使用了,可就不能让别人使用了哦 ~)
1.创建句柄

SemaphoreHandle_t Mutex_Handle=NULL;

2.创建互斥信号量
返回值为互斥信号量的句柄

Mutex_Handle = xSemaphoreCreateMutex();//创建互斥信号量

3.获取信号,给出信号
保护printf,使printf能够完整打印。

void MyPrintf(char *p)
{xSemaphoreTake(Mutex_Handle,portMAX_DELAY);//获取信号量printf("%s",p);xSemaphoreGive(Mutex_Handle);//还回去
}

完整代码:

#include "delay.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "usart.h"
#include "stdio.h"
#include "led.h"
#include "key.h"
#include "dht.h"
#include "adc.h"
#include "kqm.h"/*******************信号量句柄*********************/
SemaphoreHandle_t Binary_Handle=NULL;
SemaphoreHandle_t Count_Handle=NULL;
SemaphoreHandle_t Mutex_Handle=NULL;
/*******************互斥信号量保护资源*********************/
void MyPrintf(char *p)
{xSemaphoreTake(Mutex_Handle,portMAX_DELAY);//获取信号量printf("%s",p);xSemaphoreGive(Mutex_Handle);//还回去
}/*******************LED任务*********************/
TaskHandle_t LEDtask_Handle = NULL;
//任务函数本身
void LED_Task(void * p)
{MyPrintf("LED任务创建成功\r\n");LED_Config();BEEP_Config();while(1){	if(xSemaphoreTake(Count_Handle,portMAX_DELAY) == pdTRUE){MyPrintf("LED反转\r\n");LED1_Toggle();}else{MyPrintf("超时结束\r\n");}vTaskDelay(500);//控制任务的执行周期}
}
/*******************按键任务*********************/
TaskHandle_t KEYtask_Handle = NULL;
//任务函数本身
void KEY_Task(void * p)
{MyPrintf("按键任务创建成功\r\n");KEY_Config();while(1){	switch(KEY_Scan()){case 1:BEEP_Toggle(); break;case 2:
//				xSemaphoreGive(Binary_Handle);//给出二值信号量if(xSemaphoreGive(Count_Handle) == pdTRUE)//给出计数信号量{MyPrintf("成功给出计数信号量\r\n");}else{MyPrintf("信号量已满\r\n");}break;case 3: break;case 4:vTaskDelete(LEDtask_Handle);break;}vTaskDelay(10);}
}
/*******************传感器任务*********************/
TaskHandle_t Senortask_Handle = NULL;
//任务函数本身
void Senor_Task(void * p)
{MyPrintf("传感器任务创建成功\r\n");uint8_t cnt = 0;ADC_Config();//初始化ADCUART4_Config();//初始化KQM传感器while(1){	cnt++;if(KQM_Anlyze() == 0){printf("CO2:%d\r\n",kqmdata.CO2);}else{MyPrintf("KQM数据错误\r\n");}if(cnt>=3){cnt = 0;taskENTER_CRITICAL();//进入临界区if(DHT11_ReadData()== 0){printf("温度数据:%.2f 湿度数据:%d\r\n",TEM,HUM);}else{MyPrintf("温湿度数据获取失败\r\n");}taskEXIT_CRITICAL();//退出临界区			}vTaskDelay(1000);}
}
int main(void)
{USART_Config();BaseType_t Ret = pdPASS;Binary_Handle = xSemaphoreCreateBinary();//创建二值信号量//                       计数信号量最大值   初始时有多少个信号量可用Count_Handle = xSemaphoreCreateCounting(10,5);//创建计数信号量Mutex_Handle = xSemaphoreCreateMutex();//创建互斥信号量//动态创建任务Ret =  xTaskCreate(LED_Task,//任务函数的入口,也就是函数名"LED_Task",//任务别名,方便FreeRTOS管理100,//任务分配的堆栈空间 32单片机就是50*4 = 200字节NULL,//任务函数的参数,无参数就写NULL1,//任务优先级&LEDtask_Handle);//任务的句柄(指针),可以用来管理任务if(Ret == pdPASS){printf("LED任务创建成功\r\n");}//动态创建任务Ret =  xTaskCreate(KEY_Task,//任务函数的入口,也就是函数名"KEY_Task",//任务别名,方便FreeRTOS管理100,//任务分配的堆栈空间 32单片机就是50*4 = 200字节NULL,//任务函数的参数,无参数就写NULL1,//任务优先级&KEYtask_Handle);//任务的句柄(指针),可以用来管理任务if(Ret == pdPASS){printf("按键任务创建成功\r\n");}Ret =  xTaskCreate(Senor_Task,//任务函数的入口,也就是函数名"Senor_Task",//任务别名,方便FreeRTOS管理100,//任务分配的堆栈空间 32单片机就是50*4 = 200字节NULL,//任务函数的参数,无参数就写NULL2,//任务优先级&Senortask_Handle);//任务的句柄(指针),可以用来管理任务if(Ret == pdPASS){printf("传感器任务创建成功\r\n");}vTaskStartScheduler();//启动调度器printf("调度器启动失败\r\n");while (1){}
}//函 数 功 能:任务栈溢出钩子函数,调试阶段用
void vApplicationStackOverflowHook(TaskHandle_t xTask,signed char *pcTaskName)
{printf("任务:#%s #栈溢出\r\n",pcTaskName);printf("任务栈空间剩余:%d\r\n",uxTaskGetStackHighWaterMark(xTask));while(1){}
}

六、队列

  主要用于任务间数据传输,采用FIFO(先进先出)模式,新数据通常发到队列后面,但也可以发到队列前面。
1.创建句柄

QueueHandle_t Queue;

2.创建队列

//创建队列 长度为10 ,队列中每个数据的大小2字节Queue = xQueueCreate(10,2);

3.接收数据
参数1:要发送数据的目标队列的句柄。
参数2:指向要发送数据的指针。
参数3:发送数据时等待的最长时间
返回值:
pdPASS:数据成功发送到队列。
errQUEUE_FULL:队列已满,无法发送数据。

if(xQueueReceive(Queue,buff2,100)==pdTRUE)

4.发送数据

if(xQueueSend(Queue,buff,100) == pdTRUE)

完整代码:

//包含支持stm32f1系列的头文件
#include  "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
#include "key.h"
#include "adc.h"
#include "kqm.h"
#include "dht11.h"//使用FreeRTOS相关头文件之前先包含FreeRTOS.h
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/********************信号量句柄***********************/
SemaphoreHandle_t Binary;
SemaphoreHandle_t Count;
SemaphoreHandle_t Mutex;
/********************队列句柄***********************/
QueueHandle_t Queue;
QueueHandle_t KqmQueue;
/*********************互斥锁保护Printf****************/
void MyPrintf(char *p)
{xSemaphoreTake(Mutex,portMAX_DELAY);printf("%s",p);xSemaphoreGive(Mutex);
}//传感器任务
TaskHandle_t Sensor_TaskHandle;
void Sensor_Task(void *p)
{uint8_t recv[8] = {0};MyPrintf("Sensor Task Begin\r\n");while(1){if(xQueueReceive(KqmQueue,recv,100)==pdTRUE){printf("接受数据:%x %x %x %x %x %x %x %x\r\n",recv[0],recv[1],\recv[2],recv[3],recv[4],recv[5],recv[6],recv[7]);}else{printf("队列为空,接收失败\r\n");}taskENTER_CRITICAL();//进入临界区Dht11ReadData();//DHT11读取函数不能被打断ADC_DataFliter();//ADC均值滤波taskEXIT_CRITICAL();//退出临界区vTaskDelay(1000);//阻塞1秒}
}//任务本体 闪灯任务
TaskHandle_t LED_TaskHandle;
void LED_Task(void *p)
{uint8_t i=0;MyPrintf("LED_Task Begin\r\n");while(1){if(xSemaphoreTake(Count,portMAX_DELAY) == pdTRUE) {MyPrintf("按键按下,获取到信号量\r\n");}else{MyPrintf("获取到信号量等待超时\r\n");}printf("i=%d\r\n",i++);Led_Toggle(1);//printf("LED任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(NULL));
//	Delay_nms(200);//也能延时,但是会一直占用CPU//也是延时200ms,但是FreeRTOS提供的函数,有阻塞机制,能够让任务从运行态变为阻塞态vTaskDelay(1000);}
}
//任务本体 按键任务
TaskHandle_t KEY_TaskHandle;
void KEY_Task(void *p)
{uint8_t buff[2] = {0xAA,0x55};uint8_t buff2[2] = {0};MyPrintf("KEY_Task Begin\r\n");while(1){switch(key_getvalue()){case 1:if(xQueueSend(Queue,buff,100) == pdTRUE){printf("发送成功\r\n");}else{printf("队列已满,发送失败\r\n");}break;case 2:if(xQueueReceive(Queue,buff2,100)==pdTRUE){printf("接受数据:%x %x\r\n",buff2[0],buff2[1]);}else{printf("队列为空,接收失败\r\n");}break;case 3:xSemaphoreGive(Count);break;case 4: break;}vTaskDelay(10);//MS级别的延时,带有阻塞性质,任务会从运行态变为阻塞态}
}	int main()
{Led_Init();//初始化LEDKey_init();//初始化按键Usart1_Config();//初始化串口1ADC_Config();//初始化ADCKqm_U4Config();//初始化KQMDHT11_Mode();//初始化DHT11BaseType_t Ret = pdPASS;//创建一个二值信号量Binary = xSemaphoreCreateBinary();//创建一个计数信号量Count = xSemaphoreCreateCounting(10,5);//创建互斥锁Mutex = xSemaphoreCreateMutex();//创建队列 长度为10 ,队列中每个数据的大小2字节Queue = xQueueCreate(10,2);KqmQueue = xQueueCreate(1,8);//1,如何创建一个任务?Ret = xTaskCreate(Sensor_Task,"Sensor_Task",200,NULL,1,&Sensor_TaskHandle);
//	Ret = xTaskCreate(LED_Task, //创建任务的任务函数名
//                    "LED1_Toggle",//任务名字
//                    100,//任务栈深度。32位单片机*4
//                    NULL,//创建任务时传递参数,没有就给NULL
//                    1,//任务优先级
//										&LED_TaskHandle);//任务的句柄,用于后边删除,挂起任务
//	if(Ret == pdPASS){
//		printf("LED_Task创建完成\r\n");
//	}Ret = xTaskCreate(KEY_Task, //创建任务的任务函数名"KEY_Task",//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL1,//任务优先级&KEY_TaskHandle);//任务的句柄,用于后边删除,挂起任务if(Ret == pdPASS){printf("KEY_Task创建完成\r\n");}printf("开启FreeRTOS调度器\r\n");//调度器启动完成之后,FreeRTOS会获取CPU控制权,会按照任务优先级执行创建的任务vTaskStartScheduler();printf("开启FreeRTOS调度器成功\r\n");while(1){	}
}void vApplicationStackOverflowHook( TaskHandle_t xTask,char *pcTaskName )
{printf("任务:%s->栈溢出\r\n",pcTaskName);printf("任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(xTask));while(1)//栈溢出时卡死到钩子函数中{}
}

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

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

相关文章

二叉树 —— OJ题目详解

1.二叉树的前序遍历 二叉树的前序遍历比较简单,但是在力扣上写这个接口需要注意几个点: int* preorderTraversal(struct TreeNode* root, int* returnSize) {} preorderTraversal 的返回值是动态开辟的数组,里面存放的是前序遍历的顺序int*…

【Linux取经之路】Linux常见指令

目录 基本指令 常见指令 1)ls —— 对于目录,列出该目录下的所有子目录和文件;对于文件,将列出文件名及其他信息 2)pwd —— 显示当前所在的目录 ​编辑 3)cd —— 切换到指定路径下 4)t…

Docker的基本认识和常见命令以及场景介绍

文章目录 前言一、Docker 的基本概念二、常见 Docker 命令和使用场景1. 镜像管理2. 容器管理3. 网络管理4. 数据管理 三、实际应用场景总结 前言 当谈论 Docker 时,我们通常涉及到容器化技术的方方面面,从基本概念到实际使用的场景和命令。让我们深入了解…

itextpdf字体选择

itextpdf 版本7.2.5 itextpdf-html2pdf 版本4.0.5 这里讲的是通过html转pdf,在html2pdf中是通过html中font-family样式来确定字体的,那已知font-family的情况,怎么确定pdf中实际用的字体,大致分为两步: 1、通过font…

识别 TON 生态系统中前10种加密资产,以bitget 钱包为例

元描述:想要找到下一个 100 倍加密货币投资?请密切关注这篇文章;它揭示了所有可能很快变得非常有价值的 TON 网络宝石。 由 Telegram 提供支持的 TON(开放网络)生态系统正在蓬勃发展!这是一个充满激动人心的…

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【25】【分布式事务】

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【25】【分布式事务】 本地事务事务的基本性质事务的隔离级别(下面四个越往下,隔离级 别越高,并发能力越差)事务的传播行为(是否…

【Hive SQL 每日一题】找出各个商品销售额的中位数

文章目录 测试数据需求说明需求实现方法1 —— 升序计算法方法2 —— 正反排序法 补充 测试数据 -- 创建 orders 表 DROP TABLE IF EXISTS orders; CREATE TABLE orders (order_id INT,product_id INT,order_date STRING,amount DOUBLE );-- 插入 orders 数据 INSERT INTO ord…

软件工程课设——成绩管理系统

软件工程课设——成绩管理系统 该文档是软件工程课程设计,成绩管理子系统的开发模块仓库。 功能分析 从面向的用户分,成绩管理子系统主要面向三类用户,即至少需要满足这三类用户的需求: 学生:学生是成绩管理系统的…

kubernetes1.24版本移除 Dockershim

​为什么会从 Kubernetes 中移除 dockershim ? Kubernetes 的早期版本仅适用于特定的容器运行时:Docker Engine。 后来,Kubernetes 增加了对使用其他容器运行时的支持。创建 CRI 标准是为了实现编排器(如 Kubernetes)和…

深入理解 Git Reset 的三种模式及其使用场景

🍎个人博客:个人主页 🏆个人专栏:Android ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 1. --soft 模式 2. --mixed 模式(默认) 3. --hard 模式 总结 结语 我的其他博客 前言 在日常的开发…

机器学习-1:人工智能、机器学习和深度学习的关系

人工智能(AI) 简单理解,任何一种事物只要具备了一定的智能就可以把它归类为人工智能。 官方定义:"AI is the field that sdudies the synthesis and analysis of computational agents that act intelligently." 其中&a…

安卓学习中遇到的问题【bug】

安卓学习中遇到的问题 1Gradle下载慢怎么办? Gradle下载慢怎么办? distributionUrlhttps://mirrors.cloud.tencent.com/gradle/gradle-7.5-bin.zip 2 Could not resolve all files for configuration ‘:classpath‘. > Could not resolv…

uniapp-vue3-vite 搭建小程序、H5 项目模板

uniapp-vue3-vite 搭建小程序、H5 项目模板 特色准备拉取默认UniApp模板安装依赖启动项目测试结果 配置自动化导入安装依赖在vite.config.js中配置 引入 prerttier eslint stylelint.editorconfig.prettierrc.cjs.eslintrc.cjs.stylelintrc.cjs 引入 husky lint-staged com…

处理在 electron 中使用开启了懒加载的 el-image 后,窗口最大化或窗口尺寸变化后图片无法显示的问题

文章目录 1、问题描述2、详情动图3、解决思路4、解决方案5、效果展示 1、问题描述 在 electron 中使用 el-image 时,开启了懒加载后,发现只有当窗口滚动后,图片才会显示,即便图片已经处于窗口的可视区域。当拖动窗口使其尺寸变大…

【VUE】9、VUE项目中使用VUEX完成状态管理

Vuex 是一个专为 Vue.js 应用程序设计的状态管理模式,它帮助开发者更有效地管理组件间共享的状态。在 Vue 项目中使用 Vuex,可以解决复杂应用中状态管理的困扰,确保状态变更的可追踪性和一致性。 1、Vuex 核心概念 State(状态&a…

基于JAVA+SpringBoot+Vue+uniapp+协同过滤算法+爬虫+AI的减肥小程序

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项目背景介绍: 小程序用户登录&#…

前端开发体系+html文件详解

目录 html骨架 body主体内基本元素 基本元素 超文本(超链接跳转) 锚点 图片标签 列表标签 表格标签 框架标签(窗口标签) 音频标签 视频标签 VScode编译器 输入框 字体样式 实例展示: 首先简要介绍前端的整…

在VS2017下FFmpeg+SDL编写最简单的视频播放器

1.下载ShiftMediaProject/FFmpeg 2.下载SDL2 3.新建VC控制台应用 3.配置include和lib 4.把FFmpeg和SDL的dll 复制到工程Debug目录下,并设置调试命令 5.复制一下mp4视频到工程Debug目录下(复制一份到*.vcxproj同一目录,用于调试) 6…

Integrated Gradients (Pytorch)refs

original paper:《Axiomatic Attribution for Deep Networks》https://arxiv.org/pdf/1703.01365 2)usage : https://blog.paperspace.com/model-interpretability-and-understanding-for-pytorch-using-captum/ https://captum.ai/docs/extension/integrated_gradients 3)htt…

python中的re模块--正则表达式

正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科 学的一个概念。正则表达式通常被用来检索、替换那些符合某个模 式(规则)的文本 re模块作用 通过使用…