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

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

  • 1. 信号量
  • 2. 二值信号量
  • 3. 相关API函数
    • 3.1 创建二值信号量
    • 3.2 获取信号量
    • 3.3 释放信号量
    • 3.4 删除信号量
  • 4. 二值信号量操作实验
    • 1. 实验内容
    • 2. 代码实现:
    • 3. 运行结果

上一期我们学习了FreeRTOS中的队列,这一期我们学习信号量中的——二值信号量

1. 信号量

在学习信号量之前,我们先来回顾一下队列:

  • 队列:队列是一种任务到任务、任务到中断、中断到任务数据交流的一种机制、

随之,我们给出信号量的定义:

  • 信号量:信号量是一种解决同步问题的机制,可以实现对共享资源的有序访问。其中,“同步”指的是任务间的同步,即信号量可以使得一个任务等待另一个任务完成某件事情后,才继续执行;而“有序访问”指的是对被多任务或中断访问的共享资源(如全局变量)的管理,当一个任务在访问(读取或写入)一个共享资源时,信号量可以防止其他任务或中断在这期间访问(读取或写入)这个共享资源。

我们来举一个简单的例子,比如说现在有一个停车场,停车场上有5个车位,如果现在小明需要去停车,那么他应该先要看一下是否还有车位(判断信号量是否有资源),如果有车位,就直接停车(获取信号成功,这个时候车位-1),如果没有车位,那么可以直接选择不停车(获取信号量失败),或者原地等待(任务阻塞),直到有人开车出停车场(释放信号量,车位+1)。

在上述的例子中:一共5个车位(信号资源数为5),有人开出停车场,信号量释放,信号量计数值(资源数)加1,反之则减1。

  • 因为有5个车位,计数值最大值为5,所以这个是计数信号量。
  • 如果只有一个车位,那么计数值只有0和1,这个就是二值信号量。
  • 类似的,还有互斥信号量,这个我们后面会一一介绍。

下面我们来看一下队列和信号量的对比

队列信号量
可以容纳多个数据;创建队列有两部分内存:队列结构体+队列项存储空间仅存放计数值,无法存放其他数据;创建信号量,只需分配信号量结构体
写入队列:当队列满时,可阻塞;释放信号量:不可阻塞,计数值++,当计数值为最大值时,返回失败
读取队列:当队列为空时,可阻塞;获取信号量:计数值–,当没有资源时,可阻塞

2. 二值信号量

二值信号量是信号量的一种,前面我们提到过,信号量是基于队列实现的,二值信号量也是一样,二值信号量实际上就是一个队列长度为 1 的队列,队列中只有空和满两种情况,常用于互斥访问和任务同步,与互斥信号量比较类似,但是二值信号量可能会导致优先级翻转的问题(关于优先级翻转,我们稍后做出介绍),所以二值信号量更适合用于同步。
在这里插入图片描述

优先级翻转问题:当一个高优先级任务因获取一个被低优先级任务获取而处于没有资源状态的二值信号量时,这个高优先级的任务将被阻塞,直到低优先级的任务释放二值信号量,而在这之前,如果有一个优先级介于这个高优先级任务和低优先级任务之间的任务就绪,那么这个中等优先级的任务就会抢占低优先级任务的运行,这么一来,这三个任务中优先级最高的任务反而要最后才运行,这就是二值信号量带来的优先级翻转问题。

以上就是二值信号量的内容,下面我们看二值信号量的相关API函数

3. 相关API函数

常用的二值信号量API函数如下表:

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

3.1 创建二值信号量

  1. xSemaphoreCreateBinary()

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

#define xSemaphoreCreateBinary() \xQueueGenericCreate( ( UBaseType_t ) 1, \semSEMAPHORE_QUEUE_ITEM_LENGTH, \queueQUEUE_TYPE_BINARY_SEMAPHORE)

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

/*** @brief       xSemaphoreCreateBinary* @param       无* @retval      返回值为NULL,表示创建失败,其他值表示为创建二值信号量的句柄*/
SemaphoreHandle_t xSemaphoreCreateBinary( void );
  1. xSemaphoreCreateBinaryStatic()
    此函数用于静态方式创建二值信号量,创建二值信号量所需要的内存,需要用户手动分配,该函数实际上是一个宏定义,在semphr.h文件中有定义,具体的代码如下:
#define xSemaphoreCreateBinaryStatic(pxStaticSemaphore) \xQueueGenericCreateStatic( ( UBaseType_t ) 1, \semSEMAPHORE_QUEUE_ITEM_LENGTH, \NULL, \pxStaticSemaphore, \queueQUEUE_TYPE_BINARY_SEMAPHORE)

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

/*** @brief       xSemaphoreCreateBinaryStatic* @param       pxSemaphoreBuffer:必须指向 StaticSemaphore_t 类型的变量,该变量将用于保存信号量的状态。* @retval      返回值为NULL,表示创建失败,其他值表示为创建二值信号量的句柄*/
SemaphoreHandle_t xSemaphoreCreateBinaryStatic(StaticSemaphore_t *pxSemaphoreBuffer );

3.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() 只能用来获取二值信号量和计数信号量,不能用于互斥信号量。

3.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 () 只能用来释放二值信号量和计数信号量,不能用于互斥信号量。因为互斥信号量会有优先级继承的处理,而中断不属于任务,没有办法进行优先级继承。

3.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 );

4. 二值信号量操作实验

1. 实验内容

在STM32F103RCT6上允许FreeRTOS,通过按键控制,完成对应的队列读写,具体要求如下:

  • 定义一个二值信号量,
  • 定义任务1:每次按下按键0,释放信号量
  • 定义任务2:获取二值信号量

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);					/*任务函数*/QueueHandle_t SemaphoreBinary;				/* 定义二值信号量 *//******************************************************************************************************//*** @brief       FreeRTOS例程入口函数* @param       无* @retval      无*/
void freertos_demo(void)
{taskENTER_CRITICAL();           /* 进入临界区,关闭中断,此时停止任务调度*/SemaphoreBinary = xSemaphoreCreateBinary();if(SemaphoreBinary != 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* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task1(void *pvParameters)
{while(1){Key_One_Scan(Key_Name_Key0,Key0_Up_Task,Key0_Down_Task);		/* 按键0扫描,按下后释放二值信号量 */}
}	
/*** @brief       task2* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task2(void *pvParameters)	
{	BaseType_t errMessage;		/* 错误信息 */while(1){	errMessage = xSemaphoreTake(SemaphoreBinary,portMAX_DELAY);		/* 获取二值信号量 */if(errMessage == pdTRUE)	{printf("获取信号量成功\r\n");}else{printf("获取信号量失败\r\n");}}
}
  1. key.c
/* USER CODE BEGIN 2 */#include "freertos_demo.h"
#include "key.h"
#include "usart.h"extern QueueHandle_t SemaphoreBinary;				/* 声明外部的二值信号量 */void Key0_Down_Task(void)
{BaseType_t errMessage;		/* 错误信息 */errMessage = xSemaphoreGive(SemaphoreBinary);	/* 释放二值信号量 */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 */

3. 运行结果

在这里插入图片描述

这里解释一下,为什么按键0按下,先出现获取信号量成功,而不是直接打印二值信号量释放成功:

  • 在按键0没有按下之前,任务2处于阻塞状态,
  • 按键0按下之后,信号量释放,任务2立刻进入就绪状态。
  • 由于任务2的优先级比任务1高,所以先会立刻获取信号量,并打印获取信号量成功
  • 答应成功后,任务2再次进入阻塞,进入任务1,打印二值信号量释放成功。

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

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

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

相关文章

【含文档】基于Springboot+Vue的高校失物招领平台(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…

Excel中用位置筛选解法

有 2022 年 1 月的日销售额统计表如下所示&#xff1a; 筛选出偶数日的销售额&#xff1a; spl("E(?1).select(#%20)",A1:B32)#表示当前行号 免费课程、软件免费下载

免杀笔记 ---> 无痕Hook?硬件断点 Syscall!

说到Hook&#xff0c;我们有很多Hook&#xff0c;像Inline-Hook&#xff0c;我们也是用的比较多&#xff0c;但是正如我上一篇Blog说的&#xff0c;他会对内存进行修改&#xff0c;如果EDR或者AV增加一个校验机制&#xff0c;不断检验某一块内存&#xff0c;那么就算你用syscal…

SQL 性能调优

什么是 SQL 性能调优 SQL 性能调优是优化 SQL 查询以尽可能高效地运行的过程&#xff0c;从而减少数据库负载并提高整体系统性能。这是通过各种技术实现的&#xff0c;例如分析查询执行计划、优化索引和重写查询以确保最佳执行路径。目标是最大限度地减少执行查询所需的时间和…

【已解决】【Hadoop】【./bin的使用】bash: ./bin/hdfs: 没有那个文件或目录

在 Hadoop 环境中&#xff0c;决定何时在命令前添加 ./bin 和如何处理路径 /home/hadoop 与 /usr/local/hadoop 的问题&#xff0c;主要取决于你的当前工作目录和环境变量的设置。以下是一些指导原则&#xff1a; 何时使用 ./bin&#xff1a; 当前目录是 Hadoop 安装目录&…

高通AI应用程序开发1:SNPE 概述

1. 功能 The Qualcomm Neural Processing SDK&#xff08;SNPE&#xff09; 是 Qualcomm Snapdragon 软件加速运行时&#xff0c;用于执行深度神经网络。使用 SNPE&#xff0c;用户可以: 执行任意深度的神经网络 在 Snapdragon CPU、Adreno GPU 或 Hexagon DSP 上执行网络。 …

hadoop大数据平台操作笔记(下)

–接hive数据库的操作 函数的操作 聚合函数 函数名说明sun()求和max()最大值min()最小值count()统计avg()平均值 单行函数 数字类型 函数名说明abs()绝对值ceil()进一取整floor()去尾取整round()四舍五入pow()幂运算rand()随机值&#xff0c;获取0~1的小数percentile(字段…

卷轴模式:一种新型的电子商务营销策略

随着电子商务行业的蓬勃发展&#xff0c;各类创新营销策略层出不穷&#xff0c;旨在吸引更多消费者并提升销售额。在这之中&#xff0c;卷轴模式以其独特的优势和可观的收益逐渐受到业界renxb001的关注。本文将深入探讨卷轴模式的概念、优势、应用场景以及如何参与其中。 卷轴…

企业平台API治理的重要性

当前&#xff0c;关于API治理的讨论多聚焦于设计治理&#xff0c;即确保API设计的统一。此为治理的基础&#xff0c;因为设计的不协调会带来严重问题。 尽管应重视企业API设计治理策略&#xff0c;但我们主张扩大视野&#xff0c;关注“平台API治理”。这包括对每个API的发现、…

vioovi视与视标准工时工具与ECRS工时分析软件:精益生产的新纪元

在当今快速变化的市场环境中&#xff0c;企业面临着前所未有的挑战&#xff0c;其中成本控制与效率提升成为制约其发展的关键因素。传统的标准工时工具在应对这些挑战时显得力不从心&#xff0c;其局限性日益凸显。而vioovi视与视标准工时工具的出现&#xff0c;则为企业实现精…

【Linux实践】实验六:LINUX系统管理

【Linux实践】实验六&#xff1a;LINUX系统管理 实验目的实验内容实验步骤及结果1. 包管理工具2. VMware Tools3. 修改主机名4. 网络配置① 临时修改② 永久修改 5. 查找文件6. 前后台执行7. 查看进程8. 结束进程 实验目的 4、掌握Linux下软件包管理&#xff0c;包括命令rpm、…

three.js----快速上手,如何用vue在web页面中导入 gltf/glb , fbx , obj 模型

首先去three.js官网下载three.js包,或者在直接在vue项目中 npm install three0.158.0 --save (学three.js需要有一点前端基础,基础掌握不牢的还是从基础开始) 这个0.158.0是版本号,不用纠结选新的还是选旧的,新手先不考虑这些,three.js基本上个把月就会更新一次,选一个不太新…

搞定抖音视频剪辑,这四款足矣!

现在真的是人人都会剪辑的时代了&#xff0c;作为一个刚踏入视频创作大门的菜鸟&#xff0c;我可是没少在这些剪辑软件里摸爬滚打。今天&#xff0c;就让我以一个新手的视角&#xff0c;给大家伙儿说说四款剪辑工具&#xff0c;在抖音这片战场上&#xff0c;它们各自的表现如何…

速卖通欧盟资质认证怎么弄?速卖通GPSR超全认证攻略请收下!

8月19日&#xff0c;速卖通官方发布了关于欧盟《通用产品安全法规》&#xff08;简称&#xff1a;GPSR&#xff09;的管控通知。 通知显示&#xff1a;针对未按照法规要求完成合规的商品&#xff0c;平台已于9月中旬开始陆续执行屏蔽管控&#xff0c;预计在12月1日前完成&…

轻量级日志管理系统SpringBoot3+Loki+grafana的使用实例

目录 文章目录 目录1、简介2、SpringBoot3应用发送日志到Loki2.1、基本介绍2.2、添加依赖2.3、配置文件application.yml2.4、创建logback配置2.5、添加日志示例2.6、运行SpringBoot3 3、在grafana中查看日志3.1、登录grafana3.2、查询日志3.3、查询我们的SpringBoot发送过来的日…

【Linux】进程的标识符、状态(超详解)

目录 进程的概念 进程标识符PID 系统调用创建进程-fork初识 进程状态 R状态&#xff08;运行状态&#xff09; S&#xff0c;D状态&#xff08;休眠状态&#xff09; T&#xff0c;t状态 Z状态&#xff08;僵尸进程&#xff09; 孤儿进程 X状态&#xff08;死亡状态&a…

OceanBase云数据库战略实施两年,受零售、支付、制造行业青睐

2022年OceanBase推出云数据库产品OB Cloud,正式启动云数据库战略。两年来OB Cloud发展情况如何&#xff0c;9月26日&#xff0c;OceanBase公有云事业部总经理尹博学向记者作了介绍。 尹博学表示&#xff0c;OB Cloud推出两年以来&#xff0c;已服务超过700家客户&#xff0c;客…

巧用时间换空间:解读 ArcGraph 如何灵活应对有限内存下的图分析

导读&#xff1a;ArcGraph 是一款云原生架构、存查分析一体化的分布式图数据库。本文将详细解读 ArcGraph 如何灵活应对有限内存下的图分析。 01 引言 在图分析技术广泛应用的当下&#xff0c;学术界和各大图数据库厂商热衷于提升图分析技术的高性能指标。然而&#xff0c;追求…

夹耳式耳机哪个牌子最好?夹耳式耳机品牌排行榜前十名

随着无线音频技术的不断进步&#xff0c;耳夹式蓝牙耳机因其独特的设计与便捷的使用体验&#xff0c;逐渐成为众多消费者的心头好。然而&#xff0c;在众多品牌与型号中选择一款既符合个人需求又能保证音质与舒适度的产品并非易事。为此&#xff0c;我们综合了市场反馈、用户评…

6天19颗卫星成功发射,厉害了我的国!

我国最近成功发射了“祁连一号”、“吉林一号”、天仪41星&#xff08;神启号&#xff09;和“吉林一号”SAR01A星&#xff0c;前后仅6天就有19颗卫星被送入了太空。 不禁让人感叹&#xff1a;“我们的征途是星辰与大海&#xff0c;厉害了我的国&#xff01;” “祁连一号”与…