【正点原子FreeRTOS学习笔记】————(2)FreeRTOS的任务创建和删除

news/2024/4/28 13:11:19/文章来源:https://blog.csdn.net/wozhihecha/article/details/136937763

这里写目录标题

  • 一、任务创建和删除的API函数(熟悉)
  • 二、任务创建和删除(动态方法)(掌握)
  • 三、任务创建和删除(静态方法)(掌握)

一、任务创建和删除的API函数(熟悉)

任务的创建和删除本质就是调用FreeRTOS的API函数
在这里插入图片描述
动态创建任务:任务的任务控制块以及任务的栈空间所需的内存,均由 FreeRTOS 从 FreeRTOS 管理的堆中分配(自动)
静态创建任务:任务的任务控制块以及任务的栈空间所需的内存,需用户分配提供(手动)

动态创建任务函数

BaseType_t xTaskCreate
(TaskFunction_t 				     pxTaskCode,	/* 指向任务函数的指针 */	const char * const 				 pcName, 	    /* 任务名字,最大长度configMAX_TASK_NAME_LEN */const 	configSTACK_DEPTH_TYPE 	 usStackDepth, 	/* 任务堆栈大小,注意字为单位 */void * const 					     pvParameters,	/* 传递给任务函数的参数 */UBaseType_t 					     uxPriority,	/* 任务优先级,范围:0 ~ configMAX_PRIORITIES - 1 */TaskHandle_t * const 			     pxCreatedTask 	/* 任务句柄,就是任务的任务控制块 */
)

在这里插入图片描述
实现动态创建任务流程
在这里插入图片描述
此函数创建的任务会立刻进入就绪态,由任务调度器调度运行
在这里插入图片描述
任务控制块结构体成员介绍

typedef struct tskTaskControlBlock   
{volatile StackType_t 		* pxTopOfStack; 					    /* 任务栈栈顶,必须为TCB的第一个成员 */ListItem_t 			    xStateListItem;           			    /* 任务状态列表项 */ListItem_t 			    xEventListItem;					        /* 任务事件列表项 */   UBaseType_t 			    uxPriority;                				/* 任务优先级,数值越大,优先级越大 */StackType_t 			    * pxStack;						        /* 任务栈起始地址 */char 				        pcTaskName[ configMAX_TASK_NAME_LEN ]; 	/* 任务名字 */		…省略很多条件编译的成员
}  tskTCB;

任务栈栈顶,在任务切换时的任务上下文保存、任务恢复息息相关
注意:每个任务都有属于自己的任务控制块,类似身份证

静态创建任务函数

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		/* 任务控制块指针,由用户分配 */
)

在这里插入图片描述
静态创建任务使用流程
在这里插入图片描述
此函数创建的任务会立刻进入就绪态,由任务调度器调度运行
在这里插入图片描述
任务删除函数
在这里插入图片描述
用于删除已被创建的任务,被删除的任务将从就绪态任务列表、阻塞态任务列表、挂起态任务列表和事件列表中移除

注意:
1、当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)
2、空闲任务会负责释放被删除任务中由系统分配的内存,但是由用户在任务删除前申请的内存, 则需要由用户在任务被删除前提前释放,否则将导致内存泄露

删除任务流程:
在这里插入图片描述
在这里插入图片描述

二、任务创建和删除(动态方法)(掌握)

1、实验目的:学会 xTaskCreate( ) 和 vTaskDelete( ) 的使用
2、实验设计:将设计四个任务:start_task、task1、task2、task3
四个任务的功能如下:
在这里插入图片描述

#include "freertos_demo.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"/******************************************************************************************************/
/*FreeRTOS配置*/
/* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 *//* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 *//* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO      3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 *//* TASK3 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK3_PRIO      4                   /* 任务优先级 */
#define TASK3_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task3Task_Handler;  /* 任务句柄 */
void task3(void *pvParameters);             /* 任务函数 */
/******************************************************************************************************/
/* LCD刷屏时使用的颜色 */
uint16_t lcd_discolor[11] = {WHITE, BLACK, BLUE, RED,MAGENTA, GREEN, CYAN, YELLOW,BROWN, BRRED, GRAY};/*** @brief       FreeRTOS例程入口函数* @param       无* @retval      无*/void freertos_demo(void)
{lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);lcd_show_string(10, 47, 220, 24, 24, "Task Create & Del", RED);lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);lcd_draw_rectangle(5, 110, 115, 314, BLACK);lcd_draw_rectangle(125, 110, 234, 314, BLACK);lcd_draw_line(5, 130, 115, 130, BLACK);lcd_draw_line(125, 130, 234, 130, BLACK);lcd_show_string(15, 111, 110, 16, 16, "Task1: 000", BLUE);lcd_show_string(135, 111, 110, 16, 16, "Task2: 000", BLUE);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       start_task* @param       pvParameters : 传入参数(未用到)* @retval      无*/void start_task(void *pvParameters){taskENTER_CRITICAL();           /* 进入临界区 *//* 创建任务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);   /* 任务句柄 *//* 创建任务3 */xTaskCreate((TaskFunction_t )task3,                 /* 任务函数 */(const char*    )"task3",               /* 任务名称 */(uint16_t       )TASK3_STK_SIZE,        /* 任务堆栈大小 */(void*          )NULL,                  /* 传入给任务函数的参数 */(UBaseType_t    )TASK3_PRIO,            /* 任务优先级 */(TaskHandle_t*  )&Task3Task_Handler);   /* 任务句柄 */vTaskDelete(StartTask_Handler); /* 删除开始任务 */taskEXIT_CRITICAL();            /* 退出临界区 */}/*** @brief       task1* @param       pvParameters : 传入参数(未用到)* @retval      无*/void task1(void *pvParameters){uint32_t task1_num = 0;while (1){lcd_fill(6, 131, 114, 313, lcd_discolor[++task1_num % 11]);lcd_show_xnum(71, 111, task1_num, 3, 16, 0x80, BLUE);vTaskDelay(500);}}/*** @brief       task2* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task2(void *pvParameters)
{uint32_t task2_num = 0;while (1){lcd_fill(126, 131, 233, 313, lcd_discolor[11 - (++task2_num % 11)]);lcd_show_xnum(191, 111, task2_num, 3, 16, 0x80, BLUE);vTaskDelay(500);}
}
/*** @brief       task3* @param       pvParameters : 传入参数(未用到)* @retval      无*/void task3(void *pvParameters){uint8_t key = 0;while (1){key = key_scan(0);switch (key){case KEY0_PRES:                     /* 删除任务1 */{if (Task1Task_Handler != NULL){vTaskDelete(Task1Task_Handler);Task1Task_Handler = NULL;}break;}case KEY1_PRES:                     /* 删除任务2 */{if (Task2Task_Handler != NULL){vTaskDelete(Task2Task_Handler);Task2Task_Handler = NULL;}break;}default:{break;}}vTaskDelay(10);}}

三、任务创建和删除(静态方法)(掌握)

1、实验目的:学会 xTaskCreateStatic( ) 和 vTaskDelete( ) 的使用
2、实验设计:将设计四个任务:start_task、task1、task2、task3
四个任务的功能如下:
在这里插入图片描述

#include "freertos_demo.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
/******************************************************************************************************/
/*FreeRTOS配置*/
static StackType_t  IdleTaskStack[configMINIMAL_STACK_SIZE];        /* 空闲任务任务堆栈 */
static StaticTask_t IdleTaskTCB;                                    /* 空闲任务控制块 */
static StackType_t  TimerTaskStack[configTIMER_TASK_STACK_DEPTH];   /* 定时器服务任务堆栈 */
static StaticTask_t TimerTaskTCB;                                   /* 定时器服务任务控制块 *//*** @brief       获取空闲任务地任务堆栈和任务控制块内存,因为本例程使用的静态内存,因此空闲任务的任务堆栈和任务控制块的内存就应该有用户来提供,FreeRTOS提供了接口函数vApplicationGetIdleTaskMemory()实现此函数即可。* @param       ppxIdleTaskTCBBuffer:任务控制块内存ppxIdleTaskStackBuffer:任务堆栈内存pulIdleTaskStackSize:任务堆栈大小* @retval      无*/void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t  **ppxIdleTaskStackBuffer, uint32_t     *pulIdleTaskStackSize)
{*ppxIdleTaskTCBBuffer   = &IdleTaskTCB;*ppxIdleTaskStackBuffer = IdleTaskStack;*pulIdleTaskStackSize   = configMINIMAL_STACK_SIZE;
}/*** @brief       获取定时器服务任务的任务堆栈和任务控制块内存* @param       ppxTimerTaskTCBBuffer:任务控制块内存ppxTimerTaskStackBuffer:任务堆栈内存pulTimerTaskStackSize:任务堆栈大小* @retval      无*/
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,StackType_t  **ppxTimerTaskStackBuffer,uint32_t     *pulTimerTaskStackSize)
{*ppxTimerTaskTCBBuffer  = &TimerTaskTCB;*ppxTimerTaskStackBuffer= TimerTaskStack;*pulTimerTaskStackSize  = configTIMER_TASK_STACK_DEPTH;
}/* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
StackType_t StartTaskStack[START_STK_SIZE]; /* 任务堆栈 */
StaticTask_t            StartTaskTCB;       /* 任务控制块 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 *//* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
StackType_t Task1TaskStack[TASK1_STK_SIZE]; /* 任务堆栈 */
StaticTask_t            Task1TaskTCB;       /* 任务控制块 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);  /* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO      3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
StackType_t Task2TaskStack[TASK2_STK_SIZE]; /* 任务堆栈 */
StaticTask_t            Task2TaskTCB;       /* 任务控制块 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 */ /* TASK3 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK3_PRIO      4                   /* 任务优先级 */
#define TASK3_STK_SIZE  128                 /* 任务堆栈大小 */
StackType_t Task3TaskStack[TASK3_STK_SIZE]; /* 任务堆栈 */
StaticTask_t            Task3TaskTCB;       /* 任务控制块 */
TaskHandle_t            Task3Task_Handler;  /* 任务句柄 */
void task3(void *pvParameters);             /* 任务函数 *//******************************************************************************************************//* LCD刷屏时使用的颜色 */
uint16_t lcd_discolor[11] = {WHITE, BLACK, BLUE, RED,MAGENTA, GREEN, CYAN, YELLOW,BROWN, BRRED, GRAY};/*** @brief       FreeRTOS例程入口函数* @param       无* @retval      无*/
void freertos_demo(void)
{lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);lcd_show_string(10, 47, 220, 24, 24, "Task Create & Del", RED);lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);lcd_draw_rectangle(5, 110, 115, 314, BLACK);lcd_draw_rectangle(125, 110, 234, 314, BLACK);lcd_draw_line(5, 130, 115, 130, BLACK);lcd_draw_line(125, 130, 234, 130, BLACK);lcd_show_string(15, 111, 110, 16, 16, "Task1: 000", BLUE);lcd_show_string(135, 111, 110, 16, 16, "Task2: 000", BLUE);StartTask_Handler = xTaskCreateStatic((TaskFunction_t   )start_task,        /* 任务函数 */(const char*      )"start_task",      /* 任务名称 */(uint32_t         )START_STK_SIZE,    /* 任务堆栈大小 */(void*            )NULL,              /* 传递给任务函数的参数 */(UBaseType_t      )START_TASK_PRIO,   /* 任务优先级 */(StackType_t*     )StartTaskStack,    /* 任务堆栈 */(StaticTask_t*    )&StartTaskTCB);    /* 任务控制块 */vTaskStartScheduler();
}/*** @brief       start_task* @param       pvParameters : 传入参数(未用到)* @retval      无*/void start_task(void *pvParameters)
{taskENTER_CRITICAL();           /* 进入临界区 *//* 创建任务1 */Task1Task_Handler = xTaskCreateStatic((TaskFunction_t   )task1,         /* 任务函数 */(const char*      )"task1",       /* 任务名称 */(uint32_t         )TASK1_STK_SIZE,/* 任务堆栈大小 */(void*            )NULL,          /* 传递给任务函数的参数 */(UBaseType_t      )TASK1_PRIO,    /* 任务优先级 */(StackType_t*     )Task1TaskStack,/* 任务堆栈 */(StaticTask_t*    )&Task1TaskTCB);/* 任务控制块 *//* 创建任务2 */Task2Task_Handler = xTaskCreateStatic((TaskFunction_t   )task2,         /* 任务函数 */(const char*      )"task2",       /* 任务名称 */(uint32_t         )TASK2_STK_SIZE,/* 任务堆栈大小 */(void*            )NULL,          /* 传递给任务函数的参数 */(UBaseType_t      )TASK2_PRIO,    /* 任务优先级 */(StackType_t*     )Task2TaskStack,/* 任务堆栈 */(StaticTask_t*    )&Task2TaskTCB);/* 任务控制块 *//* 创建任务3 */Task3Task_Handler = xTaskCreateStatic((TaskFunction_t   )task3,         /* 任务函数 */(const char*      )"task3",       /* 任务名称 */(uint32_t         )TASK3_STK_SIZE,/* 任务堆栈大小 */(void*            )NULL,          /* 传递给任务函数的参数 */(UBaseType_t      )TASK3_PRIO,    /* 任务优先级 */(StackType_t*     )Task3TaskStack,/* 任务堆栈 */(StaticTask_t*    )&Task3TaskTCB);/* 任务控制块 */vTaskDelete(StartTask_Handler); /* 删除开始任务 */taskEXIT_CRITICAL();            /* 退出临界区 */
}/*** @brief       task1* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task1(void *pvParameters)
{uint32_t task1_num = 0;while (1){lcd_fill(6, 131, 114, 313, lcd_discolor[++task1_num % 11]);lcd_show_xnum(71, 111, task1_num, 3, 16, 0x80, BLUE);vTaskDelay(500);}
}/*** @brief       task2* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task2(void *pvParameters)
{uint32_t task2_num = 0;while (1){lcd_fill(126, 131, 233, 313, lcd_discolor[11 - (++task2_num % 11)]);lcd_show_xnum(191, 111, task2_num, 3, 16, 0x80, BLUE);vTaskDelay(500);}
}/*** @brief       task3* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task3(void *pvParameters)
{uint8_t key = 0;while (1){key = key_scan(0);switch (key){case KEY0_PRES:                     /* 删除任务1 */{if (Task1Task_Handler != NULL){vTaskDelete(Task1Task_Handler);Task1Task_Handler = NULL;}break;}case KEY1_PRES:                     /* 删除任务2 */{if (Task2Task_Handler != NULL){vTaskDelete(Task2Task_Handler);Task2Task_Handler = NULL;}break;}default:{break;}}vTaskDelay(10);}
}

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

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

相关文章

数据结构:初识树和二叉树

目前主流的方式是左孩子右兄弟表示法 我们的文件系统就是一个树 以上就是树的概念,我们今天还要来学习一种从树演变的重要的结构:二叉树 顾名思义二叉树就是一个结点最多有两个子树。 其中我们还要了解满二叉树和完全二叉树的概念 注意我们的完全二叉…

Java项目:78 springboot学生宿舍管理系统的设计与开发

作者主页:舒克日记 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 系统的角色:管理员、宿管、学生 管理员管理宿管员,管理学生,修改密码,维护个人信息。 宿管员管理公寓…

微服务高级篇(三):分布式缓存+Redis集群

文章目录 一、单点Redis的问题及解决方案二、Redis持久化2.1 单机安装Redis2.2 RDB持久化2.3 AOF持久化2.4 RDB和AOF对比 三、Redis主从3.1 搭建Redis主从架构3.1.1 集群结构3.1.2 准备实例和配置3.1.3 启动3.1.4 开启主从关系3.1.5 测试 3.2 数据同步3.2.1 全量同步【建立连接…

盏燕生物科技将出席2024第七届燕窝天然滋补品博览会

参展企业介绍 深圳市盏燕生物科技有限公司,办公室地址位于中国第一个经济特区,鹏城深圳,深圳市龙岗区平湖街道禾花社区富安大道18号亚钢工贸大楼1栋1017A,我公司主要提供一般经营项目是:初级农产品、海产品、化妆品、…

批量添加时,两个选择框为一组,不能选择一模一样的值,将不符合条件的值禁止设为禁止点击

效果展示&#xff1a; 完整代码如下&#xff1a; <template><div class"container"><div v-for"item in arr"><el-select v-model"item.name" placeholder"请选择" change"changeBox"><el-opti…

el-card设置内边距

el-card设置内边距 :deep(.el-card .el-card__body) {padding: 5px; }

Spring中常用的注解及使用规则

文章目录 前言一、Spring注解是什么&#xff1f;二、使用步骤1.注解使用 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 在学习Spring中&#xff0c;我们汇经常用到注解来简化我们的工作&#xff0c;接下来将为大家简单介绍一下常用的注解 提示&a…

如何实现无公网IP及服务器实现公网环境企业微信网页应用开发调试

文章目录 1. Windows安装Cpolar2. 创建Cpolar域名3. 创建企业微信应用4. 定义回调本地接口5. 回调和可信域名接口校验6. 设置固定Cpolar域名7. 使用固定域名校验 企业微信开发者在应用的开发测试阶段&#xff0c;应用服务通常是部署在开发环境&#xff0c;在有数据回调的开发场…

蓝桥杯真题Day40 倒计时19天 纯练题!

蓝桥杯第十三届省赛真题-统计子矩阵 题目描述 给定一个 N M 的矩阵 A&#xff0c;请你统计有多少个子矩阵 (最小 1 1&#xff0c;最大 N M) 满足子矩阵中所有数的和不超过给定的整数 K? 输入格式 第一行包含三个整数 N, M 和 K. 之后 N 行每行包含 M 个整数&#xf…

java日志技术——Logback日志框架安装及概述

前言&#xff1a; 整理下学习笔记&#xff0c;打好基础&#xff0c;daydayup!!! 日志 什么是日志 程序中的日志&#xff0c;通常就是一个文件&#xff0c;里面记录的是程序运行过程中的各种信息&#xff0c;通过日志可以进行操作分析&#xff0c;bug定位等 记录日志的方案 程…

【爬虫基础】第6讲 opener的使用

在爬虫中&#xff0c;opener是一个用来发送HTTP请求的对象。它可以用来模拟浏览器发送请求&#xff0c;包括设置请求头、处理Cookie等操作。使用opener可以实现一些高级功能&#xff0c;如模拟登录、处理验证码等。 方法1&#xff1a; from urllib.request import Request,bu…

【数据结构】顺序表的实现——静态分配

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;数据结构 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

Linux manim安装

简介 根据文档可知, manim目前分为两个版本, 一个是由3Blue1Brown维护更新的最新版本的manimgl, 另一个是稳定的社区版本manim or manimce. 两个版本在安装和使用上都有些不同, 不要搞混. Linux manim ERROR No package ‘pangocairo’ found Getting requirements to buil…

使用 .NET 和 Teams Toolkit 构建 AI 机器人、扩展 Copilot for Microsoft 365 以及更多

作者&#xff1a;Ayca Bas 排版&#xff1a;Alan Wang Teams Toolkit for Visual Studio 帮助 .NET 开发人员为 Microsoft Teams 构建、调试和发布应用程序。我们很高兴向大家宣布&#xff0c;Teams Toolkit for Visual Studio 2022 17.9 版本为 .NET 开发人员提供了许多令人兴…

【Qt】使用Qt实现Web服务器(六):QtWebApp用户名密码登录

1、示例 1)演示 2)登录 3)显示 2、源码 示例源码Demo1->LoginController void LoginController::service(HttpRequest& request, HttpResponse& response) {

Wagtail-基于Python Django的内容管理系统CMS实现公网访问

目录 前言 1. 安装并运行Wagtail 1.1 创建并激活虚拟环境 2. 安装cpolar内网穿透工具 3. 实现Wagtail公网访问 4. 固定Wagtail公网地址 前言 Wagtail是一个用Python编写的开源CMS&#xff0c;建立在Django Web框架上。Wagtail 是一个基于 Django 的开源内容管理系统&…

鸿蒙开发实战-如何开发一个字符串加解密应用程序

介绍 本Codelab针对用户隐私安全&#xff0c;使用加密算法API对密码进行加密存储&#xff0c;模拟开发一个用户注册登录应用。实现如下功能&#xff1a; 实现登录、注册、登录成功页面。注册的用户数据保存到关系型数据库。登录时通过查询数据库校验用户是否存在、密码是否正…

如何高效系统地自学 Python?

导言&#xff1a; Python作为一门流行的编程语言&#xff0c;被广泛运用于数据分析、人工智能、网络应用等领域。想要系统地自学Python&#xff0c;并掌握其核心概念和编程技能&#xff0c;需要一定的方法和步骤。本文将介绍如何高效系统地自学Python&#xff0c;让你能够快速…

docker推拉时的数据交换详解

前言 docker用了这么久了, 有没有想过, 在执行docker push 和 docker pull命令的时候, 数据是如何传递的呢? 换句话说, 如果要实现一个镜像仓库, 针对推拉的服务, 如何实现接口呢? 根据OCI 分发规范文档 的描述, 已经对整个推拉过程中要调用的接口有描述了. 但是, 纸上学来…

Linux升级GCC

文章目录 一、安装 EPEL 仓库二、更新yum三、安装 CentOS 开发工具组四、安装scl五、安装gcc 11六、启用gcc 11七、设置永久使用 一、安装 EPEL 仓库 命令&#xff1a; yum install epel-release -y二、更新yum 命令&#xff1a; yum update -y三、安装 CentOS 开发工具组 …