FreeRTOS 任务相关 API 函数(一)

news2024/10/5 16:28:01

文章目录

  • 一、任务创建和删除 API 函数
    • 1. xTaxkCreate()
    • 2. xTaskCreateStatic()
    • 3. xTaskCreateRestricted()
    • 4. vTaskDelete()
  • 二、任务创建和删除实验(动态方法)
  • 三、任务创建和删除实验(静态方法)


一、任务创建和删除 API 函数

FreeRTOS 最基本的功能就是任务管理,而任务管理最基本的操作就是创建和删除任务,FreeRTOS 的任务创建和删除 API 函数如下表所示:
在这里插入图片描述

1. xTaxkCreate()

此函数用来创建一个任务,任务需要 RAM 来保存与任务有关的状态信息(任务控制块),任务也需要一定的 RAM 来作为任务堆栈。如果使用函数 xTaskCreate()来创建任务的话那么这些所需的 RAM 就会自动的从 FreeRTOS 的堆中分配,因此必须提供内存管理文件,默认我们使用heap_4.c 这个内存管理文件,而且宏 configSUPPORT_DYNAMIC_ALLOCATION 必须为 1。如果使用函数 xTaskCreateStatic()创建的话这些 RAM 就需要用户来提供了。新创建的任务默认就是就绪态的,如果当前没有比它更高优先级的任务运行那么此任务就会立即进入运行态开始运行,不管在任务调度器启动前还是启动后,都可以创建任务。此函数也是我们以后经常用到的,本篇用此函数来创建任务,函数原型如下:

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
						const char * const pcName,
						const uint16_t usStackDepth,
						void * const pvParameters,
						UBaseType_t uxPriority,
						TaskHandle_t * const pxCreatedTask )

参数:
pxTaskCode: 任务函数。

pcName: 任务名字,一般用于追踪和调试,任务名字长度不能超过configMAX_TASK_NAME_LEN。

usStackDepth: 任务堆栈大小,注意实际申请到的堆栈是usStackDepth 的 4 倍。其中空闲任务的任务堆栈大小为 configMINIMAL_STACK_SIZE。

pvParameters: 传递给任务函数的参数。

uxPriotiry: 任务优先级,范围 0~ configMAX_PRIORITIES-1。

pxCreatedTask: 任务句柄,任务创建成功以后会返回此任务的任务句柄,这个句柄其实就是任务的任务堆栈。此参数就用来保存这个任务句柄。其他 API 函数可能会使用到这个句柄。

返回值:
pdPASS: 任务创建成功。
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY: 任务创建失败,因为堆内存不足!

2. xTaskCreateStatic()

此函数和 xTaskCreate()的功能相同,也是用来创建任务的,但是使用此函数创建的任务所需 的 RAM 需 要 用 用 户来提供 。 如果要 使 用 此 函 数 的 话 需 要 将 宏configSUPPORT_STATIC_ALLOCATION 定义为 1。函数原型如下:

TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
								const char * const pcName,
								const uint32_t ulStackDepth,
								void * const pvParameters,
								UBaseType_t uxPriority,
								StackType_t * const puxStackBuffer,
								StaticTask_t * const pxTaskBuffer )

参数:
pxTaskCode: 任务函数。

pcName: 任务名字,一般用于追踪和调试,任务名字长度不能超过configMAX_TASK_NAME_LEN。

usStackDepth: 任务堆栈大小,由于本函数是静态方法创建任务,所以任务堆栈由用户给出,一般是个数组,此参数就是这个数组的大小。

pvParameters: 传递给任务函数的参数。

uxPriotiry: 任务优先级,范围 0~ configMAX_PRIORITIES-1。

puxStackBuffer: 任务堆栈,一般为数组,数组类型要为StackType_t 类型。

pxTaskBuffer: 任务控制块。

返回值:
NULL: 任务创建失败,puxStackBuffer 或 pxTaskBuffer 为 NULL 的时候会导致这个错误的发生。
其他值: 任务创建成功,返回任务的任务句柄。

3. xTaskCreateRestricted()

此函数也是用来创建任务的,只不过此函数要求所使用的 MCU 有 MPU(内存保护单元),用此函数创建的任务会受到 MPU 的保护。其他的功能和函数 xTaxkCreate()一样。

BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, 
								  TaskHandle_t * pxCreatedTask )

参数:
pxTaskDefinition: 指向一个结构体 TaskParameters_t,这个结构体描述了任务的任务函数、堆栈大小、优先级等。此结构体在文件 task.h 中有定义。

pxCreatedTask: 任务句柄。

返回值:
pdPASS: 任务创建成功。
其他值: 任务未创建成功,很有可能是因为 FreeRTOS 的堆太小了。

4. vTaskDelete()

删除一个用函数 xTaskCreate()或者 xTaskCreateStatic()创建的任务,被删除了的任务不再存在,也就是说再也不会进入运行态。任务被删除以后就不能再使用此任务的句柄!如果此任务
是使用动态方法创建的,也就是使用函数 xTaskCreate()创建的,那么在此任务被删除以后此任务之前申请的堆栈和控制块内存会在空闲任务中被释放掉,因此当调用函数 vTaskDelete()删除任务以后必须给空闲任务一定的运行时间。

只有那些由内核分配给任务的内存才会在任务被删除以后自动的释放掉,用户分配给任务的内存需要用户自行释放掉,比如某个任务中用户调用函数 pvPortMalloc()分配了 500 字节的内存,那么在此任务被删除以后用户也必须调用函数 vPortFree()将这 500 字节的内存释放掉,否则会导致内存泄露。此函数原型如下:

vTaskDelete( TaskHandle_t xTaskToDelete )

参数:
xTaskToDelete: 要删除的任务的任务句柄。

返回值:

二、任务创建和删除实验(动态方法)

1. 实验程序设计
(1)实验目的
上篇讲解了 FreeRTOS 的任务创建和删除的 API 函数,本篇就来学习如何使用这些API 函数,本篇学习 xTaskCreate()和 vTaskDelete()这两个函数的使用

(2)实验设计
本实验设计三个任务:start_task、task1_task 和 task2_task ,这三个任务的任务功能如下:
start_task:用来创建其他两个任务。
task1_task :当此任务运行 5 此以后就会调用函数 vTaskDelete()删除任务 task2_task,此任务也会控制 LED0 的闪烁,并且周期性的刷新 LCD 指定区域的背景颜色。
task2_task :此任务普通的应用任务,此任务也会控制 LED1 的闪烁,并且周期性的刷新LCD 指定区域的背景颜色。

(3)实验程序与分析
● 任务设置

#define START_TASK_PRIO 1 //任务优先级 (1)
#define START_STK_SIZE 128 //任务堆栈大小 (2)
TaskHandle_t StartTask_Handler; //任务句柄 (3)
void start_task(void *pvParameters); //任务函数 (4)
#define TASK1_TASK_PRIO 2 //任务优先级
#define TASK1_STK_SIZE 128 //任务堆栈大小
TaskHandle_t Task1Task_Handler; //任务句柄
void task1_task(void *pvParameters); //任务函数
#define TASK2_TASK_PRIO 3 //任务优先级
#define TASK2_STK_SIZE 128 //任务堆栈大小
TaskHandle_t Task2Task_Handler; //任务句柄
void task2_task(void *pvParameters); //任务函数
//LCD 刷屏时使用的颜色
int lcd_discolor[14]={ WHITE, BLACK, BLUE, BRED, 
GRED, GBLUE, RED, MAGENTA, 
GREEN, CYAN, YELLOW, BROWN, 
BRRED, GRAY };

(1) 、start_task 任务的任务优先级,此处用宏来表示,以后所有的任务优先级都用宏来表示。创建任务设置优先级的时候就用这个宏,当然了也可以直接在创建任务的时候指定任务优先级。
(2)、start_task 任务的任务堆栈大小。
(3)、start_task 任务的任务句柄。
(4)、start_task 任务的任务函数声明。

● main()函数

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组 4
	delay_init(); //延时函数初始化
	uart_init(115200); //初始化串口
	LED_Init(); //初始化 LED
	LCD_Init(); //初始化 LCD
	POINT_COLOR = RED;
	LCD_ShowString(30,10,200,16,16,"ATK STM32F103/F407");
	LCD_ShowString(30,30,200,16,16,"FreeRTOS Examp 6-1");
	LCD_ShowString(30,50,200,16,16,"Task Creat and Del");
	LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(30,90,200,16,16,"2016/11/25");
	 //创建开始任务
	 xTaskCreate((TaskFunction_t )start_task, //任务函数 (1)
	 (const char* )"start_task", //任务名称
	 (uint16_t )START_STK_SIZE, //任务堆栈大小
	 (void* )NULL, //传递给任务函数的参数
	 (UBaseType_t )START_TASK_PRIO, //任务优先级
	 (TaskHandle_t* )&StartTask_Handler); //任务句柄
	 vTaskStartScheduler(); //开启任务调度 (2)
}

(1)、调用函数 xTaskCreate()创建 tart_task 任务,函数中的各个参数就是上面的任务设置中定义的,其他任务的创建也用这种方法。
(2)、调用函数 vTaskStartScheduler()开启 FreeRTOS 的任务调度器,FreeRTOS 开始运行。

● 任务函数

//开始任务任务函数
void start_task(void *pvParameters) (1)
{
	 taskENTER_CRITICAL(); //进入临界区
	 //创建 TASK1 任务
	 xTaskCreate((TaskFunction_t )task1_task, 
	 (const char* )"task1_task", 
	 (uint16_t )TASK1_STK_SIZE, 
	 (void* )NULL, 
	 (UBaseType_t )TASK1_TASK_PRIO, 
	 (TaskHandle_t* )&Task1Task_Handler); 
	 //创建 TASK2 任务
	 xTaskCreate((TaskFunction_t )task2_task, 
	 (const char* )"task2_task", 
	 (uint16_t )TASK2_STK_SIZE,
	 (void* )NULL,
	 (UBaseType_t )TASK2_TASK_PRIO,
	 (TaskHandle_t* )&Task2Task_Handler); 
	 vTaskDelete(StartTask_Handler); //删除开始任务 (2)
	 taskEXIT_CRITICAL(); //退出临界区
}

//task1 任务函数
void task1_task(void *pvParameters) (3)
{
	u8 task1_num=0;
	POINT_COLOR = BLACK;
	LCD_DrawRectangle(5,110,115,314); //画一个矩形
	LCD_DrawLine(5,130,115,130); //画线
	POINT_COLOR = BLUE;
	LCD_ShowString(6,111,110,16,16,"Task1 Run:000");
	while(1)
	{
		task1_num++; //任务执 1 行次数加 1 注意 task1_num1 加到 255 的时候会清零!!
		LED0=!LED0;
		printf("任务 1 已经执行:%d 次\r\n",task1_num);
		if(task1_num==5) 
		{
			 vTaskDelete(Task2Task_Handler);//任务 1 执行 5 次删除任务 2 (4)
			printf("任务 1 删除了任务 2!\r\n");
		}
		LCD_Fill(6,131,114,313,lcd_discolor[task1_num%14]); //填充区域
		LCD_ShowxNum(86,111,task1_num,3,16,0x80); //显示任务执行次数
		vTaskDelay(1000); //延时 1s,也就是 1000 个时钟节拍
	}
}

//task2 任务函数
void task2_task(void *pvParameters) (5)
{
	u8 task2_num=0;
	POINT_COLOR = BLACK;
	LCD_DrawRectangle(125,110,234,314); //画一个矩形
	LCD_DrawLine(125,130,234,130); //画线
	POINT_COLOR = BLUE;
	LCD_ShowString(126,111,110,16,16,"Task2 Run:000");
	while(1)
	{
		task2_num++; //任务 2 执行次数加 1 注意 task1_num2 加到 255 的时候会清零!!
		 LED1=!LED1;
		printf("任务 2 已经执行:%d 次\r\n",task2_num);
		LCD_ShowxNum(206,111,task2_num,3,16,0x80); //显示任务执行次数
		LCD_Fill(126,131,233,313,lcd_discolor[13-task2_num%14]); //填充区域
		 vTaskDelay(1000); //延时 1s,也就是 1000 个时钟节拍
	}
}

(1)、start_task 任务的任务函数,在此任务函数中我们创建了另外两个任务 task1_task 和task2_task。start_task 任务的职责就是用来创建其他的任务或者信号量、消息队列等的,当创建完成以后就可以删除掉 start_task 任务。

(2)、删除 start_task 任务,注意函数 vTaskDelete()的参数就是 start_task 任务的任务句柄StartTask_Handler。

(3)、task1_task 任务函数(任务 1),任务比较简单,每隔 1 秒钟 task1_num 加一并且 LED0反转,串口输出任务运行的次数,其实就是 task1_num 的值。当 task1_task 运行 5 次以后就调用函数 vTaskDelete()删除任务 task2_task。

(4)、任务 task1_task 运行了 5 次,调用函数 vTaskDelete()删除任务 task2_task。

(5)、task2_task 任务函数(任务 2),和 task1_task 差不多。

在 main 函数中一开始肯定是初始化各种硬件外设,初始化完外设以后调用函数xTaskCreate()创建一个开始任务,注意创建开始任务是在调用函数 vTaskStartScheduler()开启任务调度器之前,这样当后面开启任务调度器以后就会直接运行开始任务了。其他任务的创建就放到开始任务的任务函数中,由于开始任务的职责就是创建其他应用任务和信号量、队列等这些内核对象的,所以它只需要执行一次,当这些东西创建完成以后就可以删除掉开始任务了。

三、任务创建和删除实验(静态方法)

● 任务设置

#define START_TASK_PRIO 1 //任务优先级
#define START_STK_SIZE 128 //任务堆栈大小
StackType_t StartTaskStack[START_STK_SIZE]; //任务堆栈 (1)
StaticTask_t StartTaskTCB; //任务控制块 (2)
TaskHandle_t StartTask_Handler; //任务句柄
void start_task(void *pvParameters); //任务函数
#define TASK1_TASK_PRIO 2 //任务优先级
#define TASK1_STK_SIZE 128 //任务堆栈大小
StackType_t Task1TaskStack[TASK1_STK_SIZE]; //任务堆栈
StaticTask_t Task1TaskTCB; //任务控制块
TaskHandle_t Task1Task_Handler; //任务句柄
void task1_task(void *pvParameters); //任务函数
#define TASK2_TASK_PRIO 3 //任务优先级
#define TASK2_STK_SIZE 128 //任务堆栈大小
StackType_t Task2TaskStack[TASK2_STK_SIZE]; //任务堆栈
StaticTask_t Task2TaskTCB; //任务控制块
TaskHandle_t Task2Task_Handler; //任务句柄
void task2_task(void *pvParameters); //任务函数
//LCD 刷屏时使用的颜色
int lcd_discolor[14]={ WHITE, BLACK, BLUE, BRED, 
GRED, GBLUE, RED, MAGENTA, 
GREEN, CYAN, YELLOW, BROWN, 
BRRED, GRAY };

(1)、静态创建任务需要用户提供任务堆栈,这里定义一个数组作为任务堆栈,堆栈数组为StackType_t 类型。
(2)、定义任务控制块,注意任务控制块类型要用 StaticTask_t,而不是 TCB_t 或 tskTCB!

● main()函数

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组 4
	delay_init(); //延时函数初始化
	uart_init(115200); //初始化串口
	LED_Init(); //初始化 LED
	LCD_Init(); //初始化 LCD
	POINT_COLOR = RED;
	LCD_ShowString(30,10,200,16,16,"ATK STM32F103/407");
	LCD_ShowString(30,30,200,16,16,"FreeRTOS Examp 6-2");
	LCD_ShowString(30,50,200,16,16,"Task Creat and Del");
	LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(30,90,200,16,16,"2016/11/25");
	 //创建开始任务
	StartTask_Handler=xTaskCreateStatic((TaskFunction_t)start_task, //任务函数 (1)
	(const char* )"start_task", //任务名称
	(uint32_t )START_STK_SIZE, //任务堆栈大小
	(void* )NULL, //传递给任务函数的参数
	(UBaseType_t )START_TASK_PRIO, //任务优先级
	(StackType_t* )StartTaskStack, //任务堆栈 (2)
	(StaticTask_t* )&StartTaskTCB); //任务控制块(3) 
	 vTaskStartScheduler(); //开启任务调度
}

(1)、调用函数 xTaskCreateStatic()创建任务。
(2)、将定义的任务堆栈数组传递给函数。
(3)、将定义的任务控制块传递给函数。
可以看出在用法上 xTaskCreateStatic()和 xTaskCreate()没有太大的区别,大多数的参数都相同。

● 任务函数

//开始任务任务函数
void start_task(void *pvParameters)
{
	 taskENTER_CRITICAL(); //进入临界区
	 //创建 TASK1 任务
	Task1Task_Handler=xTaskCreateStatic((TaskFunction_t )task1_task, (1)
										(const char* )"task1_task",
										(uint32_t )TASK1_STK_SIZE,
										(void* )NULL,
										(UBaseType_t )TASK1_TASK_PRIO, 
										(StackType_t* )Task1TaskStack,
										(StaticTask_t* )&Task1TaskTCB);
	 //创建 TASK2 任务
	Task2Task_Handler=xTaskCreateStatic((TaskFunction_t )task2_task, (2)
										(const char* )"task2_task",
										(uint32_t )TASK2_STK_SIZE,
										(void* )NULL,
										(UBaseType_t )TASK2_TASK_PRIO,
										(StackType_t* )Task2TaskStack,
										(StaticTask_t* )&Task2TaskTCB);
	 vTaskDelete(StartTask_Handler); //删除开始任务
	 taskEXIT_CRITICAL(); //退出临界区
}

//task1 任务函数
void task1_task(void *pvParameters)
{
	u8 task1_num=0;
	POINT_COLOR = BLACK;
	LCD_DrawRectangle(5,110,115,314); //画一个矩形
	LCD_DrawLine(5,130,115,130); //画线
	POINT_COLOR = BLUE;
	LCD_ShowString(6,111,110,16,16,"Task1 Run:000");
	while(1)
	{
		task1_num++; //任务执 1 行次数加 1 注意 task1_num1 加到 255 的时候会清零!!
		LED0=!LED0;
		printf("任务 1 已经执行:%d 次\r\n",task1_num);
		if(task1_num==5) 
		{
			 vTaskDelete(Task2Task_Handler);//任务 1 执行 5 次删除任务 2
			printf("任务 1 删除了任务 2!\r\n");
		}
		LCD_Fill(6,131,114,313,lcd_discolor[task1_num%14]); //填充区域
		LCD_ShowxNum(86,111,task1_num,3,16,0x80); //显示任务执行次数
		vTaskDelay(1000); //延时 1s,也就是 1000 个时钟节拍
	}
}

//task2 任务函数
void task2_task(void *pvParameters)
{
	u8 task2_num=0;
	POINT_COLOR = BLACK;
	LCD_DrawRectangle(125,110,234,314); //画一个矩形
	LCD_DrawLine(125,130,234,130); //画线
	POINT_COLOR = BLUE;
	LCD_ShowString(126,111,110,16,16,"Task2 Run:000");
	while(1)
	{
		task2_num++; //任务 2 执行次数加 1 注意 task1_num2 加到 255 的时候会清零!!
		 LED1=!LED1;
		printf("任务 2 已经执行:%d 次\r\n",task2_num);
		LCD_ShowxNum(206,111,task2_num,3,16,0x80); //显示任务执行次数
		LCD_Fill(126,131,233,313,lcd_discolor[13-task2_num%14]); //填充区域
		vTaskDelay(1000); //延时 1s,也就是 1000 个时钟节拍
	}
}

(1)、使用静态任务创建函数 xTaskCreateStatic()来创建任务 task1_task。
(2)、使用静态任务创建函数 xTaskCreateStatic()来创建任务 task2_task。

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

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

相关文章

AcWing4957.飞机降落——学习笔记

目录 题目 代码 AC结果 思路 〇、例子 一、获取数据 二、深度优先遍历(DFS) 1.入参 2.出口 3.判断是否找到安全降落方案 4.递推过程 5.回溯过程 6.DFS完整代码 三、输出打印 题目 4957. 飞机降落 - AcWing题库https://www.acwing.com/pr…

打开 plist 文件

​ 对于使用苹果的进阶或资深玩家来说,有时候要编辑plist文件,比如要弄两个qq,要修改info.plist下的sku,而要是没有工具,就不能随意查看和编辑plist文件了。再有,可能要通过修改plist来破解某些游戏&#x…

windows服务器自带IIS搭建网站并发布公网访问【内网穿透】

文章目录1.前言2.Windows网页设置2.1 Windows IIS功能设置2.2 IIS网页访问测试3. Cpolar内网穿透3.1 下载安装Cpolar3.2 Cpolar云端设置3.3 Cpolar本地设置4.公网访问测试5.结语转载自远程源码文章:【IIS搭建网站】本地电脑做服务器搭建web站点并公网访问「内网穿透…

协同数据交换平台详细设计方案(word)

本资料来源公开网络,仅供个人学习,请勿商用,如有侵权请联系删除 1 架构设计 1.1 总体架构协同数据交换平台利用企业服务总线、数据抽取ETL、消息中间件、大文件传输等相关技术,包括文件适配器、数据库适配器、Web服务中间件等在内…

【排序算法(四)】归并排序计数排序(非比较排序)以及八大排序算法的总结

​ ​📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:数据结构 🎯长路漫漫浩浩,万事皆有期待 文章目录1、归并排序1.1 算法…

图像处理数据集

BSDS500 Berkeley Segmentation Dataset 500 是第一个用于评估超像素算法的数据集。对于参数优化,使用了验证集。 500张数据集200训练集train100验证集val200测试集test 每张图像有 5 个不同的高质量地面真值分割(groundTruth,是.mat文件) …

Android 中的混音器 AudioMixer 实现分析

Android framework 的音频处理模库 libaudioprocessing (位于 frameworks/av/media/libaudioprocessing) 提供了混音器组件 AudioMixer,它主要用在 audioflinger 里,用来将多路音频源数据混音,以方便送进音频设备播放出来。 音频混音操作本身…

MyBatis(九)MyBatis小技巧

一、#{}和${} #{}:先编译sql语句,再给占位符传值,底层是PreparedStatement实现。可以防止sql注入,比较常用。 ${}:先进行sql语句拼接,然后再编译sql语句,底层是Statement实现。存在sql注入现象。…

第09章_异常处理

第09章_异常处理 讲师:尚硅谷-宋红康(江湖人称:康师傅) 官网:http://www.atguigu.com 本章专题与脉络 1. 异常概述 1.1 什么是生活的异常 男主角小明每天开车上班,正常车程1小时。但是,不出…

计网第五章.运输层—TCP流量控制与可靠传输

以下来自湖科大计算机网络公开课笔记及个人所搜集资料 目录一、流量控制死锁死锁的解决:二、超时重传时间的选择解决方案Karn算法三、可靠传输补充:其实TCP的流量控制,可靠传输,拥塞控制,都是围绕滑动窗口机制来实现的…

SpringBoot的统一功能处理

目录 1.统一用户的的登录权限校验 最开始的用户登录 Spring拦截器 2.统一数据返回格式 统一数据的返回格式意义 统一数据返回格式的实现 3.统一异常处理 在上篇博客中我介绍了Spring AOP的基础知识,这篇博客则是AOP的实践练习,通过借助AOP实现三个目标 1.统一用户登录权…

VContainer 初体验

IOC 控制反转 IOC 提供一个对象生成容器,在我们需要取得某个对象时,不再使用New关键字进行对象生成操作,而是通过IOC容器内部控制来获得对象。 使用这种思想方式,可以让我们无需关心对象的生成方式,只需要告诉容器我需…

xmanager连接linux桌面教程 xmanager连接之后黑屏

xmanager 是一款专业的远程服务器管理软件,但习惯了使用Windows系统下的桌面,一时会无法适应linux服务器的命令行界面。下面我就为大家介绍xmanager连接linux桌面教程,xmanager连接之后黑屏的相关内容,让大家在使用linux更加方便。…

node.js详解

文章目录1.Node.js1.1 Node.js 模块化1.2 模块暴露数据1.2.1 模块初体验1.2.2 暴露数据1.3.导入(引入)模块1.4 JavaScript引擎1.5 什么是Node.js1.6 BFF2.包管理工具2.1 npm2.1.1 npm 的安装2.1.2 npm 基本使用2.1.2.1 初始化2.1.2.2 搜索包2.1.2.2 下载安装包2.1.2.3 require …

java遍历字符串的方法

在 java中,我们需要遍历字符串,如何遍历呢?首先我们先了解一下遍历的概念: 在我们的计算机中,存储的都是二进制数据,为了方便存储和管理,我们把一段数据分成多个字符串。在 java中,遍…

BM36-判断是不是平衡二叉树

题目 输入一棵节点数为 n 二叉树,判断该二叉树是否是平衡二叉树。 在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树 平衡二叉树(Balanced Binary Tree),具有以下性质:它是一棵空…

LabVIEW-簇数据类型

簇数据类似于 C 语言的结构体,创建时,首先将“簇”放置到前面板上: 然后放置簇内的元素,比如“数值输入控件”,当“簇框架”内边沿出现虚线框时,单击“数值输入控件”即可添加到簇中:在簇中也可以修改“数值…

常见网络协议汇总(一)

“网络协议”是指为完成特定的任务而制定的一套规则。网络协议通常用来表示数据传输中一组用于实现一个或多个OT模型级别的规则或规范。在通信时,网络协议定义了在通信时如何进行通信。今天海翎光电的小编就汇总了常见的网络协议,来一起看看。我们先回顾…

Linux基础IO(下)

Linux基础IO(下)FILE自己模拟实现fopen/fclose、fread/fwrite理解文件系统OS如何看待磁盘管理磁盘硬链接软连接ACM时间动态库和静态库见一见Linux下的库为什么要有库写一写库制作一个静态库制作一个动态库关于动静态库的一点小实验FILE 通过前面学习我们…

【SSM】Spring6(十二.Spring6集成MyBatis3.5)

文章目录1. 实现步骤2.具体实现2.1 准备数据库2.2 创建模块,引入依赖2.3 创建包2.4 创建Pojo类2.5 编写mapper接口2.6 编写Mapper配置文件2.7 编写service接口和service接口实现类2.8 编写jdbc.properties配置文件2.9 编写mybatis-config.xml配置文件2.10编写spring…