当前位置: 首页 > news >正文

15_FreeRtos计数信号量优先级翻转互斥信号量

目录

计数型信号量

计数型信号量相关API函数

计数型信号量实验源码

优先级翻转简介

优先级翻转实验源码

互斥信号量

互斥信号量相关API函数

互斥信号量实验源码


计数型信号量

计数型信号量相当于队列长度大于1的队列,因此计数型信号量能够容纳多个资源,这在计数型信号量被创建的时候确定的

计数型信号量适用场合:

事件计数

当每次事件发生后,在事件处理函数中释放计数型信号量(计数值+1) ,其他任务会获取计数型信号量(计数值-1),这种场合一般在创建时将初始计数值设置为 0

资源管理

信号量表示有效的资源数目。任务必须先获取信号量(信号量计数值-1)才能获取资源控制权。当计数值减为零时表示没有的资源。当任务使用完资源后,必须释放信号量(信号量计数值+1)信号量创建时计数值应等于最大资源数目

计数型信号量相关API函数

使用计数型信号量的过程:创建计数型信号量 → 释放信号量 → 获取信号量

 计数型信号量的释放和获取与二值信号量相同!

此函数用于创建一个计数型信号量。

#definexSemaphoreCreateCounting( uxMaxCount , uxInitialCount )  \
xQueueCreateCountingSemaphore( ( uxMaxCount), ( uxlnitialCount ))

此函数用于获取信号量当前计数值大小 

#defineuxSemaphoreGetCount( xSemaphore) \uxQueueMessagesWaiting( (QueueHandle_t) (xSemaphore ))

计数型信号量实验源码

将设计三个任务: start_task、task1、task2

start_task :用来创建task1和task2任务

Task1:用于按键扫描,当检测到按键KEY0被按下时,释放计数型信号量

task2:每过一秒获取一次计数型信号量,当成功获取后打印信号量计数值

/********************************************************************************* @file           : user_mian.h* @brief          : V1.00******************************************************************************* @attention********************************************************************************//* Include 包含---------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdbool.h>
#include "user_gpio.h"
#include "user_delay.h"
#include "user_rcc_config.h"
#include "user_uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "user_key.h"
/* Typedef 类型----------------------------------------------------------------*/
/* Define  定义----------------------------------------------------------------*/
/* Macro   宏------------------------------------------------------------------*/
/*二值信号量句柄*/
QueueHandle_t count_semphore_handle;
/* Variables 变量--------------------------------------------------------------*/ 
/* Constants 常量--------------------------------------------------------------*/
/* Function  函数--------------------------------------------------------------*///任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);//任务优先级
#define TASK1_PRIO			3
//任务堆栈大小	
#define TASK1_STK_SIZE 		100  
//任务句柄
TaskHandle_t Task1_Handler;
//任务函数
void task1(void *pvParameters);//任务优先级
#define TASK2_PRIO			3
//任务堆栈大小	
#define TASK2_STK_SIZE 		100  
//任务句柄
TaskHandle_t Task2_Handler;
//任务函数
void task2(void *pvParameters);int main(void){	/*配置系统中断分组为4位抢占*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);/*延时函数初始化*/delay_init();/*RCC配置*/Rcc_config();/*GPIO初始化*/ Gpio_Init();/*USART1初始化*/Uart1_Init(9600);/*创建计数型信号量最大值100,初始化值为0*/count_semphore_handle = xSemaphoreCreateCounting(100,0); if(count_semphore_handle != NULL){printf("计数型信号量创建成功初始值为0\r\n\r\n");}/*创建开始任务*/xTaskCreate((TaskFunction_t )start_task,            //任务函数(const char*    )"start_task",          //任务名称(uint16_t       )START_STK_SIZE,        //任务堆栈大小(void*          )NULL,                  //传递给任务函数的参数(UBaseType_t    )START_TASK_PRIO,       //任务优先级(TaskHandle_t*  )&StartTask_Handler);   //任务句柄              vTaskStartScheduler();          //开启任务调度}/*!\brief		开始任务函数\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           //进入临界区//创建任务1xTaskCreate((TaskFunction_t )task1,     	(const char*    )"task1",   	(uint16_t       )TASK1_STK_SIZE, (void*          )NULL,				(UBaseType_t    )TASK1_PRIO,	(TaskHandle_t*  )&Task1_Handler);   //创建任务2xTaskCreate((TaskFunction_t )task2,     (const char*    )"task2",   (uint16_t       )TASK2_STK_SIZE, (void*          )NULL,(UBaseType_t    )TASK2_PRIO,(TaskHandle_t*  )&Task2_Handler); vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}/*!\brief		task1释放计数型信号量\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void task1(void *pvParameters)
{uint8_t key = 0;while(1){	/*获取按键值*/key = Key_Scan(0);if(key == KEY0_PRES){if(count_semphore_handle != NULL){					 if(xSemaphoreGive(count_semphore_handle)){taskENTER_CRITICAL();           //进入临界区printf("计数型信号量释放成功当前值为%d\r\n\r\n",(int)uxSemaphoreGetCount(count_semphore_handle));taskEXIT_CRITICAL();            //退出临界区}}		}vTaskDelay(10);}
} /*!\brief		task2获取计数型信号量\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void task2(void *pvParameters)
{BaseType_t err;while(1){/*获取信号量死等,进入阻塞态*/err = xSemaphoreTake(count_semphore_handle,portMAX_DELAY);	if(err == pdTRUE){taskENTER_CRITICAL();           //进入临界区	printf("信号量的计数值为:%d\r\n\r\n",(int)uxSemaphoreGetCount(count_semphore_handle));		taskEXIT_CRITICAL();            //退出临界区}vTaskDelay(1000);}
}/************************************************************** END OF FILE ****/

 

优先级翻转简介

优先级翻转:高优先级的任务反而慢执行,低优先级的任务反而优先执行

优先级翻转在抢占式内核中是非常常见的,但是在实时操作系统中是不允许出现优先级翻转的,因为优先级翻转会破坏任务的预期顺序,可能会导致未知的严重后果。

在使用二值信号量的时候,经常会遇到优先级翻转的问题。

举例:

任务H 优先级最高 任务M优先级中等  任务L优先级最低

假设任务L正在运行获取了信号量,其他2任务在阻塞状态,此时任务H就绪抢占了任务L,任务H也是获取信号量,发现信号量没有了进入阻塞态,继续执行任务L(优先级翻转了),然后任务M就绪抢占了任务L,任务M执行完后,进入阻塞态,任务H一直在等信号量所以一直在阻塞态,任务L继续运行,直到释放了信号量后,任何H才会从阻塞态变成就绪态执行。

高优先级任务被低优先级任务阻塞,导致高优先级任务迟迟得不到调度,但其他中等优先级的任务却能抢到CPU资源。从现象上看,就像是中优先级的任务比高优先级任务具有更高的优先权(即优先级翻转)

优先级翻转实验源码

在使用二值信号量的时候会存在优先级翻转的问题,本实验通过模拟的方式实现优先级翻转,观察优先级翻转对抢占式内核的影响

将设计四个任务:start_task、high_task、middle_task, low_task

start_task:用来创建其它任务

high_task:高优先级任务,会获取二值信号量,获取成功以后打印提示信息,处理完后释放信号量

middle_task:中等优先级任务,简单的应用任务

low_task:低优先级任务,同高优先级一样的操作,不同的是低优先级任务占用信号量的时间久一点

/********************************************************************************* @file           : user_mian.h* @brief          : V1.00******************************************************************************* @attention********************************************************************************//* Include 包含---------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdbool.h>
#include "user_gpio.h"
#include "user_delay.h"
#include "user_rcc_config.h"
#include "user_uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "user_key.h"
/* Typedef 类型----------------------------------------------------------------*/
/* Define  定义----------------------------------------------------------------*/
/* Macro   宏------------------------------------------------------------------*/
/*二值信号量句柄*/
QueueHandle_t semphore_handle;
/* Variables 变量--------------------------------------------------------------*/ 
/* Constants 常量--------------------------------------------------------------*/
/* Function  函数--------------------------------------------------------------*///任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);//任务优先级
#define HIGH_PRIO			4
//任务堆栈大小	
#define HIGH_STK_SIZE 		100  
//任务句柄
TaskHandle_t HIGH_Handler;
//任务函数
void high_task(void *pvParameters);//任务优先级
#define MIDDLE_PRIO			3
//任务堆栈大小	
#define MIDDLE_STK_SIZE 		100  
//任务句柄
TaskHandle_t MIDDLE_Handler;
//任务函数
void middle_task(void *pvParameters);//任务优先级
#define LOW_PRIO			2
//任务堆栈大小	
#define LOW_STK_SIZE 		100  
//任务句柄
TaskHandle_t LOW_Handler;
//任务函数
void low_task(void *pvParameters);int main(void){	/*配置系统中断分组为4位抢占*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);/*延时函数初始化*/delay_init();/*RCC配置*/Rcc_config();/*GPIO初始化*/ Gpio_Init();/*USART1初始化*/Uart1_Init(9600);/*创建二值信号量*/semphore_handle = xSemaphoreCreateBinary(); if(semphore_handle == NULL){printf("二值信号量创建不成功\r\n\r\n");}else{printf("二值信号量创建成功\r\n\r\n");}/*二值释放信号量*/xSemaphoreGive(semphore_handle);/*创建开始任务*/xTaskCreate((TaskFunction_t )start_task,            //任务函数(const char*    )"start_task",          //任务名称(uint16_t       )START_STK_SIZE,        //任务堆栈大小(void*          )NULL,                  //传递给任务函数的参数(UBaseType_t    )START_TASK_PRIO,       //任务优先级(TaskHandle_t*  )&StartTask_Handler);   //任务句柄              vTaskStartScheduler();          //开启任务调度}/*!\brief		开始任务函数\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           //进入临界区//创建高优先级任务xTaskCreate((TaskFunction_t )high_task,     	(const char*    )"high_task",   	(uint16_t       )HIGH_STK_SIZE, (void*          )NULL,				(UBaseType_t    )HIGH_PRIO,	(TaskHandle_t*  )&HIGH_Handler);   //创建中优先级任务xTaskCreate((TaskFunction_t )middle_task,     (const char*    )"middle_task",   (uint16_t       )MIDDLE_STK_SIZE, (void*          )NULL,(UBaseType_t    )MIDDLE_PRIO,(TaskHandle_t*  )&MIDDLE_Handler); //创建低优先级任务xTaskCreate((TaskFunction_t )low_task,     (const char*    )"low_task",   (uint16_t       )LOW_STK_SIZE, (void*          )NULL,(UBaseType_t    )LOW_PRIO,(TaskHandle_t*  )&LOW_Handler); vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}/*!\brief		高优先级任务\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void high_task(void *pvParameters)
{while(1){	taskENTER_CRITICAL();           //进入临界区printf("high_task获取信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区/*获取二值信号量,并死等方式*/xSemaphoreTake(semphore_handle,portMAX_DELAY);taskENTER_CRITICAL();           //进入临界区printf("high_task正在运行\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区delay_xms(1000);/*释放二值信号量*/taskENTER_CRITICAL();           //进入临界区printf("high_task释放信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区xSemaphoreGive(semphore_handle);vTaskDelay(10);}
} /*!\brief		中优先级任务\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void middle_task(void *pvParameters)
{while(1){taskENTER_CRITICAL();           //进入临界区printf("middle_task正在运行\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区vTaskDelay(1000);}
}/*!\brief		低优先级任务\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void low_task(void *pvParameters)
{while(1){    taskENTER_CRITICAL();           //进入临界区printf("low_task获取信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区/*获取二值信号量,并死等方式*/xSemaphoreTake(semphore_handle,portMAX_DELAY);taskENTER_CRITICAL();           //进入临界区		printf("low_task正在运行\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区delay_xms(3000);/*释放二值信号量*/taskENTER_CRITICAL();           //进入临界区printf("low_task释放信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区xSemaphoreGive(semphore_handle);vTaskDelay(1000);		}}/************************************************************** END OF FILE ****/

互斥信号量

互斥信号量其实就是一个拥有优先级继承的二值信号量,在同步的应用中二值信号量最适合。互斥信号量适合用于那些需要互斥访问的应用中!

优先级继承:当一个互斥信号量正在被一个低优先级的任务持有时,如果此时有个高优先级的任务也尝试获取这个互斥信号量,那么这个高优先级的任务就会被阻塞。不过这个高优先级的任务会将低优先级任务的优先级提升到与自己相同的优先级。

 此时任务H的阻塞时间仅仅是任务L的执行时间,将优先级翻转的危害降到了最低

优先级继承并不能完全的消除优先级翻转的问题,它只是尽可能的降低优先级翻转带来的影响

注意:互斥信号量不能用于中断服务函数中,原因如下:

  1. 互斥信号量有任务优先级继承的机制,但是中断不是任务,没有任务优先级,所以互斥信号量只能用与任务中,不能用于中断服务函数。
  2. 中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态。

互斥信号量相关API函数

使用互斥信号量:首先将宏configUSE_MUTEXES置一

使用流程:创建互斥信号量→ (task)获取信号量→ (give)释放信号量

创建互斥信号量函数

 互斥信号量的释放和获取函数与二值信号量相同!只不过互斥信号量不支持中断中调用

注意:创建互斥信号量时,会主动释放一次信号量

#define xSemaphoreCreateMutex()  xQueueCreateMutex( queueQUEUE_TYPE_MUTEX)

此函数用于创建互斥信号量

互斥信号量实验源码

在优先级翻转实验的基础,加入互斥信号量,解决优先级翻转问题

/********************************************************************************* @file           : user_mian.h* @brief          : V1.00******************************************************************************* @attention********************************************************************************//* Include 包含---------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdbool.h>
#include "user_gpio.h"
#include "user_delay.h"
#include "user_rcc_config.h"
#include "user_uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "user_key.h"
/* Typedef 类型----------------------------------------------------------------*/
/* Define  定义----------------------------------------------------------------*/
/* Macro   宏------------------------------------------------------------------*/
/*二值信号量句柄*/
QueueHandle_t mutex_semphore_handle;
/* Variables 变量--------------------------------------------------------------*/ 
/* Constants 常量--------------------------------------------------------------*/
/* Function  函数--------------------------------------------------------------*///任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);//任务优先级
#define HIGH_PRIO			4
//任务堆栈大小	
#define HIGH_STK_SIZE 		100  
//任务句柄
TaskHandle_t HIGH_Handler;
//任务函数
void high_task(void *pvParameters);//任务优先级
#define MIDDLE_PRIO			3
//任务堆栈大小	
#define MIDDLE_STK_SIZE 		100  
//任务句柄
TaskHandle_t MIDDLE_Handler;
//任务函数
void middle_task(void *pvParameters);//任务优先级
#define LOW_PRIO			2
//任务堆栈大小	
#define LOW_STK_SIZE 		100  
//任务句柄
TaskHandle_t LOW_Handler;
//任务函数
void low_task(void *pvParameters);int main(void){	/*配置系统中断分组为4位抢占*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);/*延时函数初始化*/delay_init();/*RCC配置*/Rcc_config();/*GPIO初始化*/ Gpio_Init();/*USART1初始化*/Uart1_Init(9600);/*创建互斥信号量,默认释放一次*/mutex_semphore_handle = xSemaphoreCreateMutex(); if(mutex_semphore_handle == NULL){printf("互斥信号量创建不成功\r\n\r\n");}else{printf("互斥信号量创建成功\r\n\r\n");}/*创建开始任务*/xTaskCreate((TaskFunction_t )start_task,            //任务函数(const char*    )"start_task",          //任务名称(uint16_t       )START_STK_SIZE,        //任务堆栈大小(void*          )NULL,                  //传递给任务函数的参数(UBaseType_t    )START_TASK_PRIO,       //任务优先级(TaskHandle_t*  )&StartTask_Handler);   //任务句柄              vTaskStartScheduler();          //开启任务调度}/*!\brief		开始任务函数\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           //进入临界区//创建高优先级任务xTaskCreate((TaskFunction_t )high_task,     	(const char*    )"high_task",   	(uint16_t       )HIGH_STK_SIZE, (void*          )NULL,				(UBaseType_t    )HIGH_PRIO,	(TaskHandle_t*  )&HIGH_Handler);   //创建中优先级任务xTaskCreate((TaskFunction_t )middle_task,     (const char*    )"middle_task",   (uint16_t       )MIDDLE_STK_SIZE, (void*          )NULL,(UBaseType_t    )MIDDLE_PRIO,(TaskHandle_t*  )&MIDDLE_Handler); //创建低优先级任务xTaskCreate((TaskFunction_t )low_task,     (const char*    )"low_task",   (uint16_t       )LOW_STK_SIZE, (void*          )NULL,(UBaseType_t    )LOW_PRIO,(TaskHandle_t*  )&LOW_Handler); vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}/*!\brief		高优先级任务\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void high_task(void *pvParameters)
{while(1){	taskENTER_CRITICAL();           //进入临界区printf("high_task获取信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区/*获取二值信号量,并死等方式*/xSemaphoreTake(mutex_semphore_handle,portMAX_DELAY);taskENTER_CRITICAL();           //进入临界区printf("high_task正在运行\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区delay_xms(1000);/*释放二值信号量*/taskENTER_CRITICAL();           //进入临界区printf("high_task释放信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区xSemaphoreGive(mutex_semphore_handle);vTaskDelay(10);}
} /*!\brief		中优先级任务\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void middle_task(void *pvParameters)
{while(1){taskENTER_CRITICAL();           //进入临界区printf("middle_task正在运行\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区vTaskDelay(1000);}
}/*!\brief		低优先级任务\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void low_task(void *pvParameters)
{while(1){    taskENTER_CRITICAL();           //进入临界区printf("low_task获取信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区/*获取二值信号量,并死等方式*/xSemaphoreTake(mutex_semphore_handle,portMAX_DELAY);taskENTER_CRITICAL();           //进入临界区		printf("low_task正在运行\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区delay_xms(3000);/*释放二值信号量*/taskENTER_CRITICAL();           //进入临界区printf("low_task释放信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区xSemaphoreGive(mutex_semphore_handle);vTaskDelay(1000);		}}/************************************************************** END OF FILE ****/

相关文章:

15_FreeRtos计数信号量优先级翻转互斥信号量

目录 计数型信号量 计数型信号量相关API函数 计数型信号量实验源码 优先级翻转简介 优先级翻转实验源码 互斥信号量 互斥信号量相关API函数 互斥信号量实验源码 计数型信号量 计数型信号量相当于队列长度大于1的队列&#xff0c;因此计数型信号量能够容纳多个资源,这在…...

二叉树(一)

二叉树&#xff08;一&#xff09;1.树的概念2.树的相关概念3.树的表示4.树在实际中的运用5.二叉树概念及结构6.特殊的二叉树7.二叉树的性质&#x1f31f;&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f;&#x1f31f; &#x1f680;&#x1f680;系列专栏…...

【SCL】1200案例:天塔之光数码管显示液体混合水塔水位

使用scl编写天塔之光&数码管显示&液体混合&水塔水位 文章目录 目录 文章目录 前言 一、案例1&#xff1a;天塔之光 1.控制要求 2.编写程序 3.效果 二、案例2&#xff1a;液体混合 1.控制要求 2.编写程序 三、案例3&#xff1a;数码管显示 1.控制要求 2.编写程序 3…...

5.1配置IBGP和EBGP

5.2.1实验1&#xff1a;配置IBGP和EBGP 实验目的 熟悉IBGP和EBGP的应用场景掌握IBGP和EBGP的配置方法 实验拓扑 实验拓扑如图5-1所示&#xff1a; 图5-1&#xff1a;配置IBGP和EBGP 实验步骤 IP地址的配置 R1的配置 <Huawei>system-view Enter system view, return …...

c++中超级详细的一些知识,新手快来

目录 2.文章内容简介 3.理解虚函数表 3.1.多态与虚表 3.2.使用指针访问虚表 4.对象模型概述 4.1.简单对象模型 4.2.表格驱动模型 4.3.非继承下的C对象模型 5.继承下的C对象模型 5.1.单继承 5.2.多继承 5.2.1一般的多重继承&#xff08;非菱形继承&#xff09; 5.2…...

[答疑]经营困难时期谈建模和伪创新-长点心和长点良心

leonll 2022-11-26 9:53 我们今年真是太难了……&#xff08;此处删除若干字&#xff09;……去年底就想着邀请您来给我们讲课&#xff0c;现在也没有实行。我想再和我们老大提&#xff0c;您觉得怎么说个关键理由&#xff0c;这样的形势合适引进UML开发流程&#xff1f; UML…...

计算机基础知识

计算机网络的拓扑结构 一、OSI 7层网络模型是指什么&#xff1f; 7层分别是什么&#xff1f;每层的作用是什么&#xff1f; OSI7层模型是 国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系。 每层功能:&#xff08;自底向上&#xff09; 物理层:建立、…...

Java爬虫—WebMagic

一&#xff0c;WebMagic介绍WebMagic企业开发&#xff0c;比HttpClient和JSoup更方便一&#xff09;&#xff0c;WebMagic架构介绍WebMagic有DownLoad&#xff0c;PageProcessor&#xff0c;Schedule&#xff0c;Pipeline四大组件&#xff0c;并有Spider将他们组织起来&#xf…...

[软件工程导论(第六版)]第2章 可行性研究(复习笔记)

文章目录2.1 可行性研究的任务2.2 可行性研究过程2.3 系统流程图2.4 数据流图概念2.5 数据字典2.6 成本/效益分析2.1 可行性研究的任务 可行性研究的目的 用最小的代价在尽可能短的时间内确定问题是否能够解决。 可行性研究的3个方面 &#xff08;1&#xff09;技术可行性&…...

Mac下安装Tomcat以及IDEA中的配置

安装brew 打开终端输入以下命令&#xff1a; /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 搜索tomcat版本&#xff0c;输入以下命令&#xff1a; brew search tomcat 安装自己想要的版本&#xff0c;例…...

【Linux详解】——文件基础(I/O、文件描述符、重定向、缓冲区)

&#x1f4d6; 前言&#xff1a;本期介绍文件基础I/O。 目录&#x1f552; 1. 文件回顾&#x1f558; 1.1 基本概念&#x1f558; 1.2 C语言文件操作&#x1f564; 1.2.1 概述&#x1f564; 1.2.2 实操&#x1f564; 1.2.3 OS接口open的使用&#xff08;比特位标记&#xff09;…...

HomMat2d

1.affine_trans_region&#xff08;区域的任意变换&#xff09; 2.hom_mat2d_identity&#xff08;创建二位变换矩阵&#xff09; 3.hom_mat2d_translate&#xff08;平移&#xff09; 4.hom_mat2d_scale&#xff08;缩放&#xff09; 5.hom_mat2d_rotate&#xff08;旋转 &…...

Python3 JSON 数据解析

Python3 JSON 数据解析 JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。 Python3 中可以使用 json 模块来对 JSON 数据进行编解码&#xff0c;它包含了两个函数&#xff1a; json.dumps(): 对数据进行编码。json.loads(): 对数据进行解码。 在 json 的编解码…...

Homebrew 安装遇到的问题

Homebrew 安装遇到的问题 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 文章目录Homebrew 安装遇到的问题前言一、安装二、遇到的问题1.提示 zsh: command not found: brew三、解决问题前言 使用 Homebrew 能够 安装 Apple&#xff08;或您的 Linux 系统&#…...

Metasploit框架基础(二)

文章目录前言一、Meatsplooit的架构二、目录结构datadocumentationlibmodulesplugins三、Measploit模块四、Metasploit的使用前言 Metasploit是用ruby语言开发的&#xff0c;所以你打开软件目录&#xff0c;会发现很多.rb结尾的文件。ruby是一门OOP的语言。 一、Meatsplooit的…...

c++容器

1、vector容器 1.1性质 a&#xff09;该容器的数据结构和数组相似&#xff0c;被称为单端数组。 b&#xff09;在存储数据时不是在原有空间上往后拓展&#xff0c;而是找到一个新的空间&#xff0c;将原数据深拷贝到新空间&#xff0c;释放原空间。该过程被称为动态拓展。 vec…...

Vue.js如何实现对一千张图片进行分页加载?

目录 vue处理一千张图片进行分页加载 分页加载、懒加载---概念介绍&#xff1a; 思路&#xff1a; 开发过程中&#xff0c;如果后端一次性返回你1000多条图片或数据&#xff0c;那我们前端应该怎么用什么思路去更好的渲染呢&#xff1f; 第一种&#xff1a;我们可以使用分页…...

计算机网络复习(六)

考点&#xff1a;MIME及其编码&#xff08;base64,quoted-printable)网络协议http是基于什么协议&#xff0c;应用层到网络层基于什么协议6-27.试将数据 11001100 10000001 00111000 进行 base64 编码&#xff0c;并得到最后传输的 ASCII 数据。答&#xff1a;先将 24 比特的二…...

Redis进阶:布隆过滤器(Bloom Filter)及误判率数学推导

1 缘起 有一次偶然间听到有同事在说某个项目中使用了布隆过滤器&#xff0c; 哎呦&#xff0c;我去&#xff0c;我竟然不知道啥是布隆过滤器&#xff0c; 这我哪能忍&#xff1f;其实&#xff0c;也可以忍&#xff0c;但是&#xff0c;可能有的面试官不能忍&#xff01;&#…...

Java创建对象的方式

Java创建对象的五种方式&#xff1a; &#xff08;1&#xff09;使用new关键字 &#xff08;2&#xff09;使用Object类的clone方法 &#xff08;3&#xff09;使用Class类的newInstance方法 &#xff08;4&#xff09;使用Constructor类中的newInstance方法 &#xff08;5&am…...

dom基本操作

1、style修改样式 基本语法&#xff1a; 元素.style.样式’值‘ 注意: 1.修改样式通过style属性引出 2.如果属性有-连接符&#xff0c;需要转换为小驼峰命名法 3.赋值的时候&#xff0c;需要的时候不要忘记加css单位 4.后面的值必须是字符串 <div></div> // 1、…...

如何将python训练的XGBoost模型部署在C++环境推理

当前环境&#xff1a;Ubuntu&#xff0c;xgboost1.7.4过程介绍&#xff1a;首先用python训练XGBoost模型&#xff0c;在训练完成后注意使用xgb_model.save_model(checkpoint.model)进行模型的保存。找到xgboost的动态链接库和头文件动态链接库&#xff1a;如果你在conda环境下面…...

About Oracle Database Performance Method

bottleneck&#xff08;瓶颈&#xff09;&#xff1a; a point where resource contention is highest throughput(吞吐量)&#xff1a; the amount of work that can be completed in a specified time. response time (响应时间)&#xff1a; the time to complete a spec…...

JavaScript 日期和时间的格式化大汇总(收集)

一、日期和时间的格式化 1、原生方法 1.1、使用 toLocaleString 方法 Date 对象有一个 toLocaleString 方法&#xff0c;该方法可以根据本地时间和地区设置格式化日期时间。例如&#xff1a; const date new Date(); console.log(date.toLocaleString(en-US, { timeZone: …...

【Python】缺失值可视化工具库:missingno

文章目录一、前言二、下载二、使用介绍2.1 绘制缺失值条形图2.2 绘制缺失值热力图2.3 缺失值树状图三、参考资料一、前言 在我们进行机器学习或者深度学习的时候&#xff0c;我们经常会遇到需要处理数据集缺失值的情况&#xff0c;那么如何可视化数据集的缺失情况呢&#xff1…...

【代码随想录二刷】Day18-二叉树-C++

代码随想录二刷Day18 今日任务 513.找树左下角的值 112.路径总和 113.路径总和ii 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树 语言&#xff1a;C 513.找树左下角的值 链接&#xff1a;https://leetcode.cn/problems/find-bottom-left-tree-va…...

制造业的云ERP在外网怎么访问?内网服务器一步映射到公网

随着企业信息化、智能化时代的到来&#xff0c;很多制造业企业都在用云ERP。用友U 9cloud通过双版本公有云专属、私有云订阅、传统软件购买三种模式满足众多制造业企业的需求&#xff0c;成为一款适配中型及中大型制造业的云ERP&#xff0c;是企业数智制造的创新平台。 用友U 9…...

zookeeper 复习 ---- 练习

zookeeper 复习 ---- 练习在同一节点配置三个 zookeeper&#xff0c;配置正确的是&#xff1f; A&#xff1a; zoo1.cfg tickTime2000 initLimit5 syncLimit2 dataDir/var/lib/zookeeper/zoo1 clientPort2181 server.1localhost:2666:3666 server.2localhost:2667:3667 serv…...

2023年全国最新道路运输从业人员精选真题及答案1

百分百题库提供道路运输安全员考试试题、道路运输从业人员考试预测题、道路安全员考试真题、道路运输从业人员证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 11.在以下选项中关于安全生产管理方针描述正确的是&#xff08;…...

Java每日一练——Java简介与基础练习

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 文章目录 目录 系列文章目录 文章目录 前言 一、简述解释型语言与编译型语言 二、Java语言的执行流程 2.1、…...

wordpress实现伪静态/上海短视频推广

前几天有网友问在输入坐标或长度的时候是否能输入公式&#xff0c;比如20/3或7*8这样简单的算式。cad虽然在定位点或长度时不能直接输入算式&#xff0c;但利用计算器功能不仅可以输入数字的算式&#xff0c;还可以输入点之前的算式&#xff0c;点可以是直接拾取的点&#xff0…...

建个可以注册会员网站多少钱/b2b平台有哪些网站

一、光盘重装系统步骤1、启动计算机&#xff0c;屏幕上出现 Press Del to Enter BIOS Setup&#xff0c;按住“DEL”。2、出现BIOS设置窗口&#xff1a;点击“Advance BIOS Features”&#xff0c;点击“enter”。3、点击“First Boot Derive”&#xff0c;点击“Page Up”或“…...

企业英文网站建设的重要性/百度账户推广登陆

电话号码的字母组合 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例 1&#xff1a; 输入&#xff1a;digits “2…...

上网站建设公司/百度云搜索引擎官网入口

有时根据题意需得根据输入的二维数来动态的创建二维数组&#xff0c;那么此时就不能想以前一样直接定义多少行多少列了。因为不知道行列多少&#xff0c;假如设定太大浪费空间&#xff0c;申请太小完成不了程序的数据存储。因此需要合理的开辟二维空间。以下的两种方法都可以建…...

wordpress 3.6 下载/网站推广策划案

分析&#xff1a;这题和POJ 2492差不多&#xff0c;所以我用的是并查集&#xff0c;可以把题意理解为有很多人&#xff0c;要分成两个帮派&#xff0c;每个帮派至少有1个人&#xff0c;输入n,m分别代表n个人&#xff0c;和m对有冲突的人&#xff0c;有冲突的不能在一个帮派里&a…...

企业管理咨询报告案例/北京seo供应商

localhost变更为ip地址原因 移动端的开发页面想要在手机端查看&#xff0c;使用localhost是无法查看的只有使用IP地址才可以通过本机IP访问该页面&#xff0c;查看页面效果 变更方法 查看本机 IP 地址 调出cmd命令行&#xff0c;输入cmd按enter键 输入ipconfig 获取本机i…...