嵌入式实时操作系统笔记2:UCOS基础知识_UC/OS-III移植(STM32F4)_编写简单的UC/OS-III任务例程(失败.....)

 今日学习嵌入式实时操作系统RTOS:UC/OS-III实时操作系统

本文只是个人学习笔记备忘用,附图、描述等 部分都是对网上资料的整合......

文章主要研究如何将UC/OS-III 移植到 STM32 F407VET6上,提供测试工程下载

 (2024.5.21 文章未写完,测试有问题,以后再说)

 (2024.5.22 系统移植失败,测试有问题,以后再说)

 附言:网络上的资料真是参差不齐,整整浪费我一天时间......

目录

UCOS基础知识:

任务的五种状态:

 任务五种状态转换图:

UCOS-III的三大列表:

UCOS-III系统配置文件说明:

UC/OS-III移植(STM32F4):

添加 UC/OS-III 源码部分:

修改system_stm32f4xx.s启动文件代码:

修改/确定 系统时钟(SysTick)内核:

修改CONFIG/app_cfg.h:

修改CONFIG/includes.h :

尝试编写简单的 UC/OS-III 任务例程:

先引用头文件:

定义任务栈大小/优先级:

定义任务控制块TCB:

定义任务栈:

定义任务主体函数:

创建任务TASK1-2-3:

CPU_SR_ALLOC();  

OS_CRITICAL_ENTER();  

OS_CRITICAL_EXIT();

启动UCOS III 系统函数:

主函数调用情况展示:

测试效果展示:

整体测试工程下载:

网上学习资料网址贴出:


UCOS基础知识:

任务的五种状态:

 任务五种状态转换图:

1、被创建的任务,初始状态均为就绪态
2、被删除的任务,会转为休眠态
3、仅就绪态和中断态可转变成运行态
4、其他状态的任务想运行,必须先转变成就绪

UCOS-III的三大列表:

UCOS-川主要有三大类列表用来跟踪任务状态:


就绪列表  准备运行的任务将放在就绪列表:OSRdyList[x],其中x代表任务优先级数值
Tick列表   正在等待延时超时或挂起的对象超时的任务,将放在OSTickList
挂起列表   当任务等待信号量、事件时,任务将放置在挂起列表PendList

UCOS-III系统配置文件说明:

以下就是我们接下来需要移植的 部分文件,他们的作用大致各自如下:

UC/OS-III移植(STM32F4):

本次尝试移植UC/OS-III 于立创梁山派天空星开发板上,芯片型号是STM32F407VET6

其中UC/OS-III 的源码可以在整体工程下载中的压缩包内找到

注意:这里的源码是被我阉割过的,削除了官方文件中不必要的文件与目录

其次就是网络上那些所谓提供UC/OS源码或者教程的,如果没有移植成功的工程供下载的案例,基本都是垃圾!浪费时间!不是缺少文件,就是解释不详细,缺步漏步!

本人也是在艰难的学习中掉进太多移植源码方面的坑里了.........

添加 UC/OS-III 源码部分

在工程中新建几个分组:

uC-OS3/CPU

uC-OS3/LIB

uC-OS3/PORT

uC-OS3/SOURCE

uC-OS3/CONFIG
 

点击uC-OS3/CPU–>Add Files

UC-OSIII/CPU添加以下文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

点击uC-OS3/CPU–>Add Files

UCOSIII\bsp添加以下文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

点击uC-OS3/LIB–>Add Files

UCOSIII\uC-LIB添加以下所有文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

点击uC-OS3/PORT–>Add Files

UCOSIII\uCOS-III\Ports添加以下所有文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

点击uC-OS3/SOURCE–>Add Files

UCOSIII\uCOS-III\Source添加以下所有文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

uC-OS3/CONFIG添加文件:

UCOSIII\config添加以下所有文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

最后别忘记在魔棒中添加各个文件路径:

补:补充添加一条bsp的路径,之前忘记添加了,导致报错......

添加结束,编译看看有无报错缺漏:

这里也是完美无报错的典范了哈哈哈......

修改system_stm32f4xx.s启动文件代码:

打开工程自带的 system_stm32f4xx.s启动文件(这是启动文件,不是UC/OS源码!)

我们需要对其进行一些修改:

1

第80行框出代码修改:

                DCD     OS_CPU_PendSVHandler             ; PendSV HandlerDCD     OS_CPU_SysTickHandler            ; SysTick Handler

第220行框出代码修改:

OS_CPU_PendSVHandler\PROCEXPORT  OS_CPU_PendSVHandler       [WEAK]B       .ENDP
OS_CPU_SysTickHandler\PROCEXPORT  OS_CPU_SysTickHandler      [WEAK]B       .ENDP

最后编译检查无问题:

修改/确定 系统时钟(SysTick)内核:

这里我还特意出去学习了一下系统内核时钟的初始化等知识:并附文:

STM32F407VET6 学习笔记3:内核定时器SystemTick(SysTick)初始化中断-CSDN博客

/*** This function will initial stm32 board.*/
void board_init(void)
{/* NVIC Configuration */
#define NVIC_VTOR_MASK              0x3FFFFF80
#ifdef  VECT_TAB_RAM/* Set the Vector Table base location at 0x10000000 */SCB->VTOR  = (0x10000000 & NVIC_VTOR_MASK);
#else  /* VECT_TAB_FLASH  *//* Set the Vector Table base location at 0x08000000 */SCB->VTOR  = (0x08000000 & NVIC_VTOR_MASK);
#endifSysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); //Systick 时钟源频率168M// 计算SysTick重装载值(SystemCoreClock为168MHz,希望SysTick中断频率为1ms(1000 Hz))//SysTick_LOAD = (SystemCoreClock / TickRate) - 1uint32_t reload = SystemCoreClock / 1000 - 1; // 1ms中断频率  SysTick->LOAD = reload;  // 清除SysTick当前值并启动SysTick,同时使能中断SysTick->VAL  = 0; // 清空当前值  SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;  /* 设置NVIC优先级分组 */  // 4位抢占优先级和0位子优先级  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);   /* 设置SysTick中断的优先级 */  // 设置SysTick的抢占优先级为3(最低),没有子优先级(因为分组4没有子优先级位)  NVIC_SetPriority(SysTick_IRQn, 3); // 注意:优先级值根据分组设置可能有所不同 }
// 声明SysTick中断处理函数  
void SysTick_Handler(void)
{OSIntEnter();		      //进入中断OSTimeTick();       //调用ucos的时钟服务程序               OSIntExit();        //触发任务切换软中断
}

修改CONFIG/app_cfg.h:

#define APP_CFG_SERIAL_EN        DEF_ENABLED ------>

#define APP_CFG_SERIAL_EN        DEF_DISABLED

改后如下:

#define APP_TRACE BSP_Ser_Printf --------> #define APP_TRACE (void)

修改CONFIG/includes.h :

尝试编写简单的 UC/OS-III 任务例程:

先引用头文件:

/*****************UC/OS头文件***************/
#include "os.h"
#include "os_cpu_bsp.h"
#include <app_cfg.h>
#include <cpu_core.h>
#include <os_app_hooks.h>
#include <cpu.h>
/* USER CODE END Includes */

定义任务栈大小/优先级:


//任务栈大小定义
#define  START_STK_SIZE                     128
#define  TASK1_STK_SIZE                     128
#define  TASK2_STK_SIZE                     128
#define  TASK3_STK_SIZE                     128
//任务优先级定义
#define  APP_TASK_START_PRIO                     4
#define  APP_TASK_1_PRIO                         5
#define  APP_TASK_2_PRIO                         6
#define  APP_TASK_3_PRIO                         7

定义任务控制块TCB:

//创建任务控制块
static OS_TCB Start_Task_TCB;
static OS_TCB Task1_TCB;
static OS_TCB Task2_TCB;
static OS_TCB Task3_TCB;

定义任务栈:

//任务堆栈	
CPU_STK START_TASK_STK[START_STK_SIZE];
CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE];
CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE];
CPU_STK TASK3_TASK_STK[TASK3_STK_SIZE];

定义任务主体函数:

这个放置在主函数下面吧就:

任务里面一定要有阻塞延时,如果这个任务的优先级最高且没有阻塞延时,那么操作系统就只会执行这一个任务,其他的任务就得不到执行。

注意:这里的    OSTimeDly ( 2000, OS_OPT_TIME_DLY, & err ); 对应的延时 不仅与 内传的参数 有关 还与 内核定时器SystemTick 有关:

创建任务TASK1-2-3:

各个TASK的任务如下描述:

//TASK_1 报告自己执行次数(2s),并在执行8次后删除 TASK_2

//TASK_2 串口报告自己执行的次数 (4s)

//这里的 TASK_3 会每隔 17S 恢复TASK_2 (全新的开始)
/*
    创建一个全新的任务实例,而不是简单地“恢复”一个已经被删除的任务。
  这意味着新的任务实例将拥有自己独立的堆栈(stack)和其他资源,而原来的任务实例(如果已经被删除)的资源将被释放
*/

//TASK_1 报告自己执行次数(2s),并在执行8次后删除 TASK_2
void TASK_1(void)
{OS_ERR  err;			// 定义一个“错误” 变量用来存放一些错误的类型int TASK1_num=0;  //记录任务TASK_1执行次数//在某些嵌入式系统中,进入和退出关键区域可能需要禁用中断,以防止在关键代码执行过程中被中断打断。	CPU_SR_ALLOC();   //为保存和恢复CPU的状态寄存器(Status Register)或中断状态做准备工作。OS_CRITICAL_ENTER();/* 此处添加不希望被打断的硬件初始化代码等......*/OS_CRITICAL_EXIT();while(1){TASK1_num++;	//任务TASK_1执行次数加1if(TASK1_num%8==0){OSTaskDel((OS_TCB*)&Task2_TCB,&err);	        //任务1每执行8次后(即16s时) 删除掉任务2printf("TASK_1 has Deleted the TASK_2 !\r\n");//打印报告	任务1 删除了 任务2}UsartPrintf(USART1,"TASK_1 has Carred out %d times! \r\n",TASK1_num);	//打印测试字符串(并报告TASK_1执行次数)OSTimeDly ( 2000, OS_OPT_TIME_DLY, & err ); //使当前任务延迟指定的时间(2s):  (让当前任务放弃CPU一段时间,CPU让给其余任务)}
}//TASK_2 串口报告自己执行的次数 (4s)
void TASK_2(void)
{OS_ERR  err;			// 定义一个“错误” 变量用来存放一些错误的类型int TASK2_num=0;  //记录任务TASK_2执行次数while(1){UsartPrintf(USART1,"TASK_2 has Carred out %d times! \r\n",TASK2_num);	//打印测试字符串(并报告TASK_2执行次数)OSTimeDly ( 4000, OS_OPT_TIME_DLY, & err );//使当前任务延迟指定的时间(4S):  (让当前任务放弃CPU一段时间,CPU让给其余任务) }
}//这里的 TASK_3 会每隔 17S 恢复TASK_2 (全新的开始)
/*创建一个全新的任务实例,而不是简单地“恢复”一个已经被删除的任务。这意味着新的任务实例将拥有自己独立的堆栈(stack)和其他资源,而原来的任务实例(如果已经被删除)的资源将被释放
*/
void TASK_3(void)
{OS_ERR  err;			// 定义一个“错误” 变量用来存放一些错误的类型int TASK3_num=0;  //记录任务TASK_3执行次数CPU_SR_ALLOC();OS_CRITICAL_ENTER();	//进入临界区			 //重新创建TASK2任务OSTaskCreate((OS_TCB 	* )&Task2_TCB,		(CPU_CHAR	* )"TASK_2", 		(OS_TASK_PTR )TASK_2, 			(void		* )0,					(OS_PRIO	  )TASK2_PRIO,     	(CPU_STK   * )&TASK2_TASK_STK[0],	(CPU_STK_SIZE)TASK2_STK_SIZE/10,	(CPU_STK_SIZE)TASK2_STK_SIZE,		(OS_MSG_QTY  )0,					(OS_TICK	  )0,					(void   	* )0,				(OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR 	* )&err);	OS_CRITICAL_EXIT();	//退出临界区	 		while(1){UsartPrintf(USART1,"TASK_3 has Resume the TASK_2 %d times! \r\n",TASK3_num);	//打印测试字符串(并报告TASK_3执行次数)							 OSTimeDly ( 17000, OS_OPT_TIME_DLY, & err );//使当前任务延迟指定的时间(17S):  (让当前任务放弃CPU一段时间,CPU让给其余任务) }
}//开始任务任务函数
void start_task(void *p_arg)
{OS_ERR err;CPU_SR_ALLOC();p_arg = p_arg;CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0uOSStatTaskCPUUsageInit(&err);  	//统计任务                
#endif#ifdef CPU_CFG_INT_DIS_MEAS_EN		//如果使能了测量中断关闭时间CPU_IntDisMeasMaxCurReset();	
#endif#if	OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候//使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5msOSSchedRoundRobinCfg(DEF_ENABLED,1,&err);  
#endif	OS_CRITICAL_ENTER();	//进入临界区//创建TASK1任务OSTaskCreate((OS_TCB 	* )&Task1_TCB,				          //任务控制块(CPU_CHAR	* )"TASK_1", 	 		                  //任务名字	(OS_TASK_PTR )TASK_1, 			            //任务函数(void		* )0,					                //传递给任务函数的参数					(OS_PRIO	  )TASK1_PRIO,     (CPU_STK   * )&TASK1_TASK_STK[0],	(CPU_STK_SIZE)TASK1_STK_SIZE/10,	(CPU_STK_SIZE)TASK1_STK_SIZE,		(OS_MSG_QTY  )0,					(OS_TICK	  )0,					(void   	* )0,					(OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,(OS_ERR 	* )&err);				//创建TASK2任务OSTaskCreate((OS_TCB 	* )&Task2_TCB,		(CPU_CHAR	* )"TASK_2", 		(OS_TASK_PTR )TASK_2, 			(void		* )0,					(OS_PRIO	  )TASK2_PRIO,     	(CPU_STK   * )&TASK2_TASK_STK[0],	(CPU_STK_SIZE)TASK2_STK_SIZE/10,	(CPU_STK_SIZE)TASK2_STK_SIZE,		(OS_MSG_QTY  )0,					(OS_TICK	  )0,					(void   	* )0,				(OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR 	* )&err);		//创建TASK3任务OSTaskCreate((OS_TCB 	* )&Task3_TCB,		(CPU_CHAR	* )"TASK_3", 		(OS_TASK_PTR )TASK_3, 			(void		* )0,					(OS_PRIO	  )TASK3_PRIO,     	(CPU_STK   * )&TASK3_TASK_STK[0],	(CPU_STK_SIZE)TASK3_STK_SIZE/10,	(CPU_STK_SIZE)TASK3_STK_SIZE,		(OS_MSG_QTY  )0,					(OS_TICK	  )0,					(void   	* )0,				(OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR 	* )&err);	OS_CRITICAL_EXIT();	//退出临界区OSTaskDel((OS_TCB*)0,&err);	//删除start_task任务自身
}

CPU_SR_ALLOC();  

OS_CRITICAL_ENTER();  

OS_CRITICAL_EXIT();

	//在某些嵌入式系统中,进入和退出关键区域可能需要禁用中断,以防止在关键代码执行过程中被中断打断。	CPU_SR_ALLOC();   //为保存和恢复CPU的状态寄存器(Status Register)或中断状态做准备工作。/*OS_CRITICAL_ENTER();这个函数通常用于进入一个关键区域。在进入关键区域之前,它可能会禁用中断(如果之前通过CPU_SR_ALLOC();已经做了相关准备),或者通过其他机制(如锁)来确保没有其他线程或中断可以访问当前线程正在使用的共享资源。通过禁用中断或获得锁,OS_CRITICAL_ENTER();确保了代码的关键部分在执行时不会被其他任务或中断打断,从而保证了数据的一致性和操作的原子性。*/OS_CRITICAL_ENTER();/*OS_CRITICAL_EXIT();这个函数用于退出之前由OS_CRITICAL_ENTER();进入的关键区域。在退出关键区域时,它可能会重新启用之前被禁用的中断,或者释放之前获得的锁。这样做允许其他任务或中断再次访问之前被保护的共享资源*/OS_CRITICAL_EXIT();

启动UCOS III 系统函数:

//启动UCOS III 系统 !
void UCOS_III_init(void)
{OS_ERR err;CPU_SR_ALLOC();OSInit(&err);		      //初始化UCOSIIIOS_CRITICAL_ENTER();	//进入临界区			 //创建开始任务OSTaskCreate((OS_TCB 	* )&Start_Task_TCB,		      //任务控制块(CPU_CHAR	* )"start_task", 		            //任务名字(OS_TASK_PTR )start_task, 			    //任务函数(void		* )0,					            //传递给任务函数的参数(OS_PRIO	  )START_TASK_PRIO,       //任务优先级(CPU_STK   * )&START_TASK_STK[0],	//任务堆栈基地址(CPU_STK_SIZE)START_STK_SIZE/10,	  //任务堆栈深度限位(CPU_STK_SIZE)START_STK_SIZE,		  //任务堆栈大小(OS_MSG_QTY  )0,				//任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息(OS_TICK	  )0,					//当使能时间片轮转时的时间片长度,为0时为默认长度,(void   	* )0,					//用户补充的存储区(OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项(OS_ERR 	* )&err);			//存放该函数错误时的返回值OS_CRITICAL_EXIT();	//退出临界区	 OSStart(&err);      //开启UCOSIII	 
}

主函数调用情况展示:

网上学习资料网址贴出:

第3讲 UCOS基础知识_哔哩哔哩_bilibili

uCosII移植STM32F407教程_stm32f407 ucos-CSDN博客

基于stm32cubemx移植uC/OS-III操作系统_cubemx ucos-CSDN博客

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

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

相关文章

明天(周六)下午!武汉Linux爱好者线下沙龙,我们在华中科技大学等你!

2024 年 5月 25 日&#xff08;周六&#xff09;下午&#xff0c;我们将在「武汉市洪山区」 珞喻路 1037 号华中科技大学南五楼 613 室举办武汉 Linux 爱好者线下沙龙&#xff08;WHLUG&#xff09;&#xff0c;欢迎广大 Linux 爱好者来到现场&#xff0c;与我们一同交流技术&a…

【Spring】SSM介绍_SSM整合

1、SSM介绍 1.1简介 SSM&#xff08;Spring SpringMVC MyBatis&#xff09;整合是一种流行的Java Web应用程序框架组合&#xff0c;它将Spring框架的核心特性、SpringMVC作为Web层框架和MyBatis作为数据访问层框架结合在一起。这种整合方式提供了从数据访问到业务逻辑处理再…

构建智能化的语言培训教育技术架构:挑战与机遇

随着全球化的发展和人们对语言学习需求的增长&#xff0c;语言培训教育行业正面临着越来越多的挑战和机遇。在这个背景下&#xff0c;构建智能化的语言培训教育技术架构成为提升服务质量和效率的重要手段。本文将探讨语言培训教育行业的技术架构设计与实践。 一、智能化教学平台…

接口响应断言

目录 接口断言介绍接口断言方式介绍响应状态码断言 课程目标 掌握什么是接口断言。了解接口断言的多种方式。掌握如何对响应状态码完成断言。 思考 这两段代码是完整的接口自动化测试代码吗&#xff1f; …省略… when().get(“https://httpbin.ceshiren.com/get?namead&…

Golang | Leetcode Golang题解之第109题有序链表转换二叉搜索树

题目&#xff1a; 题解&#xff1a; var globalHead *ListNodefunc sortedListToBST(head *ListNode) *TreeNode {globalHead headlength : getLength(head)return buildTree(0, length - 1) }func getLength(head *ListNode) int {ret : 0for ; head ! nil; head head.Next…

AI视频智能分析技术赋能营业厅:智慧化管理与效率新突破

一、方案背景 随着信息技术的快速发展&#xff0c;图像和视频分析技术已广泛应用于各行各业&#xff0c;特别是在营业厅场景中&#xff0c;该技术能够有效提升服务质量、优化客户体验&#xff0c;并提高安全保障水平。TSINGSEE青犀智慧营业厅视频管理方案旨在探讨视频监控和视…

爬虫基础1

一、爬虫的基本概念 1.什么是爬虫&#xff1f; 请求网站并提取数据的自动化程序 2.爬虫的分类 2.1 通用爬虫&#xff08;大而全&#xff09; 功能强大&#xff0c;采集面广&#xff0c;通常用于搜索引擎&#xff1a;百度&#xff0c;360&#xff0c;谷歌 2.2 聚焦爬虫&#x…

Linux 如何用上次的checkpoint文件dist_train.sh 接着训练【mmdetection】

在Linux环境下&#xff0c;如果你想要用上一次的checkpoint文件继续训练&#xff0c;你可以在你的dist_train.sh脚本中设置--resume_from参数。这个参数指定了checkpoint文件的路径&#xff0c;训练会从该文件的状态继续进行。 例如&#xff0c;如果你的checkpoint文件名为las…

LAMDA面试准备(2024-05-23)

有没有学习过机器学习&#xff0c;提问了 FP-Growth 相比 Apriori 的优点 1. 更高的效率和更少的计算量&#xff08;时间&#xff09; FP-Growth 通过构建和遍历 FP-树 (Frequent Pattern Tree) 来挖掘频繁项集&#xff0c;而不需要像 Apriori 那样生成和测试大量的候选项集。具…

IDEA 将多个微服务Springboot项目Application启动类添加到services标签,统一启动、关闭服务

IDEA 将多个微服务Springboot项目Application启动类添加到services标签&#xff0c;统一启动、关闭服务 首先在Views > Tool Windows > Services 添加services窗口 点击services窗口&#xff0c;首次需要添加配置类型&#xff0c;我们选择Springboot 默认按照运行状态分…

LiveGBS流媒体平台GB/T28181用户手册-用户管理:添加用户、编辑、关联通道、搜索、重置密码

LiveGBS流媒体平台GB/T28181用户手册-用户管理:添加用户、编辑、关联通道、搜索、重置密码 1、用户管理1.1、添加用户1.2、编辑用户1.3、关联通道1.4、重置密码1.5、搜索1.6、删除 2、搭建GB28181视频直播平台 1、用户管理 1.1、添加用户 添加用户&#xff0c;可以配置登陆用户…

Node.js —— 前后端的身份认证 之用 express 实现 JWT 身份认证

JWT的认识 什么是 JWT JWT&#xff08;英文全称&#xff1a;JSON Web Token&#xff09;是目前最流行的跨域认证解决方案。 JWT 的工作原理 总结&#xff1a;用户的信息通过 Token 字符串的形式&#xff0c;保存在客户端浏览器中。服务器通过还原 Token 字符串的形式来认证用…

如何彻底搞懂装饰器(Decorator)设计模式?

对于任何一个软件系统而言&#xff0c;往现有对象中添加新功能是一种不可避免的实现场景&#xff0c;但这一实现过程对现有系统的影响可大可小。从架构设计上讲&#xff0c;我们也知道存在一个开闭原则&#xff08;Open-Closed Principle&#xff0c;OCP&#xff09;&#xff0…

抖音极速版:抖音轻量精简版本,新人享大福利

和快手一样&#xff0c;抖音也有自己的极速版&#xff0c;可视作抖音的轻量精简版&#xff0c;更专注于刷视频看广告赚钱&#xff0c;收益比抖音要高&#xff0c;可玩性更佳。 抖音极速版简介 抖音极速版是一个提供短视频创业和收益任务的平台&#xff0c;用户可以通过观看广…

Spring系列-03-BeanFactory和Application接口和相关实现

BeanFactory BeanFactory和它的子接口们 BeanFactory 接口的所有子接口, 如下图 BeanFactory(根容器)-掌握 BeanFactory是根容器 The root interface for accessing a Spring bean container. This is the basic client view of a bean container; further interfaces such …

【Linux网络】端口及UDP

文章目录 1.再看四层2.端口号2.1引入linux端口号和进程pid的区别端口号是如何生成的传输层有了pid还设置端口号端口号划分 2.2问题2.3netstat 3.UDP协议3.0每学一个协议 都要讨论一下问题3.1UDP协议3.2谈udp/tcp实际上是在讨论什么&#xff1f; 1.再看四层 2.端口号 端口号(Po…

sw套合样条曲线

套合样条曲线,可以变成一条曲线,然后可以进行分段

吉林大学软件工程易错题

1.【单选题】软件工程方法是&#xff08; &#xff09;。 A、为开发软件提供技术上的解决方法 &#xff08;软件工程方法 &#xff09; B、为支持软件开发、维护、管理而研制的计算机程序系统&#xff08;软件工程工具&#xff09; …

码蹄集部分题目(2024OJ赛16期;单调栈集训+差分集训)

&#x1f9c0;&#x1f9c0;&#x1f9c0;单调栈集训 &#x1f96a;单调栈 单调递增栈伪代码&#xff1a; stack<int> st; for(遍历数组) {while(栈不为空&&栈顶元素大于当前元素)//单调递减栈就是把后方判断条件变为小于等于即可{栈顶元素出栈;//同时进行其他…

react antd中transfer穿梭框组件中清除搜索框内容

如图&#xff1a;需要清除search搜索框内容 antd的transfer穿梭框组件未提供入口修改input框的值。 2种方法修改。 1、直接操作dom元素设置值&#xff08;不推荐&#xff09; useEffect(() > {const searchInput document.querySelector(.ant-transfer-list-search input)…