【FreeRTOS】二值信号量实现线程的同步

2023-05-16

【FreeRTOS】二值信号量实现线程的同步

测试环境如下

stm32L431RCT6
MDK keil5
stm32cube + FreeRTOS

一、添加多个任务

1、引脚配置

LED使用的引脚PA8和PB2设置成output

在这里插入图片描述

在这里插入图片描述

将按键引脚PC9设置为Input
在这里插入图片描述

2、选择时钟源,配置时钟

在这里插入图片描述

在这里插入图片描述

3、调试模式和基础源时钟

在这里插入图片描述

在基于STM32 HAL的项目中,一般需要维护的 “时基” 主要有2个:

  • HAL的时基,SYS Timebase Source
  • OS的时基(仅在使用OS的情况下才考虑)

而这些 “时基” 该去如何维护,主要分为两种情况考虑:

  • 裸机运行:

可以通过 SysTick(滴答定时器)或 (TIMx)定时器 的方式来维护 SYS Timebase Source,也就是HAL库中的 uwTick,这是HAL库中维护的一个全局变量。在裸机运行的情况下,我们一般选择默认的 SysTick(滴答定时器) 方式即可,也就是直接放在 SysTick_Handler() 中断服务函数中来维护。

  • 带OS运行:

前面提到的 SYS Timebase Source 是STM32的HAL库中的新增部分,主要用于实现 HAL_Delay() 以及作为各种 timeout 的时钟基准。

在使用了OS(操作系统)之后,OS的运行也需要一个时钟基准(简称“时基”),来对任务和时间等进行管理。而OS的这个 时基 一般也都是通过 SysTick(滴答定时器) 来维护的,这时就需要考虑 “HAL的时基” 和 “OS的时基” 是否要共用 SysTick(滴答定时器) 了。

如果共用SysTick,当我们在CubeMX中选择启用FreeRTOS之后,在生成代码时,CubeMX一定会报如下提示:在这里插入图片描述

建议不要使用 SysTick(滴答定时器)作为 “HAL的时基”,因为FreeRTOS要用,如果共用,潜在一定风险。

4、调试串口选择

在这里插入图片描述

需要在NVIC使能串口UART1中断

在这里插入图片描述

5、选择使用FREERTOS以及接口版本

在这里插入图片描述

Cortex微控制器软件接口标准(CMSIS)是独立于供应商的硬件抽象层,用于基于Arm Cortex处理器的微控制器。 CMSIS定义了通用工具接口,并提供一致的设备支持。 CMSIS软件接口简化了软件重用,CMSIS提供了到处理器和外围设备,实时操作系统以及中间件组件的接口。

V1使得软件能够在不同的RTOS系统下工作,为实时操作系统提供通用的API。 V2是在V1基础上的扩展了一些关于 Armv8-M的支持,动态对象,多核系统相关的东西。

6、创建任务

在这里插入图片描述

在这里插入图片描述

7、生成代码

在这里插入图片描述
在这里插入图片描述

8、添加UART串口打印代码

1)在uart.c里面添加printf重定向

/* USER CODE BEGIN 0 */
static uint8_t s_uart1_rxch;
char           g_uart1_rxbuf[256];
uint8_t        g_uart1_bytes;

/* USER CODE END 0 */
………..省略………
/* USER CODE BEGIN 1 */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
	HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);
	return ch;
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)
	{
		if(g_uart1_bytes<sizeof(g_uart1_rxbuf))
		{
			g_uart1_rxbuf[g_uart1_bytes++]=s_uart1_rxch;
		}
		HAL_UART_Receive_IT(&huart1,&s_uart1_rxch,1);
	}
}

2)使能UART1的中断,在该函数中进行

void MX_UART1_UART_Init(void)
{
。。。。
  /* USER CODE BEGIN USART1_Init 2 */
  //中断接收的每个字节暂时放在s_uart1_rxch
  HAL_UART_Receive_IT(&huart1, &s_uart1_rxch, 1);
  /* USER CODE END USART1_Init 2 */

}

3)在uart.h里面添加头文件和定义


/* USER CODE BEGIN Includes */
#include <stdio.h>

#include <string.h>
/* USER CODE END Includes */


/* USER CODE BEGIN Private defines */
extern char       g_uart1_rxbuf[256];

extern uint8_t    g_uart1_bytes;

#define clear_uart1_rxbuf() do {memset(g_uart1_rxbuf,0,sizeof(g_uart1_rxbuf));\
        g_uart1_bytes=0; } while(0)


/* USER CODE END Private defines */
void MX_USART1_UART_Init(void);

/* USER CODE BEGIN Prototypes */


9、跑马灯跑起来

跑马灯跑起来 在 freertos.c 文件中我们能看到我们创建的任务函数: void Start_RedLed_toggle(void const * argument) 我们需要在任务函数中写跑马灯程序:

在这里插入图片描述

/* USER CODE END Header_Start_RedLed_toggle */
void Start_RedLed_toggle(void const * argument)
{
  /* USER CODE BEGIN Start_RedLed_toggle */
  /* Infinite loop */
  for(;;)
  {

    osDelay(500);
    HAL_GPIO_WritePin(RedLED_GPIO_Port, RedLED_Pin, GPIO_PIN_SET);
    printf("this is RED!\r\n");
    osDelay(500);
    HAL_GPIO_WritePin(RedLED_GPIO_Port, RedLED_Pin, GPIO_PIN_RESET);
    osDelay(500);
  }
  /* USER CODE END Start_RedLed_toggle */
}

/* USER CODE END Header_start_GreenLed_toggle */
void start_GreenLed_toggle(void const * argument)
{
  /* USER CODE BEGIN start_GreenLed_toggle */
  /* Infinite loop */
  for(;;)
  {
    osDelay(1000);
    HAL_GPIO_WritePin(GreenLED_GPIO_Port, GreenLED_Pin, GPIO_PIN_SET);
    printf("this is Green!\r\n");
    osDelay(1000);
    HAL_GPIO_WritePin(GreenLED_GPIO_Port, GreenLED_Pin, GPIO_PIN_RESET);
    osDelay(1000);
  }
  /* USER CODE END start_GreenLed_toggle */
}


10、运行测试

然后编译下载 ,可以观察到板子上的LED灯安装程序跑起来了,可以看到RedLed和GreenLed交替闪烁。1秒内红灯闪两次,绿灯闪一次。

在这里插入图片描述

二、实现多任务间的同步

在多任务处理系统中,如果一个任务开始访问资源,但在脱离运行状态之前没有完成其访问,则有可能出错。 如果任务使资源处于不一致状态,则通过任何其他任务或中断访问同一资源可能导致数据损坏或其他类似问题。

对任务之间或任务与中断之间共享的资源的访问必须使用**“互斥”技术进行管理**。 目标是确保一旦一个任务开始访问一个不可重入且不线程安全的共享资源,同一任务就具有对资源的独占访问权限,直到资源返回到一致状态为止。

FreeRTOS提供了几个可以用来实现互斥的特性,但是最好的互斥方法是(只要有可能,因为它不实用)设计应用程序,使资源不被共享,并且每个资源只从一个任务访问。

1、二值信号量

互斥信号是一种特殊类型的二进制信号量,用于控制对两个或多个任务之间共享的资源的访问。

信号量名副其实就是一个信号可以进行任务之前信息的交互,二值信号量通常用于互斥访问或同步。二值信号量就是一个只能保存一个数据的队列,这个队列要么是空要么是有他就只有两种状态。

2、创建信号量Semaphore

在 Timers and Semaphores 进行配置。

1)创建二值信号量Binary Semaphore,

这里比较简单我们只需要设置一下二值信号量的名字即可

在这里插入图片描述

  • Semaphore Name: 信号量名称
  • Allocation: 分配方式:Dynamic 动态内存创建
  • Conrol Block Name: 控制块名称

2)代码编写

1.创建二值信号量

这部分代码cubeMX会自动生成
在这里插入图片描述

3、相关API介绍

(1) osSemaphoreCreate

用于创建一个二值信号量,并返回一个ID。

函数 osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count)
参数 semaphore_def: 引用由osSemaphoreDef定义的信号量 count: 信号量数量
返回值 成功返回信号量ID,失败返回0
(2)osSemaphoreDelete

用于删除一个信号量,包括二值信号量,计数信号量,互斥量和递归互斥量。如果有任务阻塞在该信号量上,那么不要删除该信号量。

函数 osStatus osSemaphoreDelete (osSemaphoreId semaphore_id)
参数 semaphore_id: 信号量ID
返回值 错误码
(3)osSemaphoreRelease

用于释放信号量的宏。释放的信号量对象必须是已经被创建的,可以用于二值信号量、计数信号量、互斥量的释放,但不能释放由函数 xSemaphoreCreateRecursiveMutex() 创建的递归互斥量。可用在中断服务程序中。

函数 osStatus osSemaphoreRelease (osSemaphoreId semaphore_id)
参数 semaphore_id: 信号量ID
返回值 错误码
(4)osSemaphoreWait

用于获取信号量,不带中断保护。获取的信号量对象可以是二值信号量、计数信号量和互斥量,但是递归互斥量并不能使用这个 API 函数获取。可用在中断服务程序中。

函数 int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec)
参数 semaphore_id: 信号量ID millisec:等待信号量可用的最大超时时间,单位为 tick(即系统节拍周期)。 如果宏 INCLUDE_vTaskSuspend 定义为 1 且形参 xTicksToWait 设置为 portMAX_DELAY ,则任务将一直阻塞在该信号量上(即没有超时时间)
返回值 错误码

4、二值信号量使用

在 freertos.c 文件中,找到我们创建的两个任务,修改代码。

/* USER CODE END Header_Start_RedLed_toggle */
void Start_RedLed_toggle(void const * argument)
{
  /* USER CODE BEGIN Start_RedLed_toggle */
	osStatus xReturn = osErrorValue;
  /* Infinite loop */
  for(;;)
  {
	xReturn = osSemaphoreWait(myBinarySem01Handle, /* 二值信号量句柄 */
	                               osWaitForever); /* 等待时间 */
	if(osOK == xReturn)
	{
		printf("BinarySem get!\n\n");
		osDelay(500);
		HAL_GPIO_WritePin(RedLED_GPIO_Port, RedLED_Pin, GPIO_PIN_RESET);
		printf("this is RED!\r\n");
		osDelay(500);
		HAL_GPIO_WritePin(RedLED_GPIO_Port, RedLED_Pin, GPIO_PIN_SET);
		osDelay(500);
	}
  }
  /* USER CODE END Start_RedLed_toggle */
}

/* USER CODE END Header_start_GreenLed_toggle */
void start_GreenLed_toggle(void const * argument)
{
  /* USER CODE BEGIN start_GreenLed_toggle */
        osStatus xReturn;
  /* Infinite loop */
  for(;;)
  {

         if(HAL_GPIO_ReadPin(Key1_GPIO_Port, Key1_Pin) == GPIO_PIN_RESET)
         {
                 xReturn = osSemaphoreRelease(myBinarySem01Handle);//给出二值信号量
                 if(osOK == xReturn)
                 {
                         printf("release!\r\n");
                         osDelay(1000);
                         HAL_GPIO_WritePin(GreenLED_GPIO_Port, GreenLED_Pin, GPIO_PIN_RESET);
                         printf("this is Green!\r\n");
                         osDelay(1000);
                         HAL_GPIO_WritePin(GreenLED_GPIO_Port, GreenLED_Pin, GPIO_PIN_SET);
                         osDelay(1000);
                  }
                  else
                  {
                     printf("BinarySem release fail!\r\n");
                  }
         }
         osDelay(100);

  }
  /* USER CODE END start_GreenLed_toggle */
}

5、运行测试

红灯尝试获取资源,由于资源是可用的,红灯任务成功的获取资源(红灯闪烁一次),绿灯任务尝试获取资源,但是资源被红灯任务持有,所以尝试失败,绿灯任务进入阻塞状态等待资源,允许红灯再次运行(红灯闪烁一次),按键按下资源被释放,绿灯任务退出阻塞状态,绿灯任务获取资源成功(绿灯闪烁一次)并且之后允许访问资源,当绿灯任务执行完之后也会将资源释放。资源可以再次用于两个任务之间。

在这里插入图片描述

2、计数信号量

在这里插入图片描述

这里需要使用两个按键,按键配置的方法和KEY1一样,实现按下KEY1申请资源,按下KEY2释放资源。

1)创建计数信号量Counting Semaphore

要想使用计数信号量必须在 Config parameters 中把 USE_COUNTING_SEMAPHORES 选择 Enabled 来使能。

用计数信号量实现二值信号量只需将计数信号量的初始值设置为 1 即可。

在这里插入图片描述

添加计数信号量
在这里插入图片描述

  • Semaphore Name: 信号量名称
  • Count: 计数信号量的最大值
  • Allocation: 分配方式:Dynamic 动态内存创建
  • Conrol Block Name: 控制块名称

2)生成代码,计数信号量自动创建。

在这里插入图片描述

3)修改代码

void Start_RedLed_toggle(void const * argument)
{
  /* USER CODE BEGIN Start_RedLed_toggle */
	osStatus xReturn = osErrorValue;
  /* Infinite loop */
  for(;;)
  {
	/*xReturn = osSemaphoreWait(myBinarySem01Handle, // 二 ? 信号量句柄
	                            osWaitForever); // 等待时间
	*/

	if(HAL_GPIO_ReadPin(Key2_GPIO_Port, Key2_Pin) == GPIO_PIN_RESET)
	{
		 xReturn = osSemaphoreWait(myCountingSem01Handle, /* 计数信号量句柄 */
		                                        0); /* 等待时间:0 */

	 if(osOK == xReturn)
	 {
	      printf( "Key2 is pressed and successfully applied for parking space.\r\n" );
	      osDelay(500);
	      HAL_GPIO_WritePin(RedLED_GPIO_Port, RedLED_Pin, GPIO_PIN_RESET);
	      printf("this is RED!\r\n");
	      osDelay(500);
	      HAL_GPIO_WritePin(RedLED_GPIO_Port, RedLED_Pin, GPIO_PIN_SET);
	      osDelay(500);
	 }
	 else
	 {
	      printf( "Key2 is pressed. Sorry, the parking lot is full now!\r\n" );
	 }
	}
  }
  /* USER CODE END Start_RedLed_toggle */
}
void start_GreenLed_toggle(void const * argument)
{
  /* USER CODE BEGIN start_GreenLed_toggle */
	osStatus xReturn;
  /* Infinite loop */
  for(;;)
  {

	 if(HAL_GPIO_ReadPin(Key1_GPIO_Port, Key1_Pin) == GPIO_PIN_RESET)
	 {
		 //xReturn = osSemaphoreRelease(myBinarySem01Handle);//给出二 ? 信号量
		 xReturn = osSemaphoreRelease(myCountingSem01Handle);// 给出计数信号量

	 if(osOK == xReturn)
	 {
		 printf( "Key1 is pressed to release 1 parking space.\r\n" );
		 osDelay(1000);
		 HAL_GPIO_WritePin(GreenLED_GPIO_Port, GreenLED_Pin, GPIO_PIN_RESET);
		 printf("this is Green!\r\n");
		 osDelay(1000);
		 HAL_GPIO_WritePin(GreenLED_GPIO_Port, GreenLED_Pin, GPIO_PIN_SET);
		 osDelay(1000);
	  }
	  else
	  {
		  printf( "Key1 is pressed, but there is no parking space to release!\r\n" );
	  }
	 }
	 osDelay(100);

  }
  /* USER CODE END start_GreenLed_toggle */
}

4)运行测试

按下key2申请资源,按下key1释放资源,当申请资源数量为5时,再次申请资源会失败,只能等资源释放后才能再次申请。
在这里插入图片描述

参考资料:

配置说明:FreeRTOS记录(一、熟悉开发环境以及CubeMX下FreeRTOS配置) - 知乎 (zhihu.com)

二值信号量:(92条消息) FreeRTOS笔记篇:第七章 – 资源管理(互斥锁、二进制信号量、死锁)_墨客Y的博客-CSDN博客_freertos 死锁

创建二值信号量:(92条消息) STM32CubeMX学习笔记(30)——FreeRTOS实时操作系统使用(信号量)_Leung_ManWah的博客-CSDN博客_ossemaphorecreate

创建二值信号量:(92条消息) STM32CubeMX学习笔记(30)——FreeRTOS实时操作系统使用(信号量)_Leung_ManWah的博客-CSDN博客_ossemaphorecreate

(92条消息) STM32FreeRTOS二值信号量的基本介绍和操作_花落已飘的博客-CSDN博客

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【FreeRTOS】二值信号量实现线程的同步 的相关文章

  • 基于HAL库的FREERTOS----------二.任务API函数

    任务API函数览概 CUBEMX对 做了API的封装 很多 的函数没有封装到位 可以用原函数调用 任务API函数分别介绍 1 uxTaskPriorityGet 此函数用来获取指定任务的优先级 要使用此函数的话宏 INCLUDE uxTas
  • FreeRTOS快速上手

    FreeRTOS使用 一 源码下载和移植文件提取 1 1 源码下载 在网站https sourceforge net projects freertos 可以找到freertos最新的源码 1 2 移植文件提取 根据第一步 我们会得到一个f
  • FreeRTOS config开始的宏

    FreeRTOSConfig h系统配置文件中可以自定义 FreeRTOS h中定义默认值 configAPPLICATION ALLOCATED HEAP 默认情况下FreeRTOS的堆内存是由编译器来分配的 将宏configAPPLIC
  • FreeRTOS记录(七、FreeRTOS信号量、事件标志组、邮箱和消息队列、任务通知的关系)

    我们在前面单独介绍过FreeRTOS的任务通知和消息队列 但是在FreeRTOS中任务间的通讯还有信号量 邮箱 事件组标志等可以使用 这篇文章就这些成员与消息队列和任务通知的关系进行说明分析 增加邮箱部分 任务通知发送消息 Demo 202
  • 【FreeRTOS】多任务创建

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • 【FreeRTOS】队列的使用

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • FreeRTOS学习笔记<中断>

    中断概念 Cortex M的NVIC最多支持240个IRQ 中断请求 1个不可屏蔽中断 NMI 1个Systick 滴答定时器 定时器中断和多个系统异常 Cortex M处理器有多个用于管中断和异常的可编程寄存器 这些寄存器大多数都在 NV
  • FreeRTOS+CubeMX系列第一篇——初识FreeRTOS

    文章目录 一 关于FreeRTOS 二 FreeRTOS的特点 三 如何在CubeMX上配置FreeRTOS 四 FreeRTOS文档资料 五 同系列博客 一 关于FreeRTOS 1 什么是FreeRTOS FreeRTOS是一个迷你的实
  • FreeRTOS临界区

    FreeRTOS临界区是指那些必须完整运行 不能被打断的代码段 比如有的外设的初始化需要严格的时序 初始化过程中不能被打断 FreeRTOS 在进入临界区代码的时候需要关闭中断 当处理完临界区代码以后再打开中断 FreeRTOS 系统本身就
  • 【FreeRTOS(三)】任务状态

    文章目录 任务状态 任务挂起 vTaskSuspend 取消任务挂起 vTaskResume 挂起任务调度器 vTaskSuspendAll 取消挂起任务调度器 xTaskResumeAll 代码示例 任务挂起 取消任务挂起 代码示例 挂起
  • 【FreeRTOS】任务通知的使用

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • FreeRTOS基础五:软件定时器

    软件定时器简介 软件定时器的作用 在指定的时间到来时执行指定的函数 或者以某个频率周期性地执行某个函数 被执行的函数叫做软件定时器回调函数 软件定时器由FreeRTOS内核实现 不需要硬件支持 软件定时器只有在软件定时器回调函数被调用时才需
  • FreeRTOS,串口中断接收中使用xQueueOverwriteFromISR()函数,程序卡死在configASSERT

    原因 UART的中断优先级设置的太高 高于了configMAX SYSCALL INTERRUPT PRIORITY宏定义的安全中断等级 UART的中断等级小于等于宏定义的优先等级即可
  • FreeRTOS学习(三)开关中断

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 背景知识 Cotex M3的NVIC最多支持240个IRQ 中断请求 1个不可屏蔽 NMI 1个Systick 滴答定时器 Cortex M处理
  • FreeRTOS学习笔记(8)---- 软件定时器

    使用FreeRTOS软件定时器需要在文件FreeRTOSConfig h先做如下配置 1 configUSE TIMERS 使能软件定时器 2 configTIMER TASK PRIORITY 定时器任务优先级 3 configTIMER
  • [FreeRTOS入门学习笔记]定时器

    定时器的使用步骤 1 定义一个handle xTimerCreate创建 2 启动定时器 在Task1中调用 通过队列通知守护任务来执行定时器任务 要再config头文件中定义守护任务相关配置 虽然定时器是在task1中启动 但是定时器的任
  • STM32 Freertos 添加 外部sram heap_5.c

    1 添加外部SRAM 初始化 2 添加heap 5 c 3 初始化heap 5 c 外部堆栈 Define the start address and size of the two RAM regions not used by the
  • 再论FreeRTOS中的configTOTAL_HEAP_SIZE

    关于任务栈和系统栈的基础知识 可以参考之前的随笔 FreeRTOS 任务栈大小确定及其溢出检测 这里再次说明 define configTOTAL HEAP SIZE size t 17 1024 这个宏 官方文档解释 configTOTA
  • FreeRTOS 匈牙利表示法 [重复]

    这个问题在这里已经有答案了 我是 RTOS 和 C 编程的新手 而且我仍在习惯 C 的良好实践 因此 我打开了一个使用 FreeRTOS 的项目 我注意到操作系统文件使用匈牙利表示法 我知道一点符号 但面临一些新的 标准 FreeRTOS
  • 小型 ARM 微控制器的 RTOS 内核之间的可量化差异 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 有许多不同的 RTOS 可用于微控制器 我专门寻找支持 ARM Cortex M 处理器的 RTOS 另外 我对闭源解决方案不感兴趣 试图从网站

随机推荐

  • 路径规划资料

    1 RRT算法原理图解 https blog csdn net weixin 43465857 article details 96451631 2 最透彻的A 算法详解 https my oschina net u 4847229 blo
  • nav2阅读笔记

    1 机器人起始坐标是在全局地图中 xff0c 目标点也在全局地图中 xff0c 全局路径规划在全局地图完成 机器人的运动控制是在局部地图中完成 xff0c 也就是在车体坐标系下 2 无人机 自动驾驶车辆全局路径规划 局部路径规划都是在全局坐
  • 日常使用标签2

    日常使用标签2 1 CUDA入门教程 https blog csdn net luoganttcc article details 123474189
  • 人工智能概述

    目录 什么是人工智能实现人工智能的方法逻辑编程机器学习深度学习机器学习和深度学习的区别 人工智能的分类如何实现人工智能 什么是人工智能 人工智能 又被称为机器智能 xff0c 是一种综合计算机科学 统计学 语言学等多种学科 xff0c 使机
  • 2019了,转行学编程过时了吗?

    最近 xff0c 我的一篇文章 现在学Java的人都是傻子 引起了一些网友讨论 xff0c 都在说现在学Java过时了 xff0c Java市场趋于饱和了 xff0c 应该弃学Java xff0c xff0c 难道Java编程真的过时了 x
  • 什么是用户态和内核态?用户态和内核态是如何切换的?

    3 什么是用户态和内核态 xff1f 用户态和内核态是操作系统的两种运行状态 xff0c 操作系统主要是为了对访问能力进行限制 xff0c 用户态的权限较低 xff0c 而内核态的权限较高 用户态 xff1a 用户态运行的程序只能受限地访问
  • ubuntu安装Clamav

    一 简介 Clam AntiVirus是一个类UNIX系统上使用的反病毒软件包 主要应用于邮件服务器 xff0c 采用多线程后台操作 xff0c 可以自动升级病毒库 ClamAV是一个在命令行下查毒软件 xff0c 因为它不将杀毒作为主要功
  • 什么是上下文切换?

    上下文切换指的是内核操作系统的核心在CPU上对进程或者线程进行切换 搞清楚上下文切换需要先搞清楚什么是上下文 CPU在开始执行任务时需要先知道从哪里去加载任务 xff0c 从哪里开始执行 xff0c 上下文的作用就是告诉CPU这些 xff0
  • ubuntu16.04下,ROS+PX4+QGC安装

    ubuntu16 04下 xff0c ROS 43 PX4 43 QGC安装 ROS安装 xff1a 第一步 xff1a ROS安装前准备工作 1 在Ubuntu系统上 xff0c 确认git已经安装 span class token fu
  • TokenEndpoint : Handling Null Pointer Exception

    springboot oauth2 0生成token时报错 详细的日志没有打印出来 需要手动配置log 64 Override public void configure AuthorizationServerEndpointsConfig
  • linux(ubuntu)无法连接网络

    提示 xff1a 版本 xff1a ubuntu16 0 4 问题 xff1a 开机没有网络 xff0c 无法连接网络 xff0c 尝试了很多方法最终才可以 首先查看ifconfig 查看网卡信息 ifconfig 查看ip ip a 查看
  • 八皇后问题

    问题描述 在国际象棋中 xff0c 有一个非常强势的棋子 皇后 xff0c 他的走法可以在网上参考一下 xff0c 概括来说就是可以沿着行 列 与对角线平行的线走 而在计算机中有一个关于他的经典问题 xff0c 8皇后 xff0c 就是在8
  • ubuntu18.04.3如何在终端下切换到指定文件夹或根目录

    看到很多的新手 xff0c 不知道如何在终端切换到根目录的 xff0c 或者是指定的目录的 xff0c 下面介绍一下切换的方法 1 先按键盘 ctrl 43 alt 43 t 弹出终端 xff0c 那么你会看到终端上的提示当前目录为 这个就
  • MySql简单查询——单表查询

    一 DDL xff08 Data Definition Language xff09 xff1a 数据定义语言 xff0c 用来定义数据库对象 xff1a 库 表 列等 xff1b 相关字段 xff1a create drop alter
  • linux下可视化git工具git-cola安装与使用(HTTP方式)

    一 git cola为何物 很多小伙伴 xff0c 特别喜欢使用TortoiseGit xff0c 该软件是做什么的 xff0c 就不用多说吧 奈何 xff0c TortoiseGit只有windows版 xff0c 这让在linux上开发
  • 解决ubuntu下应用程序菜单不在程序的左上角

    测试版本 xff1a ubuntu16 04 问题 xff1a 应用程序菜单不在程序的左上角 xff0c 默认放在了桌面顶部的菜单栏上 如下 xff1a 解决办法 xff1a System Settings gt Appearance gt
  • linux下可视化git工具git-cola安装与使用(SSH方式)

    一 git cola为何物 很多小伙伴 xff0c 特别喜欢使用TortoiseGit xff0c 该软件是做什么的 xff0c 就不用多说吧 奈何 xff0c TortoiseGit只有windows版 xff0c 这让在linux上开发
  • CAS实现SSO单点登录原理

    yale cas可以百度一下 xff0c 这是学习cas后的一点总结 xff0c 以备日后使用 xff01 安全性 xff1a 用户只须在cas录入用户名和密码 xff0c 之后通过ticket绑定用户 xff0c 在cas客户端与cas校
  • 五种知网文献免费下载方式

    1 idata中国知网 网址 xff1a idata中国知网 进入系统 xff0c 注册账号 xff0c 登录即可 每天五篇额度 xff0c 基本够用 xff0c 可注册多个账号使用 2 上海研发公共服务平台 网址 xff1a 上海研发公共
  • 【FreeRTOS】二值信号量实现线程的同步

    FreeRTOS 二值信号量实现线程的同步 测试环境如下 stm32L431RCT6 MDK keil5 stm32cube 43 FreeRTOS 一 添加多个任务 1 引脚配置 LED使用的引脚PA8和PB2设置成output 将按键引