FreeRTOS——软件定时器

一、什么是定时器

简单可以理解为闹钟,到达指定一段时间后,就会响铃。

STM32 芯片自带硬件定时器,精度较高,达到定时时间后会触发中断,也可以生成 PWM 、输入捕获、输出 比较,等等,功能强大,但是由于硬件的限制个数有限

软件定时器也可以实现定时功能,达到定时时间后可调用回调函数,可以在回调函数里处理信息。

二、软件定时器优缺点 

优点:

1. 简单、成本低;

2. 只要内存足够,可创建多个

缺点:

精度较低,容易受中断影响。在大多数情况下够用,但对于精度要求比较高的场合不建议使用

三、软件定时器原理

定时器是一个可选的、不属于 FreeRTOS 内核的功能,它是由定时器服务任务来提供的。

调用函数 vTaskStartScheduler() 开启任务调度器的时候,会创建一个用于管理软件定时器的任务,这个 任务就叫做软件定时器服务任务

        1. 负责软件定时器超时的逻辑判断

        2. 调用超时软件定时器的超时回调函数

        3. 处理软件定时器命令队列

FreeRTOS提供了很多定时器有关的API函数,这些API函数大多都使用FreeRTOS的队列发送命令给定时器服务任务。这个队列叫做定时器命令队列。定时器命令队列是提供给FreeRTOS的软件定时器使用的,用户不能直接访问

四、软件定时器相关配置 

        软件定时器有一个定时器服务任务定时器命令队列,这两个东西肯定是要配置的,相关的配置也是放到文件FreeRTOSConfig.h中的,涉及到的配置如下:

1、configUSE_TIMERS

如果要使用软件定时器的话宏configUSE_TIMERS一定要设置为1,当设置为1的话定时器服务任务就会在启动FreeRTOS调度器的时候自动创建。

2、configTIMER_TASK_PRIORITY

设置软件定时器服务任务的任务优先级,可以为0~(configMAX_PRIORITIES-1)。优先级一定要根据实际的应用要求来设置。如果定时器服务任务的优先级设置的高的话,定时器命令队列中的命令和定时器回调函数就会及时的得到处理。

3、configTIMER_QUEUE_LENGTH

此宏用来设置定时器命令队列的队列长度

4、configTIMER_TASK_STACK_DEPTH

此宏用来设置定时器服务任务的任务堆栈大小

五、单次定时器和周期定时器

单次定时器: 只超时一次,调用一次回调函数。可手动再开启定时器;

周期定时器: 多次超时,多次调用回调函数。

六、软件定时器相关 API 函数

6.1、创建软件定时器

TimerHandle_t xTimerCreate( const char * const          pcTimerName,const TickType_t            xTimerPeriod,const UBaseType_t           uxAutoReload,void * const                pvTimerID,TimerCallbackFunction_t     pxCallbackFunction 
);

参数:

pcTimerName:软件定时器名称

xTimerPeriodInTicks:定时超时时间,单位:系统时钟节拍宏 pdMS_TO_TICKS() 可用于将以毫秒为单位 指定的时间转换为以 tick 为单位指定的时间。

uxAutoReload:定时器模式, pdTRUE:周期定时器, pdFALSE:单次定时器

pvTimerID:软件定时器 ID,用于多个软件定时器公用一个超时回调函数

pxCallbackFunction:软件定时器超时回调函数

返回值: 成功:定时器句柄 失败:NULL

6.2、开启软件定时器

BaseType_t xTimerStart( TimerHandle_t    xTimer,TickType_t       xBlockTime 
);

参数:

xTimer:待开启的软件定时器的句柄

xTickToWait:发送命令到软件定时器命令队列的最大等待时间

返回值:

pdPASS:开启成功 pdFAIL:开启失败

6.3、停止软件定时器

BaseType_t xTimerStop( TimerHandle_t  xTimer,TickType_t     xBlockTime 
);

参数与返回值同上。

6.4、复位软件定时器

BaseType_t xTimerReset( TimerHandle_t  xTimer,TickType_t     xBlockTime 
);

参数与返回值同上。

该功能将使软件定时器的重新开启定时,复位后的软件定时器以复位时的时刻作为开启时刻重新定时

6.5、更改软件定时器定时时间

BaseType_t xTimerChangePeriod( TimerHandle_t  xTimer,TickType_t     xNewPeriod,TickType_t     xBlockTime 
);

xNewPeriod:新的定时超时时间,单位:系统时钟节拍

其余参数与返回值同上。

七、实操

7.1、任务需求

创建两个定时器:

定时器1,周期定时器,每1秒打印一次 I LOVE YOU

定时器2,单次定时器,启动后 2 秒打印一次 You Look Handsome

7.2、代码

7.2.1、CubeMX封装函数代码

/* USER CODE BEGIN Header */
/********************************************************************************* File Name          : freertos.c* Description        : Code for freertos applications******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables *//* USER CODE END Variables */
osThreadId defaultTaskHandle;
osTimerId myTimer01Handle;				/*定时器1句柄*/
osTimerId myTimer02Handle;/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes *//* USER CODE END FunctionPrototypes */void StartDefaultTask(void const * argument);
void Callback01(void const * argument);
void Callback02(void const * argument);void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) *//* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );/* GetTimerTaskMemory prototype (linked to static allocation support) */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize );/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;*ppxIdleTaskStackBuffer = &xIdleStack[0];*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;/* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY *//* USER CODE BEGIN GET_TIMER_TASK_MEMORY */
static StaticTask_t xTimerTaskTCBBuffer;
static StackType_t xTimerStack[configTIMER_TASK_STACK_DEPTH];void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )
{*ppxTimerTaskTCBBuffer = &xTimerTaskTCBBuffer;*ppxTimerTaskStackBuffer = &xTimerStack[0];*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;/* place for user code */
}
/* USER CODE END GET_TIMER_TASK_MEMORY *//*** @brief  FreeRTOS initialization* @param  None* @retval None*/
void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* Create the timer(s) *//* definition and creation of myTimer01 */osTimerDef(myTimer01, Callback01);myTimer01Handle = osTimerCreate(osTimer(myTimer01), osTimerPeriodic, NULL);		/*创建软件定时器1,osTimerCreate是CubeMX封装函数,底层还是xTimerCreate*//* definition and creation of myTimer02 */osTimerDef(myTimer02, Callback02);myTimer02Handle = osTimerCreate(osTimer(myTimer02), osTimerOnce, NULL);/* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* definition and creation of defaultTask */osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS */}/* USER CODE BEGIN Header_StartDefaultTask */
/*** @brief  Function implementing the defaultTask thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{/* USER CODE BEGIN StartDefaultTask */osTimerStart(myTimer01Handle, 1000);			/*开启软件定时器1,定时1000ms*/
// xTimerChangePeriod(myTimer01Handle, pdMS_TO_TICKS(1000), 0);			/*修改软件定时器1的事件为1000ms*/osTimerStart(myTimer02Handle, 2000);/* Infinite loop */for(;;){osDelay(1);}/* USER CODE END StartDefaultTask */
}/* Callback01 function */
void Callback01(void const * argument)	/*定时器1对应的回调函数*/
{/* USER CODE BEGIN Callback01 */printf("周期定时器:I LOVE YOU!\r\n");/* USER CODE END Callback01 */
}/* Callback02 function */
void Callback02(void const * argument)
{/* USER CODE BEGIN Callback02 */printf("单次定时器:You Look Handsome!\r\n");/* USER CODE END Callback02 */
}/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application *//* USER CODE END Application */

7.2.1、原函数代码

/* USER CODE BEGIN Header */
/********************************************************************************* File Name          : freertos.c* Description        : Code for freertos applications******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables *//* USER CODE END Variables */
osThreadId defaultTaskHandle;
osTimerId myTimer01Handle;				/*定时器1句柄*/
osTimerId myTimer02Handle;/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes *//* USER CODE END FunctionPrototypes */void StartDefaultTask(void const * argument);
void Callback01(void const * argument);
void Callback02(void const * argument);void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) *//* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );/* GetTimerTaskMemory prototype (linked to static allocation support) */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize );/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;*ppxIdleTaskStackBuffer = &xIdleStack[0];*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;/* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY *//* USER CODE BEGIN GET_TIMER_TASK_MEMORY */
static StaticTask_t xTimerTaskTCBBuffer;
static StackType_t xTimerStack[configTIMER_TASK_STACK_DEPTH];void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )
{*ppxTimerTaskTCBBuffer = &xTimerTaskTCBBuffer;*ppxTimerTaskStackBuffer = &xTimerStack[0];*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;/* place for user code */
}
/* USER CODE END GET_TIMER_TASK_MEMORY *//*** @brief  FreeRTOS initialization* @param  None* @retval None*/
void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* Create the timer(s) *//* definition and creation of myTimer01 */int Timer1_ID = 1;
//  osTimerDef(myTimer01, Callback01);
//  myTimer01Handle = osTimerCreate(osTimer(myTimer01), osTimerPeriodic, NULL);		/*创建软件定时器1,osTimerCreate是CubeMX封装函数,底层还是xTimerCreate*//*	创建软件定时器1,名称:myTimer01 ,定时时间1000ms:pdMS_TO_TICKS(1000)	,模式:周期定时*/myTimer01Handle = xTimerCreate("myTimer01" , pdMS_TO_TICKS(1000) ,pdTRUE , &Timer1_ID ,Callback01);/* definition and creation of myTimer02 */int Timer2_ID = 2;
//  osTimerDef(myTimer02, Callback02);
//  myTimer02Handle = osTimerCreate(osTimer(myTimer02), osTimerOnce, NULL);myTimer02Handle = xTimerCreate("myTimer02" , pdMS_TO_TICKS(2000) ,pdFALSE , &Timer2_ID ,Callback02);/* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* definition and creation of defaultTask */osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS */}/* USER CODE BEGIN Header_StartDefaultTask */
/*** @brief  Function implementing the defaultTask thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{/* USER CODE BEGIN StartDefaultTask *///osTimerStart(myTimer01Handle, 1000);			/*CubeMX封装的函数,开启软件定时器1,定时1000ms*/
// xTimerChangePeriod(myTimer01Handle, pdMS_TO_TICKS(1000), 0);			/*修改软件定时器1的事件为1000ms*///osTimerStart(myTimer02Handle, 2000);xTimerStart(myTimer01Handle ,portMAX_DELAY);		/*开启定时器1*/xTimerStart(myTimer02Handle ,portMAX_DELAY);		/*开启定时器2*//* Infinite loop */for(;;){osDelay(1);}/* USER CODE END StartDefaultTask */
}/* Callback01 function */
void Callback01(void const * argument)	/*定时器1对应的回调函数*/
{/* USER CODE BEGIN Callback01 */printf("周期定时器:I LOVE YOU!\r\n");/* USER CODE END Callback01 */
}/* Callback02 function */
void Callback02(void const * argument)
{/* USER CODE BEGIN Callback02 */printf("单次定时器:You Look Handsome!\r\n");/* USER CODE END Callback02 */
}/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application *//* USER CODE END Application */

结果:

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

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

相关文章

P12 音视频复合流——TS流讲解

前言 从本章开始我们将要学习嵌入式音视频的学习了 ,使用的瑞芯微的开发板 🎬 个人主页:ChenPi 🐻推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ 🔥 推荐专栏2: 《Linux C应用编程(概念类)_C…

电脑文件mfc100u.dll丢失的解决方法分析,怎么修复mfc100u.dll靠谱

mfc100u.dll丢失了要怎么办?其实很多人都遇到过这样的电脑故障吧,说这个mfc100u.dll文件已经不见了,然后一些程序打不开了,那么这种情况我们要怎么解决呢?今天我们就来给大家详细的说说mfc100u.dll丢失的解决方法。 一…

李家的张麻子:ETL工程师的数据库编程之旅,用ChatGPT打破常规!

数据库编程大赛:一条SQL计算扑克牌24点 12月27日,NineData和云数据库技术社区主办,华为云、火山引擎、开源中国、云和恩墨、TDengine、云猿生数据、DORIS、ITPUB等协办单位和媒体,共同举办了本次《数据库编程大赛》。大赛题目「用…

EtherCAT主站SOEM -- 13 --Qt-Soem通过界面按键控制 EtherCAT IO模块的io输出

EtherCAT主站SOEM -- 13 --Qt-Soem通过界面按键控制 EtherCAT IO模块的io输出 一 mainwindow.c 文件函数:1.1 自定义PDO配置2.2 主站初始化2.3 去motrorcontrol界面二 motrorcontrol.c 文件三 allvalue.h 文件该文档修改记录:总结一 mainwindow.c 文件函数: mainwindow主界…

20240105移远的4G模块EC20在Ubuntu 20.04.6 LTS下使用联通5G卡上网的步骤

20240105移远的4G模块EC20在Ubuntu 20.04.6 LTS下使用联通5G卡上网的步骤 2024/1/5 10:11 缘起:需要在Firefly的AIO-3399J开发板上调试移远的4G模块EC20(Android10/11/12),需要现在先测试EC20的好坏! 陶老板告诉我找一…

PPT插件-大珩助手-免费功能-特殊格式介绍

上、下标切换 直接切换选中的字符为上、下标。 大小金额 支持超大金额的大写金额转换 当前日期 本次打开文件的时间 转二维码 将当前选中的文字,转为二维码图片,并插入到PPT当前位置 特殊字符 内置常用的特殊字符,点击使用 软件介绍 …

致命勒索|揭秘2023年度十大勒索团伙

2023年,全球数字化转型加速 ,5G网络以及人工智能的高速发展,都给网络安全带来了新的挑战 。受地缘政治因素及疫情影响,国际局势动荡不安,经济衰退, 越来越多的网络攻击组织建立了高效的商业模式&#xff0c…

你们做外贸主要的获客渠道有哪些?

昨天跟一个同行朋友聊天,他原本主打产品是做动力类的,这两年竞争太大,订单也减少了很多。为了求发展,就拓品了,而拓展的新品刚好是我们这一块,而且非常迅速地找到场地把生产线弄了起来,还不断扩…

mysql原理--InnoDB的Buffer Pool

1.缓存的重要性 对于使用 InnoDB 作为存储引擎的表来说,不管是用于存储用户数据的索引(包括聚簇索引和二级索引),还是各种系统数据,都是以 页 的形式存放在 表空间 中的,而所谓的 表空间 只不过是 InnoDB 对…

将Django项目从本地上传至宝塔服务器(踩坑记录)

文章目录 写在前面配置本地文件配置宝塔面板解决遇到问题展示运行结果热门文章 自我介绍 ⭐2022年度CSDN 社区之星 Top6 ⭐2023年度CSDN 博客之星 Top16 ⭐2023年度CSDN 城市之星 Top2(苏州) ⭐CSDN Python领域 优质创作者 ⭐CSDN 内容合伙人 推荐热门…

Dockerfile语法和简单镜像构建

Dockerfile是一个用于定义Docker镜像的文本文件,包含了一系列的指令和参数,用于指示Docker在构建镜像时应该执行哪些操作,例如基于哪个基础镜像、复制哪些文件到镜像中、运行哪些命令等。 Dockerfile文件的内容主要有几个部分组成&#xff0c…

Python - 深夜数据结构与算法之 Two-Ended BFS

目录 一.引言 二.双向 BFS 简介 1.双向遍历示例 2.搜索模版回顾 三.经典算法实战 1.Word-Ladder [127] 2.Min-Gen-Mutation [433] 四.总结 一.引言 DFS、BFS 是常见的初级搜索方式,为了提高搜索效率,衍生了剪枝、双向 BFS 以及 A* 即启发式搜索…

pyqt调用UI和开启子进程

UI制作 qrc 注意调用UI前把样式表里绑定的资源(qrc)转换成py导入进去 xxx.qrc转xxx.py 两种方法 1命令 pyrcc5 -o icons_rc.py icons.qrc 2外部工具pyrcc 实参 -o $FileNameWithoutExtension$.py $FileNameWithoutExtension$.qrcsdz.qrc→→sdaz.py 在代码里写 import…

【模拟IC学习笔记】 采样保持电路的设计

目录 采样保持工作原理 概念 时域响应-采保信号 采样网络的KT/C噪声 采样电容大小的选取 采样抖动(jitter) jitter对SNR的影响 法一 法二 采样开关的种类 单MOS管 实践:Nmos导通电阻 传输门 栅压自举开关 采样技术 上极板采样 下极板采样 采样保持…

数据库的导入导出以及备份

1.数据库的导出和导入 一.navicat导入导出 导入:右键➡运行SQL文件 导出选:中要导出的表➡右键➡转储SQL文件➡数据和结构 mysqldump命 1. 进入navicat安装目录的bin目录,cmd打开命令窗口 2. mysql -u用户名 -p ➡ 输入密码 3. creat…

v-if控制div内容显示,克隆这个div但是v-if没有效果

问题描述: 我的子页面打印的时候通过isPdf来隐藏“选择参加人员”按钮。 我子页面有个el-dialog,el-dialog里面有个大的div它的id为app-pre-meet-add,在子页面我通过isPdf来显示我想要的内容。现在我在父页面先通过this.$refs.child.control…

虚拟主机 如何上传大于100M的文件 php网站程序

问题 虚拟主机上传文件大小限制100m, 有时会遇到非常大的文件上传,上传过程中耗时非常久, 可能服务器的限制设置了上传文件尺寸,返回“413 request entity too large” 整体逻辑 前端:上传文件时,进行文…

使用Windbg静态分析dump文件的一般步骤详解

目录 1、概述 2、静态分析dump文件的一般步骤 2.1、查看异常类型 2.2、使用.ecxr命令切换到发生异常的线程上下文,查看发生异常的那条汇编指令 2.3、使用kn/kv/kp命令查看异常发生时的函数调用堆栈 2.4、使用lm命令查看模块的时间戳,找到对应的pdb…

状态管理小能手:Cookie 和 Session

1. 引言 大家好,我是小❤,一个漂泊江湖多年的 985 非科班程序员,曾混迹于国企、互联网大厂和创业公司的后台开发攻城狮。 假期抢票的尴尬事件 最近小❤在抢出行的高铁票时,发生了一件尴尬的事情。 这不是临近假期了嘛&#xf…

WPF真入门教程26--项目案例--欧姆龙PLC通讯工具

1、案例介绍 前面已经完成了25篇的文章介绍,概括起来就是从0开始,一步步熟悉了wpf的概念,UI布局控件,资源样式文件的使用,MVVM模式介绍,命令Command等内容,这节来完成一个实际的项目开发&#…