当前位置: 首页 > news >正文

FreeRTOS任务管理

 1. 任务状态理论讲解

 定时器职中断周期此处的1000Hz表示的是没次间隔1毫秒就记一次数(在FreeConfig.h)文件中进行配置

#define configTICK_RATE_HZ			( ( TickType_t ) 1000 )

判断是否需要任务切换在FreeRTOS里面每次间隔1毫秒切换一次(程序辅助理解图如下所示)

 FreeRTOS中三种状态的切换(分别是就绪态,阻塞态,暂停态),三种状态的理解图如下说所示

2. 任务状态实验

对应程序:08_freertos_example_task_status

  • 任务切换的基础:tick中断

  • 有哪些任务状态?状态切换图

  • 怎么管理不同状态的任务:放在不同链表里

  • 阻塞状态(Blocked)举例:vTaskDelay函数

  • 暂停状态(Suspended)举例:vTaskSuspend/vTaskResume

任务状态理解图展示

程序测试过程中遇到的问题

Load "F:\\STM32Study\\FreeRTOS_WDS\\1-6freertos_example_createtaskstatic\\FreeRTOS\\Demo\\CORTEX_STM32F103_Keil\\RTOSDemo.axf" 
BS \\RTOSDemo\main.c\200, 1
WS 1, `ch
LA `task1flagrun
___^
*** error 34: undefined identifier
LA `task2flagrun
___^
*** error 34: undefined identifier
LA `task3flagrun
___^
*** error 34: undefined identifier
*** error 65: access violation at 0x4002100C : no 'write' permission
*** error 65: access violation at 0x40021010 : no 'write' permission

解决问题参考文章

Keil Debug——*** error 65: access violation at 0x20005000 : no ‘write‘ permission_*** error 65: access violation at 0x4002100c : no -CSDN博客文章浏览阅读840次,点赞2次,收藏5次。当遇到"*** error 65: access violation at 0x20005000 : no 'write' permission"类似错误时,这通常表示程序试图写入一个没有写入权限的内存地址。这个错误可能有多种原因,以下是一些常见的解决方法:1. 检查内存保护设置:请确保您的程序没有试图写入受保护的内存区域。某些嵌入式系统可能使用内存保护机制,如存储器保护单元(MPU)或写保护寄存器。请检查您的系统文档或参考手册,了解如何正确配置内存保护设置。_*** error 65: access violation at 0x4002100c : no 'write' permissionhttps://blog.csdn.net/weixin_44406127/article/details/134159125

具体修改方式如下所示

测试代码

// 定义一个全局标记为用于表示任务是否在运行
static int task1flagrun = 0;
static int task2flagrun = 0;
static int task3flagrun = 0;TaskHandle_t xHandleTask1;   // 任务1的句柄
TaskHandle_t xHandleTask2;   // 任务2的句柄
TaskHandle_t xHandleTask3;   // 任务3的句柄void Task1Function(void * pram){// 获取TickCount的函数TickType_t tStart = xTaskGetTickCount();TickType_t t;// 添加标记位int flag  = 0;while(1){t = xTaskGetTickCount();task1flagrun = 1;task2flagrun = 0;task3flagrun = 0;printf("1"); if(!flag && (t > tStart + 10)){vTaskSuspend(xHandleTask3);   // 命令任务3进入暂停状态flag = 1;}if(t > tStart + 20){vTaskResume(xHandleTask3);    // 调用Resume进入就绪状态}}
}void Task2Function(void * pram){int i = 0;while(1){task1flagrun = 0;task2flagrun = 1;task3flagrun = 0;printf("2");// 让任务2进入到阻塞状态vTaskDelay(10);  // 这个是系统的延迟函数,主动进入阻塞状态,// 等待某个时刻的到来,这个时刻就是当前时间加上10个tick}
}void Task3Function(void * pram){while(1){task1flagrun = 0;task2flagrun = 0;task3flagrun = 1;printf("3");}
}void TaskGenericFunction(void * pram){int val = (int) pram;while(1){task1flagrun = 0;task2flagrun = 0;task3flagrun = 1;printf("%d",val);}
}StackType_t xTask3Stack[100];
StaticTask_t xTask3TCB;
// 创建空闲的任务(创建静态任务的时候要编写一个函数让CPU在空闲的状态下也不能闲着)
StackType_t xIdleTaskStack[100];
StaticTask_t xIdleTaskTCB;// 提供空闲栈的大小
void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,StackType_t ** ppxIdleTaskStackBuffer,uint32_t * pulIdleTaskStackSize
){*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;*ppxIdleTaskStackBuffer = xIdleTaskStack;*pulIdleTaskStackSize = 100;
}int main( void )
{#ifdef DEBUGdebug();
#endifprvSetupHardware();printf("Hello, world!\r\n");xTaskCreate(Task1Function,"Task1",100,NULL,1,&xHandleTask1);xTaskCreate(Task2Function,"Task2",100,NULL,1,NULL);xHandleTask3 = xTaskCreateStatic(Task3Function,"task3",100,NULL,1,xTask3Stack,&xTask3TCB);vTaskStartScheduler();/* Will only get here if there was not enough heap space to create theidle task. */return 0;
}

 测试程序PWM波形图

3. vTaskDelay和vTaskDelayUntil原理用法

对应程序:09_freertos_example_delay

有两个Delay函数:

  • vTaskDelay:至少等待指定个数的Tick Interrupt才能变为就绪状态

  • vTaskDelayUntil

    • 老版本,没有返回值

    • 等待到指定的绝对时刻,才能变为就绪态。

  • xTaskDelayUntil

    • 新版本,返回pdTRUE表示确实延迟了,返回pdFALSE表示没有发生延迟(因为延迟的时间点早就过了)

    • 等待到指定的绝对时刻,才能变为就绪态。

遇到这个问题:遇到不恰当的争论

 这个问题的原因是在keil结束断点调试的时候没有吧断点取消掉,然后就会一直报这个错误,并且KEIL无法关闭,调试完程序后一定要吧keil关闭掉

代码测试过程中遇到的问题

解决问题的博客:解决调试时候出现的“Encountered an improper argument”错误-CSDN博客文章浏览阅读2.6w次,点赞23次,收藏30次。今天分享一个我们在调试时候出现的一个错误,同时这个错误让我的工程也崩了好几十次。_encountered an improper argumenthttps://blog.csdn.net/OMGMac/article/details/126614887

测试程序的代码

 

// 定义一个全局标记为用于表示任务是否在运行
static int task1flagrun = 0;
static int task2flagrun = 0;
static int task3flagrun = 0;static int rands[] = {10,3,6,8,9,99,66};TaskHandle_t xHandleTask1;   // 任务1的句柄
TaskHandle_t xHandleTask2;   // 任务2的句柄
TaskHandle_t xHandleTask3;   // 任务3的句柄void Task1Function(void * pram){// 获取TickCount的函数TickType_t tStart = xTaskGetTickCount();int i = 0;int j = 0;while(1){task1flagrun = 1;task2flagrun = 0;task3flagrun = 0;// 延时函数执行的时间是不固定的for(i = 0; i <rands[j]; i++){printf("1"); 	}j++;if(j == 7){j = 0;}vTaskDelay(20);	}
}void Task2Function(void * pram){int i = 0;while(1){task1flagrun = 0;task2flagrun = 1;task3flagrun = 0;printf("2");}
}void Task3Function(void * pram){while(1){task1flagrun = 0;task2flagrun = 0;task3flagrun = 1;printf("3");}
}void TaskGenericFunction(void * pram){int val = (int) pram;while(1){task1flagrun = 0;task2flagrun = 0;task3flagrun = 1;printf("%d",val);}
}StackType_t xTask3Stack[100];
StaticTask_t xTask3TCB;
// 创建空闲的任务(创建静态任务的时候要编写一个函数让CPU在空闲的状态下也不能闲着)
StackType_t xIdleTaskStack[100];
StaticTask_t xIdleTaskTCB;// 提供空闲栈的大小
void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,StackType_t ** ppxIdleTaskStackBuffer,uint32_t * pulIdleTaskStackSize
){*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;*ppxIdleTaskStackBuffer = xIdleTaskStack;*pulIdleTaskStackSize = 100;
}int main( void )
{#ifdef DEBUGdebug();
#endifprvSetupHardware();printf("Hello, world!\r\n");xTaskCreate(Task1Function,"Task1",100,NULL,2,&xHandleTask1);xTaskCreate(Task2Function,"Task2",100,NULL,1,NULL);xHandleTask3 = xTaskCreateStatic(Task3Function,"task3",100,NULL,1,xTask3Stack,&xTask3TCB);vTaskStartScheduler();/* Will only get here if there was not enough heap space to create theidle task. */return 0;
}

编写代码后程序的执行结果展示:PWM波形结果展示vTaskDelay()这个函数可以保证休眠的时间是一样的但是无法保证程序执行的时刻间隔是一样的

vTaskDelayUntil函数的含义

测试代码

// 定义一个全局标记为用于表示任务是否在运行
static int task1flagrun = 0;
static int task2flagrun = 0;
static int task3flagrun = 0;static int rands[] = {10,3,6,8,9,99,66};TaskHandle_t xHandleTask1;   // 任务1的句柄
TaskHandle_t xHandleTask2;   // 任务2的句柄
TaskHandle_t xHandleTask3;   // 任务3的句柄void Task1Function(void * pram){// 获取TickCount的函数,表示将启动的时间记录下来TickType_t tStart = xTaskGetTickCount();int i = 0;int j = 0;while(1){task1flagrun = 1;task2flagrun = 0;task3flagrun = 0;// 延时函数执行的时间是不固定的for(i = 0; i <rands[j]; i++){printf("1"); 	}j++;if(j == 7){j = 0;}
#if 0 vTaskDelay(20);	
#elsevTaskDelayUntil(&tStart,20);
#endif}
}void Task2Function(void * pram){int i = 0;while(1){task1flagrun = 0;task2flagrun = 1;task3flagrun = 0;printf("2");}
}void Task3Function(void * pram){while(1){task1flagrun = 0;task2flagrun = 0;task3flagrun = 1;printf("3");}
}void TaskGenericFunction(void * pram){int val = (int) pram;while(1){task1flagrun = 0;task2flagrun = 0;task3flagrun = 1;printf("%d",val);}
}StackType_t xTask3Stack[100];
StaticTask_t xTask3TCB;
// 创建空闲的任务(创建静态任务的时候要编写一个函数让CPU在空闲的状态下也不能闲着)
StackType_t xIdleTaskStack[100];
StaticTask_t xIdleTaskTCB;// 提供空闲栈的大小
void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,StackType_t ** ppxIdleTaskStackBuffer,uint32_t * pulIdleTaskStackSize
){*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;*ppxIdleTaskStackBuffer = xIdleTaskStack;*pulIdleTaskStackSize = 100;
}int main( void )
{#ifdef DEBUGdebug();
#endifprvSetupHardware();printf("Hello, world!\r\n");xTaskCreate(Task1Function,"Task1",100,NULL,2,&xHandleTask1);xTaskCreate(Task2Function,"Task2",100,NULL,1,NULL);xHandleTask3 = xTaskCreateStatic(Task3Function,"task3",100,NULL,1,xTask3Stack,&xTask3TCB);vTaskStartScheduler();/* Will only get here if there was not enough heap space to create theidle task. */return 0;
}

PWM波形展示

4. 空闲任务及其钩子函数

对应程序:10_freertos_example_idletask,在05_freertos_example_createtask基础上修改

  • 任务后的清理工作在哪执行?分两类:

    • 自杀的任务:在空闲任务中完成清理工作,比如释放内存(都自杀了,怎么清理自己的尸体? 由别人来做)

    • 非自杀的任务:在vTaskDelete内部完成清理工作(凶手执行清理工作)

  • 空闲任务何时才能执行?

  • 空闲任务只能处于这2个状态之一:Running、Ready

  • 空闲任务钩子函数

    • 执行一些低优先级的、后台的、需要连续执行的函数

    • 测量系统的空闲时间:空闲任务能被执行就意味着所有的高优先级任务都停止了,所以测量空闲任 务占据的时间,就可以算出处理器占用率。

    • 让系统进入省电模式:空闲任务能被执行就意味着没有重要的事情要做,当然可以进入省电模式 了。

    • 绝对不能导致任务进入Blocked、Suspended状态

    • 如果你会使用 vTaskDelete() 来删除任务,那么钩子函数要非常高效地执行。如果空闲任务移植 卡在钩子函数里的话,它就无法释放内存。

空闲任务和钩子函数

定时宏:实现函数(这个钩子函数有一定的限制就是不能让空闲的任务进入空闲的状态或者是阻塞的状态要让空闲的任务执行一些清理的状态,因此空闲的任务要么处于运行状态,要么处于就绪状态永远不能处于阻塞状态,钩子函数执行的速度要越快越好)

实现代码

void Task2Function(void * param);// 这个是任务的标志位
static int task1flagrun = 0;
static int task2flagrun = 0;
static int taskidleflagrun = 0;// 在主函数中创建任务1,在任务1里面创建任务2,并在任务1中删除任务2
void Task1Function(void * param)
{TaskHandle_t xHandleTask2;BaseType_t xReturn;while (1){// 在任务1里面设置对应的变量task1flagrun = 1;task2flagrun = 0;taskidleflagrun = 0;printf("1");// 保存这个函数的返回值xReturn = xTaskCreate(Task2Function, "Task2", 1024, NULL, 2, &xHandleTask2);// 判断如果等于pass的话表示返回成功if (xReturn != pdPASS)printf("xTaskCreate err\r\n");//vTaskDelete(xHandleTask2);}
}void Task2Function(void * param)
{while (1){// 在任务2里面设置自己对应的变量task1flagrun = 0;task2flagrun = 1;taskidleflagrun = 0;printf("2");   // 观察变量的高低电平//vTaskDelay(2);vTaskDelete(NULL);}
}// 这个是任务调度函数:也就是钩子函数
void vApplicationIdleHook( void )
{task1flagrun = 0;task2flagrun = 0;taskidleflagrun = 1;	printf("0");
}/*-----------------------------------------------------------*/int main( void )
{TaskHandle_t xHandleTask1;#ifdef DEBUGdebug();
#endifprvSetupHardware();printf("Hello, world!\r\n");// 设置任务1的优先级将任务1的优先级设置为0xTaskCreate(Task1Function, "Task1", 100, NULL, 0, &xHandleTask1);/* Start the scheduler. */vTaskStartScheduler();/* Will only get here if there was not enough heap space to create theidle task. */return 0;
}

实现函数(钩子函数不能放在死循环中不然空闲任务就不能执行其他的操作比如清理工作)

5. 任务调度算法

正在运行的任务,被称为"正在使用处理器",它处于运行状态。在单处理器系统中,任何时间里只能有一个任务处于运行状态。

非运行状态的任务,它处于这3种状态之一:

  • 阻塞(Blocked)

  • 暂停(Suspended)

  • 就绪(Ready)

就绪态的任务,可以被调度器挑选出来切换为运行状态,调度器永远都是挑选最高优先级的就绪态任务并让它进入运行状态。

阻塞状态的任务,它在等待"事件",当事件发生时任务就会进入就绪状态。

事件分为两类:

  • 时间相关的事件

    • 所谓时间相关的事件,就是设置超时时间:在指定时间内阻塞,时间到了就进入就绪状态。

    • 使用时间相关的事件,可以实现周期性的功能、可以实现超时功能。

  • 同步事件

    • 同步事件就是:某个任务在等待某些信息,别的任务或者中断服务程序会给它发送信息。

    • 怎么"发送信息"?方法很多

      • 任务通知(task notification)

      • 队列(queue)

      • 事件组(event group)

      • 信号量(semaphoe)

      • 互斥量(mutex)等

      • 这些方法用来发送同步信息,比如表示某个外设得到了数据。

static void prvSetupHardware( void );static volatile int flagIdleTaskrun = 0;  // 空闲任务运行时flagIdleTaskrun=1
static volatile int flagTask1run = 0;     // 任务1运行时flagTask1run=1
static volatile int flagTask2run = 0;     // 任务2运行时flagTask2run=1
static volatile int flagTask3run = 0;     // 任务3运行时flagTask3run=1/*-----------------------------------------------------------*/void vTask1( void *pvParameters )
{/* 任务函数的主体一般都是无限循环 */for( ;; ){flagIdleTaskrun = 0;flagTask1run = 1;flagTask2run = 0;flagTask3run = 0;/* 打印任务的信息 */printf("T1\r\n");				}
}void vTask2( void *pvParameters )
{	/* 任务函数的主体一般都是无限循环 */for( ;; ){flagIdleTaskrun = 0;flagTask1run = 0;flagTask2run = 1;flagTask3run = 0;/* 打印任务的信息 */printf("T2\r\n");				}
}void vTask3( void *pvParameters )
{	const TickType_t xDelay5ms = pdMS_TO_TICKS( 5UL );		/* 任务函数的主体一般都是无限循环 */for( ;; ){flagIdleTaskrun = 0;flagTask1run = 0;flagTask2run = 0;flagTask3run = 1;/* 打印任务的信息 */printf("T3\r\n");				// 如果不休眠的话, 其他任务无法得到执行vTaskDelay( xDelay5ms );}
}void vApplicationIdleHook(void)
{flagIdleTaskrun = 1;flagTask1run = 0;flagTask2run = 0;flagTask3run = 0;	/* 故意加入打印让flagIdleTaskrun变为1的时间维持长一点 *///printf("Id\r\n");				
}int main( void )
{prvSetupHardware();//动态创建任务1优先级是0xTaskCreate(vTask1, "Task 1", 1000, NULL, 0, NULL);//动态创建任务2优先级是0xTaskCreate(vTask2, "Task 2", 1000, NULL, 0, NULL);//动态创建任务3优先级是2xTaskCreate(vTask3, "Task 3", 1000, NULL, 2, NULL);/* 启动调度器 */vTaskStartScheduler();/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */return 0;
}

此处的高优先级的先执行

 

以下是任务调度相关部分的代码

/* Demo app includes. */
static void prvSetupHardware( void );static volatile int flagIdleTaskrun = 0;  // 空闲任务运行时flagIdleTaskrun=1
static volatile int flagTask1run = 0;     // 任务1运行时flagTask1run=1
static volatile int flagTask2run = 0;     // 任务2运行时flagTask2run=1
static volatile int flagTask3run = 0;     // 任务3运行时flagTask3run=1/*-----------------------------------------------------------*/void vTask1( void *pvParameters )
{/* 任务函数的主体一般都是无限循环 */for( ;; ){flagIdleTaskrun = 0;flagTask1run = 1;flagTask2run = 0;flagTask3run = 0;/* 打印任务的信息 */printf("T1\r\n");				}
}void vTask2( void *pvParameters )
{	/* 任务函数的主体一般都是无限循环 */for( ;; ){flagIdleTaskrun = 0;flagTask1run = 0;flagTask2run = 1;flagTask3run = 0;/* 打印任务的信息 */printf("T2\r\n");				}
}void vTask3( void *pvParameters )
{	const TickType_t xDelay5ms = pdMS_TO_TICKS( 5UL );		/* 任务函数的主体一般都是无限循环 */for( ;; ){flagIdleTaskrun = 0;flagTask1run = 0;flagTask2run = 0;flagTask3run = 1;/* 打印任务的信息 */printf("T3\r\n");				// 如果不休眠的话, 其他任务无法得到执行vTaskDelay( xDelay5ms );}
}void vApplicationIdleHook(void)
{flagIdleTaskrun = 1;flagTask1run = 0;flagTask2run = 0;flagTask3run = 0;	/* 故意加入打印让flagIdleTaskrun变为1的时间维持长一点 *///printf("Id\r\n");				
}int main( void )
{prvSetupHardware();//动态创建任务1优先级是0xTaskCreate(vTask1, "Task 1", 1000, NULL, 0, NULL);//动态创建任务2优先级是0xTaskCreate(vTask2, "Task 2", 1000, NULL, 0, NULL);//动态创建任务3优先级是2xTaskCreate(vTask3, "Task 3", 1000, NULL, 2, NULL);/* 启动调度器 */vTaskStartScheduler();/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */return 0;
}

这种调度策略表示的是不允许抢占,(使用这种方式编写代码最好是在做完一些事情之后放弃占用CPU的资源)

 

#define configUSE_PREEMPTION 1  是否支持抢占式调度 #define configUSE_TIME_SLICING 1              时间片轮转(默认的情况下应该是支持时间片轮转的)

这个是是否支持时间片轮转的的任务函数(PWM)波形

#define configIDLE_SHOULD_YIELD 1 这个表示的是空闲的任务应该空闲礼让他人,将GPU资源让给用户任务

这个是是否空闲任务礼让其他的CPU任务的PWM波形

这个是礼让(空闲的任务礼让其他的任务)

这个是不礼让(空闲的任务不礼让,也其他的任务一样抢占CPU的资源)

5.2 调度策略

  • 是否抢占?

  • #define configUSE_PREEMPTION 1 是否支持抢占式调度

  • 允许抢占时,是否允许时间片轮转?

  • #define configUSE_TIME_SLICING 1 时间片轮转(默认的情况下应该是支持时间片轮转的)

  • 允许抢占、允许时间片轮转时,空闲任务是否让步?

  • #define configIDLE_SHOULD_YIELD 1 这个表示的是空闲的任务应该空闲礼让他人,将GPU资源让给用户任务

相关文章:

FreeRTOS任务管理

1. 任务状态理论讲解 定时器职中断周期此处的1000Hz表示的是没次间隔1毫秒就记一次数&#xff08;在FreeConfig.h&#xff09;文件中进行配置 #define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) 判断是否需要任务切换在FreeRTOS里面每次间隔1毫秒切换一次&#xff08;程序…...

Qwen1.5大语言模型微调实践

在人工智能领域&#xff0c;大语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;的兴起和广泛应用&#xff0c;为自然语言处理&#xff08;NLP&#xff09;带来了前所未有的变革。Qwen1.5大语言模型作为其中的佼佼者&#xff0c;不仅拥有强大的语言生成和理…...

购物车实现

目录 1.购物车常见的实现方式 2.购物车数据结构介绍 3.实例分析 1.controller层 2.service层 1.购物车常见的实现方式 方式一&#xff1a;存储到数据库 性能存在瓶颈方式二&#xff1a;前端本地存储 localstorage在浏览器中存储 key/value 对&#xff0c;没有过期时间。s…...

HTML5漫画风格个人介绍源码

源码介绍 HTML5漫画风格个人介绍源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 效果截图 源码下载 HTML5漫画风格…...

工业数学模型——高炉煤气发生量预测(三)

1、工业场景 冶金过程中生产的各种煤气&#xff0c;例如高炉煤气、焦炉煤气、转炉煤气等。作为重要的副产品和二次能源&#xff0c;保证它们的梯级利用和减少放散是煤气能源平衡调控的一项紧迫任务&#xff0c;准确的预测煤气的发生量是实现煤气系统在线最优调控的前提。 2、…...

pnpm - Failed to resolve loader: cache-loader. You may need to install it.

起因 工作原因需要研究 vue-grid-layout 的源码&#xff0c;于是下载到本地。因为我习惯使用 pnpm&#xff0c;所以直接用 pnpm i 安装依赖&#xff0c;npm run serve 启动失败。折腾了一番没成功。 看到源码里有 yarn.lock&#xff0c;于是重新用 yarn install 安装依赖&…...

CSS transition和animation的用法和区别

Transition和Animation在CSS中都是用于实现元素状态变化的效果&#xff0c;但它们在用法和特性上存在明显的区别。 Transition transition是过度属性&#xff0c;主要强调的是元素状态的过渡效果。 它通常用于在元素的状态发生变化时&#xff0c;平滑地过渡到一个新的状态。…...

书籍推荐(附上每本书的看点)

1、《FPGA深度解析》&#xff0c;这本书的FIFO部分我觉得讲得很好; 2、《verilog数字系统设计教程》&#xff0c;夏宇闻老师的蓝皮书&#xff0c;这本书里包含很多考试知识点; 3、《SOC设计方法和实现》郭炜老师写的&#xff0c;我觉得他的低功耗设计讲得很好; 《高级FPGA设计结…...

LLM理解v1

答疑 什么是知识库&#xff1f; LLM&#xff08;Large Language Models&#xff0c;大型语言模型&#xff09;如GPT系列&#xff0c;通常是基于海量的文本数据进行训练的。它们通过分析和理解这些数据来生成回答、撰写文章、解决问题等。当我们提到LLM的“本地知识库”时&…...

ubuntu 22.04 -- cmake安装

安装方式一&#xff1a;源码安装 1、下载安装包 官网下载&#xff1a;下载链接&#xff1a;Download CMake 也可以使用命令行下载 wget https://github.com/Kitware/CMake/releases/download/v3.26.5/cmake-3.26.5.tar.gz2、解压并安装 # 1、解压 tar -zxvf cmake-3.26.5.…...

字符串算法题(第二十四天)

344. 反转字符串 题目 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间&#xff0c;你必须**原地修改输入数组**、使用 O(1) 的额外空间解决这一问题。 示例 1&#xff1a; 输入&#xff1…...

【Linux】应用层协议序列化和反序列化

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;C【智能指针】 前言 在正式代码开始前&#xff0c;会有一些前提知识引入 目录 &#x1f449;&#x1f3fb;序列…...

使用Canal同步MySQL 8到ES中小白配置教程

&#x1f680; 使用Canal同步MySQL 8到ES中小白配置教程 &#x1f680; 文章目录 &#x1f680; 使用Canal同步MySQL 8到ES中小白配置教程 &#x1f680;**摘要****引言****正文**&#x1f4d8; 第1章&#xff1a;初识Canal1.1 Canal概述1.2 工作原理解析 &#x1f4d8; 第2章&…...

关于部署ELK和EFLK的相关知识

文章目录 一、ELK日志分析系统1、ELK简介1.2 ElasticSearch1.3 Logstash1.4 Kibana&#xff08;展示数据可视化界面&#xff09;1.5 Filebeat 2、使用ELK的原因3、完整日志系统的基本特征4、ELK的工作原理 二、部署ELK日志分析系统1、服务器配置2、关闭防火墙3、ELK ElasticSea…...

实验室信息系统源码 saas模式java+.Net Core版开发的云LIS系统全套源码可二次开发有演示

实验室信息系统源码 saas模式java.Net Core版开发的云LIS系统全套源码可二次开发有演示 一、技术框架 技术架构&#xff1a;Asp.NET CORE 3.1 MVC SQLserver Redis等 开发语言&#xff1a;C# 6.0、JavaScript 前端框架&#xff1a;JQuery、EasyUI、Bootstrap 后端框架&am…...

PCB---Design Entry cis 绘图 导出

修改纸张大小&#xff1a; 画图前准备&#xff1a;导入 画图&#xff1a; 习惯&#xff1a; 电源朝上 地朝下 配置pbc_footprint编号&#xff1a; 都配置好编号就可以导出了 导出&#xff1a;...

vue 一键更换主题颜色

这里提供简单的实现步骤&#xff0c;具体看自己怎么加到项目中 我展示的是vue2 vue3同理 在 App.vue 添加 入口处直接修改 #app { // 定义的全局修改颜色变量--themeColor:#008cff; } // 组件某些背景颜色需要跟着一起改变&#xff0c;其他也是同理 /deep/ .ant-btn-primar…...

WebKit内核游览器

WebKit内核游览器 基础概念游览器引擎Chromium 浏览器架构Webkit 资源加载这里就不得不提到http超文本传输协议这个概念了&#xff1a; 游览器多线程HTML 解析总结 基础概念 百度百科介绍 WebKit 是一个开源的浏览器引擎&#xff0c;与之相对应的引擎有Gecko&#xff08;Mozil…...

Qt 拖放功能详解:理论与实践并举的深度指南

拖放&#xff08;Drag and Drop&#xff09;作为一种直观且高效的用户交互方式&#xff0c;在现代图形用户界面中扮演着重要角色。Qt 框架提供了完善的拖放支持&#xff0c;允许开发者在应用程序中轻松实现这一功能。本篇博文将详细阐述Qt拖放机制的工作原理&#xff0c;结合详…...

Springboot+Vue项目-基于Java+MySQL的企业客户管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…...

【Linux学习】Linux指令(四)

文章标题 &#x1f680;zip/unzip指令&#xff1a;&#x1f680;tar指令&#xff08;重要&#xff09;&#xff1a;&#x1f680;uname –r指令&#xff1a;&#x1f680;关机指令&#x1f680;几个常用操作 &#x1f680;zip/unzip指令&#xff1a; zip 与 unzip的安装 yum i…...

阿里云服务器 使用Certbot申请免费 HTTPS 证书及自动续期

前言 Certbot是一款免费且开源的自动化安全证书管理工具&#xff0c;由电子前沿基金会&#xff08;EFF&#xff09;开发和维护&#xff0c;是在Linux、Apache和Nginx服务器上配置和管理SSL/TLS证书的一种机制。Certbot可以自动完成域名的认证并安装证书。 一、 安装软件 1.1…...

统一SQL-number/decimal/dec/numeric转换

统一SQL介绍 https://www.light-pg.com/docs/LTSQL/current/index.html 源和目标 源数据库&#xff1a;Oracle 目标数据库&#xff1a;Postgresql&#xff0c;TDSQL-MySQL&#xff0c;达梦8&#xff0c;LightDB-Oracle 操作目标 通过统一SQL&#xff0c;将Oracle中的numb…...

软件测试入门学习笔记

系统测试流程规范 一.研发模型 1.瀑布模型 从可行性研究&#xff08;或系统分析&#xff09;开始&#xff0c;需求 2.增量迭代模型 3.敏捷开发模型 二.质量模型...

31. 下一个排列

题目描述 整数数组的一个排列 就是将其所有成员以序列或线性顺序排列。 例如&#xff0c;arr [1,2,3] &#xff0c;以下这些都可以视作 arr 的排列&#xff1a;[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的下一个排列是指其整数的下一个字典序更大的排列。更正式地&…...

Android笔记: mkdirs不生效失败

Manifest已经配置权限,代码中也动态获取权限,mkdirs一直返回false File.mkdirs()方法创建文件夹失败 1、动态申请读写权限 <!--SDCard写权限--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!--SDCard读权…...

需要添加的硬币的最小数量(Lc2952)——贪心+构造

给你一个下标从 0 开始的整数数组 coins&#xff0c;表示可用的硬币的面值&#xff0c;以及一个整数 target 。 如果存在某个 coins 的子序列总和为 x&#xff0c;那么整数 x 就是一个 可取得的金额 。 返回需要添加到数组中的 任意面值 硬币的 最小数量 &#xff0c;使范围 …...

军工保密资质介绍及申请要求

军工保密资质介绍 军工保密资质是指国家对从事军工研发、生产、销售等活动的企事业单位进行的一种资质认证。该资质的核心目标是保护国家军事机密和军事技术秘密&#xff0c;确保国家安全和国防利益。军工保密资质的认证标准非常严格&#xff0c;涉及企业的安全管理、技术保密…...

ES6的编程风格

ES6 提出了两个新的声明变量的命令&#xff1a;let和const。其中&#xff0c;let完全可以取代var&#xff0c;因为两者语义相同&#xff0c;而且let没有副作用。 var命令存在变量提升效用&#xff0c;let命令没有这个问题 if (true) {console.log(x); // ReferenceErrorlet x…...

springboot 载入自定义的yml文件转DTO

json解析的pom引入 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-json</artifactId><version>5.8.20</version></dependency>resources目录下的my-data.yml project:data:- name: service-genbase-package:…...

webpack-(plugin,本地服务器,路径别名,安装vue)

安装vue npm i vue-loader -D npm i vue 编写一个vue文件&#xff1a; 在index.html中设置 一个id为app的div 将vue文件挂载到app中 vue比较特殊&#xff0c;除了使用loader外&#xff0c;还使用了plugin const path require("path"); const { VueLoaderPlugin …...

http请求头导致了dial tcp:lookup xxxx on 10.43.0.10:53 no sunch host

事实证明人有的时候也不能太偷懒&#xff0c;太偷懒容易给自己埋坑。 问题的背景&#xff1a; web端调用服务A&#xff0c;服务A异步调用服务B。服务A有四个场景需要调用服务B&#xff0c;所以&#xff0c;服务A中封装了一个公用的方法&#xff0c;唯一的区别是&#xff0c;场…...

想要设计放大电路,必须掌握哪些?

放大电路是电子系统中的核心组成部分&#xff0c;其设计好坏将直接影响到整个系统的性能&#xff0c;对电子工程师来说&#xff0c;在设计放大电路时&#xff0c;必须掌握且关注多方面&#xff0c;以此确保电路的稳定性和放大效果&#xff0c;那么需要注意哪些&#xff1f; 1、…...

每天五分钟计算机视觉:基于卷积操作完成滑动窗口的图片分类?

本文重点 我们前面学习了使用不同大小的滑动窗口来滑动图片,然后切分成许多小的图片,然后依次应用到我们已经训练好的图像分类模型中,但是这种方式效率太低了,本节课程我们学习一种新的方式,来看一下如何并行识别这些剪切的图片。 原始结构 首先我们先来看一下,如何把…...

UI设计/交互设计/视觉设计项目汇报/作品集Figma/PPT模板

作为UI设计/交互设计/视觉设计师&#xff0c;创建作品集对于向潜在客户或雇主展示您的技能、创造力和风格至关重要。以下分步指南可帮助您创建令人印象深刻的作品集&#xff1a; 选择您的最佳作品&#xff1a;选择您最强大且最相关的设计项目&#xff0c;将其纳入您的作品集。…...

25、Lua 学习笔记之三(高阶话题)

Lua 学习笔记之三 高阶话题迭代实例代码有关迭代的描述 协作线程实例代码有关协作线程的描述 高阶话题 迭代 实例代码 --迭代 local function enum(array)local index 1return function()local ret array[index]index index 1return retend endlocal function foreach(a…...

企业网盘搭建——LNMP

php包链接&#xff1a;https://pan.baidu.com/s/1RElYTQx320pN6452N_7t1Q?pwdp8gs 提取码&#xff1a;p8gs 网盘源码包链接&#xff1a;https://pan.baidu.com/s/1BaYqwruka1P6h5wBBrLiBw?pwdwrzo 提取码&#xff1a;wrzo 目录 一.手动部署 二.自动部署 一.手动部署 …...

Go语言异常处理方式

Go 语言没有传统的异常处理机制&#xff0c;如 Java、C 或 Python 中的 try-catch 语句。取而代之&#xff0c;Go 采用了基于返回错误值和 panic/recover 机制的混合模式来进行错误处理。以下是 Go 语言中处理异常&#xff08;或称错误&#xff09;的两种主要方式&#xff1a; …...

时序分析基本知识点

【FPGA开发/IC开发之时序约束最全面的归纳总结】时序路径基本概念及时序约束分析方法_时序约束指令-CSDN博客...

ELK(Elasticsearch+Logstash+Kibana)日志分析系统

目录 前言 一、ELK日志分析系统概述 1、三大组件工具介绍 1.1 Elasticsearch 1.1.1 Elasticsearch概念 1.1.2 关系型数据库和ElasticSearch中的对应关系 1.1.3 Elasticsearch提供的操作命令 1.2 Logstash 1.2.1 Logstash概念 1.2.2 Logstash的主要组件 1.2.3 Logsta…...

【投稿优惠-EI稳定检索】2024年地理信息技术与遥感测绘国际学术会议(ICGITRSM 2024)

2024 International Conference on Geographic Information Technology and Remote Sensing Mapping (ICGITRSM 2024) ●会议简介 2024年地理信息技术与遥感测绘国际学术会议将聚焦于地理信息技术及遥感测绘领域的最新发展与应用。本次会议汇聚了来自世界各地的顶尖专家和学者…...

MySQL的内外连接

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;MySQL &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容主要介绍了MySQL中的内外连接 文章目录 MySQL的内外连接…...

Pandas连接MySQL数据库

pandas是一个强大的Python工具包&#xff0c;能够快速帮助我们做很多数据处理。但是在利用pandas连接数据库时&#xff0c;也会遇到很多问题&#xff0c;在此我总结了一个相对较为简单的连接范式&#xff0c;供大家参考学习。 先上代码&#xff1a; import pandas as pd# 数据…...

2024华中杯数学建模参考思路+完整代码+后续成品论文预约

&#xff08;完整版资料获取在文末哦&#xff09; 关于24年华中杯的更新进度&#xff0c;大家可以参考我们前年比赛。 22年华中杯思路&#xff1a; 大家也可以看这一篇 A题思路 一订单包含多种货品&#xff0c;每种商品有不同的数量&#xff0c;题目没说订单的需求时间&am…...

ARM_day8:基于iic总线的通信

一、IIC总线的基本概念&#xff1a; iic总线是一种带应答的同步的、串行、半双工的通信方式&#xff0c;支持一个主机对应多个从机。它有一根SCL&#xff08;时钟线&#xff09;和一根SDA&#xff08;数据线&#xff09;组成&#xff0c;由于只有一根数据线&#xff0c;所以它是…...

33、Lua Cocos2d-x使用Luajit实现加密

项目要求对lua脚本进行加密&#xff0c;查了一下相关的资料 &#xff0c;得知lua本身可以使用luac将脚本编译为字节码(bytecode)从而实现加密&#xff0c;试了一下&#xff0c;确实可行。下面是使用原生的lua解释器编译字节码&#xff1a; 新建一个名为1.lua的文件&#xff0c;…...

spring 集成 mybatis

spring 集成 mybatis 1、spring对junit的支持1.1、对junit4的支持1.2 对junit5的支持 2、Spring6集成MyBatis3.52.1 实现步骤2.2 实现 1、spring对junit的支持 1.1、对junit4的支持 依赖 <?xml version"1.0" encoding"UTF-8"?> <project xml…...

rtpengine 的端点学习模式

端点学习模式&#xff08;endpoint-learning&#xff09; delayed|immediate|off|heuristic delayed 延迟模式&#xff0c;等待 3 秒钟&#xff0c;然后再提交到端点地址 immediate 立即模式&#xff0c;收到第一个 rtp 包之后立即学习&#xff0c;不等 3 秒 off 关闭模式…...

Windows 安装 A UDP/TCP Assistant 网络调试助手

Windows 安装 A UDP/TCP Assistant 网络调试助手 0. 引言1. 下载地址2. 安装和使用 0. 引言 需要调试一个实时在线聊天程序&#xff0c;安装一个UDP/TCP Assistant 网络调试助手&#xff0c;方便调试。 1. 下载地址 https://github.com/busyluo/NetAssistant/releases 2. 安…...

web自动化系列-selenium的3种等待方式(十一)

在ui自动化测试中&#xff0c;几乎出现问题最多的情况就是定位不到元素 &#xff0c;当你的自动化在运行过程中 &#xff0c;突然发现报错走不下去了 。很大概率就是因为找不到元素 &#xff0c;而找不到元素的一个主要原因就是页面加载慢 &#xff0c;代码运行速度快导致 。 …...

孩子参加编程竞赛和考级怎么选择?

孩子参加编程竞赛和考级都是有益的学习方式&#xff0c;但各有不同的优势和目的。下面我将分别介绍一下竞赛和考级的特点&#xff0c;以便您更好地选择适合孩子的学习方式。 竞赛&#xff1a; 激发竞争意识&#xff1a;参加编程竞赛可以激发孩子的竞争意识&#xff0c;让他们…...

数据库设计基础知识

NoSQL数据库 按照使用的数据结构的类型分类 NoSQL数据库可分为列式存储数据库、键值对存储数据库、文档型数据库、图数据库 &#xff08;1&#xff09;列式存储数据库用来应对分布式存储的海量数据&#xff0c;键仍然存在&#xff0c;特点是指向了多个列。现有产品如 Cattand…...

LLAMA-Factory微调chatglm3-6b出现KeyError: ‘instruction‘错误

之前我也遇到过这样的错误就是在LLAMA-Factory微调chatglm3-6b时报错KeyError: ‘instruction‘。那时候是因为数据现存在少部分格式不同&#xff0c;这才导致KeyError: instruction错误。 但是候来又遇到了KeyError: ‘instruction‘&#xff0c;但这次没有格式不同的问题。 …...

DOS学习-目录与文件应用操作经典案例-dir

欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一.前言 二.使用 三.练习 一.前言 dir是"directory"&#xff08;目录&#xff09;的缩写&#xff0c;它主要用于展示某个磁盘上的全部或特定文件目录。在DOS操作系统中&#…...

always on 可用行分析及部署操作

一、Always On 可用性分析 Always On 是 SQL Server 提供的一种高可用性和灾难恢复解决方案。它通过允许数据库在多个 SQL Server 实例之间自动故障转移,从而确保业务的连续性。以下是对 Always On 的可用性分析: 高可用性:Always On 通过创建可用性组,将数据库同步到多个…...

信息系统项目管理师0601:项目立项管理 — 考点总结(可直接理解记忆)

点击查看专栏目录 项目立项管理 — 考点总结(可直接理解记忆) 1.项目建议书(又称立项申请)是项目建设单位向上级主管部门提交项目申请时所必须的文件,是对拟建项目提出的框架性的总体设想。在项目建议书批准后,方可开展对外工作(掌握)。 2.项目建议书应该包括的核心内…...