FreeRTOS源码分析-10 互斥信号量

目录

1 事件标志组概念及其应用

1.1 事件标志组定义

1.2 FreeRTOS事件标志组介绍

1.3 FreeRTOS事件标志组工作原理

2 事件标志组应用

2.1 功能需求

2.2 API

 2.3 功能实现

3 事件标志组原理

3.1 事件标志组控制块

3.2 事件标志组获取标志位

3.3 等待事件标志触发

3.4 事件标志组设置标志位

3.5 事件标志组任务同步


1 事件标志组概念及其应用

1.1 事件标志组定义

门钥匙代表或的问题,每个都可以开启
公交车代表与的问题,到齐了才可以走

 

FreeRTOS事件标志组一共8个bit。

如Task 1或Tast 2去触发第1位,第1位或第三位能触发任务Task3

如Task 6、7、8同时置位触发Task 4

1.2 FreeRTOS事件标志组介绍

任务可以和事件标志组进行关联,如bit23,任务阻塞等待消息,和消息队列一样有个超时机制

当任意任务或者中断触发置位的时候,任务会从阻塞变为就绪态。

1.3 FreeRTOS事件标志组工作原理

 创建事件控制块,关联事件,等待事件触发

2 事件标志组应用

2.1 功能需求

  • 1、使用事件标志组检测多个按键输入(K3、K4、K5、K6)
  • 2、当检测到任何一个按键按下,串口打印输出按键信息
  • 3、当4路按键都已经按下,触发蜂鸣器报警

2.2 API

CubeMX中未提供,需要自己创建

 EventBits_t 返回值返回的是所有24位的值

守护任务:处理操作系统不想在中断中处理的任务,是一种特殊类型的任务,它在系统中扮演着重要的角色。它被用于监控和处理FreeRTOS内部的错误和异常情况,以确保系统的稳定性。守护任务可以使用软件定时器来执行一些周期性的任务。通过创建一个周期性的软件定时器,守护任务可以在固定的时间间隔内执行特定的操作。例如,守护任务可以使用软件定时器来定期检查任务堆栈的使用情况、检测任务优先级错误或处理未处理的中断等。软件定时器提供了一种简便的方式来触发守护任务的执行,以确保系统中的重要任务得到及时处理。

中断中不允许上下文切换,都是由守护任务来执行的。

 使用WaitBits,会让任务进入阻塞态

 参数解释:

  • xEventGroup:事件组句柄,表示要操作的事件组。
  • uxBitsToWaitFor:等待的事件位,即需要等待其中的哪些事件发生。可以使用位掩码形式指定多个事件位。若指定为0,则表示不等待任何事件,直接返回当前事件组的位状态。
  • uxBitsToSet:设置的事件位,即在等待期间发生事件后,需要设置哪些事件位。同样,可以使用位掩码指定多个事件位。
  • xTicksToWait:等待的超时时间,以FreeRTOS的Tick单位表示。可以设置为portMAX_DELAY表示无限等待,或者具体的等待时间。

返回值:

  • 返回已经发生的事件位,即满足等待条件的事件。如果等待发生事件时超时,则返回0。

使用xEvetnGroupSync函数的具体步骤如下:

  1. 创建或获取一个事件组句柄。
  2. 使用xEvetnGroupSync函数等待指定的事件位。可以设置需要等待的事件位、需要设置的事件位和等待超时时间。
  3. 根据返回值判断等待是否成功,根据已发生的事件位执行相应的操作。

注意,xEvetnGroupSync函数是一个阻塞函数,即在等待期间会阻塞当前任务的执行。如果有其他任务在等待相同的事件组,则它们可能会被唤醒以执行后续操作。因此,在使用xEvetnGroupSync函数时需要谨慎设计,以避免出现死锁或优先级反转等问题。

 2.3 功能实现

STM32CubeMX功能配置

GPIO略

根据接口说明 ,事件标志组中断中需要开启守护任务

 

 

 

按键中断及事件标志组创建

//freertos.c//...略
#include "event_groups.h"EventGroupHandle_t KeyEventGroup; //全局变量句柄void MX_FREERTOS_Init(void) {//创建KeyEventGroup = xEventGroupCreate();if(KeyEventGroup == NULL){printf("KeyEventGroup Create Error\r\n");}//...略
}

按键检测任务和蜂鸣器报警任务

 

//gpio.c#include "event_groups.h"//...略
/*  
#define KEY3_EVENT_BIT  (1<<0)
#define KEY4_EVENT_BIT  (1<<1)
#define KEY5_EVENT_BIT  (1<<2)
#define KEY6_EVENT_BIT  (1<<3) typedef enum
{KEY_DOWN,KEY_UP,KEY_RESET}teKeyStatus;*/teKeyStatus KeyStatus;
extern EventGroupHandle_t KeyEventGroup;void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){if(Key3_Pin == GPIO_Pin){if(HAL_GPIO_ReadPin(Key3_GPIO_Port,Key3_Pin) == GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(Key3_GPIO_Port,Key3_Pin) == GPIO_PIN_RESET){//设置事件xEventGroupSetBitsFromISR(KeyEventGroup,KEY3_EVENT_BIT,NULL);}}}if(Key4_Pin == GPIO_Pin){if(HAL_GPIO_ReadPin(Key4_GPIO_Port,Key4_Pin) == GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(Key4_GPIO_Port,Key4_Pin) == GPIO_PIN_RESET){//设置事件xEventGroupSetBitsFromISR(KeyEventGroup,KEY4_EVENT_BIT,NULL);}}}if(Key5_Pin == GPIO_Pin){if(HAL_GPIO_ReadPin(Key5_GPIO_Port,Key5_Pin) == GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(Key5_GPIO_Port,Key5_Pin) == GPIO_PIN_RESET){//设置事件xEventGroupSetBitsFromISR(KeyEventGroup,KEY5_EVENT_BIT,NULL);}}}if(Key6_Pin == GPIO_Pin){if(HAL_GPIO_ReadPin(Key6_GPIO_Port,Key6_Pin) == GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(Key6_GPIO_Port,Key6_Pin) == GPIO_PIN_RESET){//设置事件xEventGroupSetBitsFromISR(KeyEventGroup,KEY6_EVENT_BIT,NULL);}}}
}
//freertos.cvoid Delay_Task(void const * argument)
{/* USER CODE BEGIN Delay_Task */EventBits_t KeyEventBits;/* Infinite loop */for(;;){KeyEventBits = xEventGroupWaitBits(KeyEventGroup,KEY3_EVENT_BIT|KEY4_EVENT_BIT|KEY5_EVENT_BIT|KEY6_EVENT_BIT,pdFALSE,pdFALSE,portMAX_DELAY);printf("Key is Down Key Event Bit is %x\r\n",KeyEventBits);osDelay(10);}
}void High_Task(void const * argument)
{EventBits_t KeyEventBits;for(;;){KeyEventBits = xEventGroupWaitBits(KeyEventGroup,KEY3_EVENT_BIT|KEY4_EVENT_BIT|KEY5_EVENT_BIT|KEY6_EVENT_BIT,pdTRUE,pdTRUE,portMAX_DELAY);	if(KeyEventBits == (KEY3_EVENT_BIT|KEY4_EVENT_BIT|KEY5_EVENT_BIT|KEY6_EVENT_BIT)){printf("Buzzer is Toggle\r\n");HAL_GPIO_TogglePin(Buzzer_GPIO_Port,Buzzer_Pin);}osDelay(10);}
}

3 事件标志组原理

3.1 事件标志组控制块

 

#define eventCLEAR_EVENTS_ON_EXIT_BIT	0x01000000UL		//表示退出是否清楚已经触发的标志位 25bit表示#define eventUNBLOCKED_DUE_TO_BIT_SET	0x02000000UL		//解除阻塞是否,已经设置标志位 26位#define eventWAIT_FOR_ALL_BITS			0x04000000UL		//是与逻辑还是或逻辑#define eventEVENT_BITS_CONTROL_BYTES	0xff000000UL		//用于分解出,事件标志组位使用typedef struct xEventGroupDefinition
{//事件标志组EventBits_t uxEventBits;//任务等待的列表List_t xTasksWaitingForBits;		/*< List of tasks waiting for a bit to be set. */
} EventGroup_t;

3.2 事件标志组获取标志位

 全局变量一定要保护,所以要进入临界段

#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 )/*参数:1、控制块/句柄2、要清除位返回值:事件标志位*/ 1<<0
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventBits_t uxReturn;/*1、进入临界段2、获取当前事件标志位3、清除要设置的事件标志位4、退出临界段5、返回事件标志组值*/taskENTER_CRITICAL();{/* The value returned is the event group value prior to the bits beingcleared. */uxReturn = pxEventBits->uxEventBits;/* Clear the bits. */pxEventBits->uxEventBits &= ~uxBitsToClear;}taskEXIT_CRITICAL();return uxReturn;
}/*参数:	1、事件控制块返回值:事件标志位*/
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
{
UBaseType_t uxSavedInterruptStatus;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventBits_t uxReturn;//禁止中断 带返回值uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();{//获取事件标志位uxReturn = pxEventBits->uxEventBits;}//恢复中断,在进入禁止之前的状态portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );return uxReturn;
}

3.3 等待事件标志触发

 复位列表项:表示事件信息

/*参数:1、事件控制块2、要等待出发的标志位3、退出是否要清除4、与逻辑还是或逻辑5、阻塞等待时间返回值:当前事件标志位
*/
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventBits_t uxReturn, uxControlBits = 0;
BaseType_t xWaitConditionMet, xAlreadyYielded;
BaseType_t xTimeoutOccurred = pdFALSE;//挂起调度器vTaskSuspendAll();{//获取当前的事件标志位const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;/* 检查是否触发 参数:	1、当前的事件标志位2、要等待触发的事件标志位3、触发逻辑???返回值:	pdFALSE  pdTRUE*/xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );if( xWaitConditionMet != pdFALSE ){/* 已经触发 */uxReturn = uxCurrentEventBits;xTicksToWait = ( TickType_t ) 0;/* 清楚已经触发的标志 */if( xClearOnExit != pdFALSE ){pxEventBits->uxEventBits &= ~uxBitsToWaitFor;}else{mtCOVERAGE_TEST_MARKER();}}else if( xTicksToWait == ( TickType_t ) 0 ){/* 不需要超时,直接返回标志位. */uxReturn = uxCurrentEventBits;}else{/* 事件没有触发,并且需要超时*/if( xClearOnExit != pdFALSE ){//uxControlBits = 0x01000000UL;uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;}else{mtCOVERAGE_TEST_MARKER();}if( xWaitForAllBits != pdFALSE ){//uxControlBits = 0x05000000UL;uxControlBits |= eventWAIT_FOR_ALL_BITS;}else{mtCOVERAGE_TEST_MARKER();}/* 把任务添加到事件列表中参数:1、列表的地址2、传入列表项值3、任务阻塞时间*/vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );uxReturn = 0;traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );}}//恢复调度器xAlreadyYielded = xTaskResumeAll();//再次判断是否需要超时if( xTicksToWait != ( TickType_t ) 0 ){if( xAlreadyYielded == pdFALSE ){//进行上下文切换 ->pendSVportYIELD_WITHIN_API();}else{mtCOVERAGE_TEST_MARKER();}/* 任务已经恢复1、复位列表项中的值  复位为任务有优先级*/uxReturn = uxTaskResetEventItemValue();//是不是通过事件置位解除的任务if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ){//进入临界段taskENTER_CRITICAL();{/* 获取当前事件位. */uxReturn = pxEventBits->uxEventBits;/* 再此判断是否已经置位 */if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE ){//如果需要清除,清除触发后的标志位if( xClearOnExit != pdFALSE ){pxEventBits->uxEventBits &= ~uxBitsToWaitFor;}else{mtCOVERAGE_TEST_MARKER();}}else{mtCOVERAGE_TEST_MARKER();}}taskEXIT_CRITICAL();xTimeoutOccurred = pdFALSE;}else{/* The task unblocked because the bits were set. */}/* 返回当前事件标志位. */uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;}traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );return uxReturn;
}

3.4 事件标志组设置标志位

 

/*参数:1、事件控制块2、要设置的事件位返回值:1、当前事件标志位
*/
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
{
ListItem_t *pxListItem, *pxNext;
ListItem_t const *pxListEnd;
List_t *pxList;
EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
BaseType_t xMatchFound = pdFALSE;//获取事件列表头pxList = &( pxEventBits->xTasksWaitingForBits );//获取列表尾节点pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. *///挂起调度器vTaskSuspendAll();{//获取头节点pxListItem = listGET_HEAD_ENTRY( pxList );/* 设置事件标志位 */pxEventBits->uxEventBits |= uxBitsToSet;/* 循环遍历整个列表项,直到列表头节点等于尾节点(指针) */while( pxListItem != pxListEnd ){//获取下个列表项pxNext = listGET_NEXT( pxListItem );//获取当前列表项的值uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );//标记,是否找到需要处理的节点xMatchFound = pdFALSE;/* 拆分*/uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 ){//或逻辑/* 等待位已经置位 */if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 ){//找到了已经触发的节点xMatchFound = pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}}//表示所有等待的位都已经触发else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor ){/*找到触发的节点 */xMatchFound = pdTRUE;}else{/* Need all bits to be set, but not all the bits were set. */}if( xMatchFound != pdFALSE ){/* 是否需要清除 */if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 ){//做个标记uxBitsToClear |= uxBitsWaitedFor;}else{mtCOVERAGE_TEST_MARKER();}/* 把任务从事件列表中移除参数:	1、列表项2、事件标志位+解锁处理标志位  内部写入了列表项的value里面*/( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );}/* 当前列表项指向下个,继续遍历*/pxListItem = pxNext;}/* 清除设置后的标志位 */pxEventBits->uxEventBits &= ~uxBitsToClear;}//开启调度器( void ) xTaskResumeAll();return pxEventBits->uxEventBits;
}/*参数:1、事件控制块2、要设置的标志位3、NULL*/BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ){BaseType_t xReturn;//调用软件定时器函数,,用于发送消息到软件定时器任务,进行处理xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );return xReturn;}/*设置事件标志位的回调函数,内部其实就是调用xEventGroupSetBits*/void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ){( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );}BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ){DaemonTaskMessage_t xMessage;BaseType_t xReturn;/* 封装消息 */xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR;xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;//通过消息队列和软件定时器任务进行通信xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );/*分析:软件定时器任务要等待消息队列,之后解析处理,最终调用xEventGroupSetBits*/return xReturn;}

3.5 事件标志组任务同步

 待完成

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

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

相关文章

ESD接地实时监控系统有哪些功能

ESD接地实时监控系统是一种用于监测和维护静电放电&#xff08;ESD&#xff09;接地的设备和软件系统。静电放电事件可能会对敏感电子元件、设备或工作环境造成损害&#xff0c;因此对ESD接地进行有效的监控至关重要。 ESD接地实时监控系统主要包括以下几个方面的功能&#xf…

小程序的api使用 以及一些weui组件实列获取头像 扫码等

今日目标 响应式单位rpx小程序的生命周期 【重点】20%小程序框架 weui 【重点】 50%内置API 【重点】30%综合练习 1. 响应式rpx 1.1 rpx单位 rpx是微信小程序提出的一个尺寸单位&#xff0c;将整个手机屏幕宽度分为750份&#xff0c;1rpx 就是 1/750&#xff0c;避免不同手…

PCL 可视化球图形

文章目录 一、简介二、实现代码三、实现效果修改之处一、简介 过程很简单,使用pcl::visualization::PCLVisualizer中的addSphere函数就可以了,不过PCL中默认的球的分辨率过小,不够精细,需要我们手动修改一下源码。 二、实现代码 //标准文件 #include <iostream> #in…

QT自带PDF库的使用

QT自带PDF库可以方便的打开PDF文件&#xff0c;并将文件解析为QImage&#xff0c;相比网上提供的开源库&#xff0c;QT自带PDF库使用更方便&#xff0c;也更加可靠&#xff0c;然而&#xff0c;QT自带PDF库的使用却不同于其他通用库的使用&#xff0c;具备一定的技巧。 1. 安装…

以太网DHCP协议(十)

目录 一、工作原理 二、DHCP报文 2.1 DHCP报文类型 2.2 DHCP报文格式 当网络内部的主机设备数量过多是&#xff0c;IP地址的手动设置是一件非常繁琐的事情。为了实现自动设置IP地址、统一管理IP地址分配&#xff0c;TCPIP协议栈中引入了DHCP协议。 一、工作原理 使用DHCP之…

Go语言基础: Switch语句、Arrays数组、Slices切片 详细教程案例

文章目录 一. Switch语句1. Default case2. Multiple expressions in case3. Expressionless switch4. Fallthrough5. break6. break for loop 二. Arrays数组1. when arrays are passed to functions as parameters2. Iterating arrays using range3.Multidimensional arrays …

通向架构师的道路之weblogic与apache的整合与调优

一、BEAWeblogic的历史 BEA WebLogic是用于开发、集成、部署和管理大型分布式Web应用、 网络应用和数据库应 用的Java应用服务器。将Java的动态功能和Java Enterprise标准的安全性引入大型网络应用的 开发、集成、部署和管理之中。 BEA WebLogic Server拥有处理关键Web应…

title和h1、b与strong、i和em的区别

title 与 h1 的区别、b 与 strong 的区别、i 与 em 的区别&#xff1f; title 与 h1&#xff1a;h1 标签写在网页的 body 中&#xff0c;title 标签写在网页的 head 中&#xff0c;h1 标签控制一段文字的大小&#xff08;从 h1~h6&#xff09;&#xff0c;title 是网页标题的意…

pytorch求导

pytorch求导的初步认识 requires_grad tensor(data, dtypeNone, deviceNone, requires_gradFalse)requires_grad是torch.tensor类的一个属性。如果设置为True&#xff0c;它会告诉PyTorch跟踪对该张量的操作&#xff0c;允许在反向传播期间计算梯度。 x.requires_grad 判…

TM4C123库函数学习(1)--- 点亮LED+TM4C123的ROM函数简介+keil开发环境搭建

前言 &#xff08;1&#xff09; 首先&#xff0c;我们需要知道TM4C123是M4的内核。对于绝大多数人而言&#xff0c;入门都是学习STM32F103&#xff0c;这款芯片是采用的M3的内核。所以想必各位对M3内核还是有一定的了解。M4内核就是M3内核的升级版本&#xff0c;他继承了M3的的…

【力扣每日一题】2023.8.5 合并两个有序链表

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们两个有序的链表&#xff0c;要我们保持升序的状态合并它们。 我们可以马上想要把两个链表都遍历一遍&#xff0c;把所有节点的…

扫地机器人(dfs基础)

题面 Mike同学在为扫地机器人设计一个在矩形区域中行走的算法&#xff0c;Mike是这样设计的&#xff1a;先把机器人放在出发点 (1,1)(1,1) 点上&#xff0c;机器人在每个点上都会沿用如下的规则来判断下一个该去的点是哪里。规则&#xff1a;优先向右&#xff0c;如果向右不能走…

1-搭建一个最简单的验证平台UVM,已用Questasim实现波形!

UVM-搭建一个最简单的验证平台&#xff0c;已用Questasim实现波形 1&#xff0c;背景知识2&#xff0c;".sv"文件搭建的UVM验证平台&#xff0c;包括代码块分享3&#xff0c;Questasim仿真输出&#xff08;1&#xff09;compile all&#xff0c;成功&#xff01;&…

基于 CentOS 7 构建 LVS-DR 集群 及 配置nginx负载均衡

一、构建LVS-DR集群 1、主机规划 Node01&#xff1a;PC Node02&#xff1a;LVS Node03、Node04&#xff1a;Webserver 2、部署环境 2.1 在Node02上配置 2.1.1 安装ipvsadm管理软件按 [rootlocalhost ~]# yum install -y ipvsadm 2.1.2 配置VIP [rootlocalhost ~]# if…

【力扣每日一题】2023.8.8 任意子数组和的绝对值的最大值

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们一个数组&#xff0c;让我们找出它的绝对值最大的子数组的和。 这边的子数组是要求连续的&#xff0c;让我们找出一个元素之和…

GG修改器安装与Root环境的安装

关于GG修改器大家应该都有一定的了解吧&#xff0c;就是类似于电脑端CE的一个软件。 GG修改器在百度云盘里请自行下载&#xff01; 百度网盘链接&#xff1a;https://pan.baidu.com/s/1p3KJRg9oq4s0XzRuEIBH4Q 提取码&#xff1a;vuwj 那我要开始了&#xff01; 本来不想讲GG…

Spring Boot集成EasyPoi实现导入导出操作

文章目录 Spring Boot集成EasyPoi实现导入导出操作0 简要说明1 环境搭建1.1 项目目录1.2 依赖管理2.3 关于swagger处理2.4 关于切面处理耗时1 自定义注解2 定义切面类3 如何使用 2.5 核心导入操作2.6 核心导出操作 2 最佳实线2.1 导入操作1 实体类说明2 业务层3 效果3 控制层 2…

常用抓包工具

Fiddler Fiddler 是一个很好用的抓包工具&#xff0c;可以用于抓取http/https的数据包&#xff0c;常用于Windows系统的抓包&#xff0c;它有个优势就是免费 Charles Charles是由JAVA开发的&#xff0c;可以运行在window Linux MacOS&#xff0c;但它是收费的&#xff0c;和…

.Net Framework请求外部Api

要在.NET Framework 4.5中进行外部API的POST请求&#xff0c;你可以使用HttpClient类。 1. Post请求 using System; using System.Net.Http; using System.Threading.Tasks;class Program {static async Task Main(string[] args){// 创建一个HttpClient实例using (HttpClien…

Python取得系统进程列表

Python取得系统进程列表 上代码 上代码 import psutilfor proc in psutil.process_iter():try:pinfo proc.as_dict(attrs[pid, name])except psutil.NoSuchProcess:passelse:print(pinfo)