FreeRTOS二值信号量详解与实战教程
FreeRTOS二值信号量详解与实战教程
📚 作者推荐:想系统学习FreeRTOS嵌入式开发?请访问我的FreeRTOS开源学习库,内含从入门到精通的完整教程和实例代码!
1. 二值信号量核心概念解析
二值信号量(Binary Semaphore)是FreeRTOS提供的一种简单而强大的同步工具,它只有两个可能值:0或1。这种简单特性使它成为嵌入式系统中极其实用的同步原语。
💡 形象理解:二值信号量就像公共卫生间的占用指示灯:
- 绿灯(值为1):资源可用,任务可以获取
- 红灯(值为0):资源被占用,需要等待
2. 二值信号量三大应用场景
2.1 资源互斥访问
当多个任务需要访问共享资源(如全局变量、外设)时,二值信号量能确保任一时刻只有一个任务能访问该资源:
// 任务想要访问共享资源时
xSemaphoreTake(xMutexSemaphore, portMAX_DELAY); // 获取访问权
// 访问共享资源
xSemaphoreGive(xMutexSemaphore); // 释放访问权
2.2 任务同步控制
实现"任务A必须在任务B之前完成"的先后依赖关系:
// 任务A完成工作后
xSemaphoreGive(xSyncSemaphore); // 发出"我完成了"的信号// 任务B开始前
xSemaphoreTake(xSyncSemaphore, portMAX_DELAY); // 等待任务A完成
// 开始任务B的工作
2.3 任务阻塞与唤醒机制
FreeRTOS使用优先级管理等待同一信号量的多个任务:
- 不同优先级:高优先级任务优先获得信号量
- 相同优先级:先等待的任务先获得信号量
3. 二值信号量的底层实现揭秘
🔍 底层原理:二值信号量实质上是一个队列长度为1的特殊队列!
在FreeRTOS内核中:
- 队列为空 → 信号量值为0(不可用)
- 队列有元素 → 信号量值为1(可用)
这种实现使二值信号量具有队列的所有优势,包括任务阻塞和优先级继承等特性。
4. 二值信号量核心API详解
函数 | 描述 | 使用场景 |
---|---|---|
vSemaphoreCreateBinary() | 创建二值信号量(创建后自动释放一次) | 需要初始状态为"可用"的场景 |
xSemaphoreCreateBinary() | 创建二值信号量(不会自动释放) | 需要初始状态为"不可用"的场景 |
xSemaphoreTake() | 获取信号量(将信号量由1变为0) | 任务中获取信号量 |
xSemaphoreGive() | 释放信号量(将信号量由0变为1) | 任务中释放信号量 |
xSemaphoreTakeFromISR() | 中断中获取信号量 | 中断服务程序中获取信号量 |
xSemaphoreGiveFromISR() | 中断中释放信号量 | 中断服务程序中释放信号量 |
5. 二值信号量实战示例教程
下面通过一个完整示例展示二值信号量的使用方法。我们创建两个任务:
- 任务1:定期释放信号量
- 任务2:等待并获取信号量,成功后打印提示
5.1 代码实现步骤
-
准备工程:复制006多任务创建模板,并重命名为010
-
删除不必要的代码:
#include "queue.h"
TaskHandle_t myTaskHandler3;
struct print{int cnt;char data[20];
};
struct print data = {.data = "myTask1 runnig"};
data.cnt++;xQueueSend(myPrintfQueueHandler, &data, 0);
struct print data = {.data = "myTask2 runnig"};
data.cnt++;xQueueSend(myPrintfQueueHandler, &data, 0);
void myTask3(void *arg)
{struct print data;BaseType_t xStatus;while(1){xStatus = xQueueReceive(myPrintfQueueHandler, &data, portMAX_DELAY);if(xStatus == pdPASS){taskENTER_CRITICAL();printf("%s:%d\n", data.data,data.cnt);taskEXIT_CRITICAL();}
// vTaskDelay(500);}
}
xTaskCreate(myTask3,"myTask3",128,NULL,2,&myTaskHandler3);
myPrintfQueueHandler = xQueueCreate(2,sizeof(struct print));
- 导入信号量头文件:
#include "semphr.h" //信号量相关的头文件
- 创建二值信号量:
深入理解:为什么选择v开头的创建函数?
查看vSemaphoreCreateBinary
定义,理解其内部实现:
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )#define vSemaphoreCreateBinary( xSemaphore ) \{ \( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \if( ( xSemaphore ) != NULL ) \{ \( void ) xSemaphoreGive( ( xSemaphore ) ); \} \}
#endif
从源码可以看出:
- 它首先创建一个长度为1的队列
- 创建成功后,立即执行
xSemaphoreGive
释放信号量,使其初始值为1(可用状态) - 这正是我们需要的初始状态!
对比另一个创建函数:
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
#endif
xSemaphoreCreateBinary
仅创建队列,不自动释放,初始值为0(不可用状态)。
-
声明信号量句柄:
-
创建失败检测:
-
编写Task1(释放信号量):
void myTask1(void *arg)
{BaseType_t res = 0;while(1){taskENTER_CRITICAL();printf("myTask1 runnig\n");/* 释放二值信号量 */res = xSemaphoreGive(myPrintfQueueHandler);if(res == pdPASS){printf("Task1 release successful\r\n");}else {printf("Task1 release failed\r\n");}taskEXIT_CRITICAL();vTaskDelay(500);}
}
📝 说明:这里使用临界区保护打印操作,防止多任务打印导致的输出混乱。
查看xSemaphoreGive
定义:
#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
本质上是向队列发送一个空数据!
- 编写Task2(获取信号量):
void myTask2(void *arg)
{BaseType_t res = 0;while (1){/* 获取二值信号量 */res = xSemaphoreTake(myPrintfQueueHandler,portMAX_DELAY);if(res == pdPASS){printf("Task2 release successful\r\n"); }else {printf("Task2 release failed\r\n"); }}
}
查看xSemaphoreTake
定义:
#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) )
- 编译、调试、运行:输出如下内容表示成功
5.2 实例代码深度解析
-
创建信号量:使用
vSemaphoreCreateBinary()
创建二值信号量,初始值为1(可用)。 -
Task1工作流程:
- 进入临界区(防止打印混乱)
- 打印运行状态信息
- 释放信号量(使值为1)
- 打印释放结果
- 退出临界区
- 延时500ms
-
Task2工作流程:
- 尝试获取信号量(将值从1变为0)
- 若成功(返回pdPASS),打印成功信息
- 若失败,打印失败信息
- 循环执行(无延时)
-
portMAX_DELAY参数:表示无限等待,直到获取到信号量才继续执行。
5.3 运行结果分析
执行程序后,我们观察到典型的执行顺序:
- 系统启动,Task2立即获取到信号量(因初始值为1)并打印成功信息。
- 信号量值变为0,Task2再次尝试获取时进入阻塞状态。
- Task1执行,释放信号量,值变为1。
- Task2被唤醒,获取信号量,打印成功信息。
- 周而复始,形成Task1释放→Task2获取的循环。
🔍 现象解释:为什么有时Task1的释放成功信息会出现在Task2的获取成功信息之后?
这是因为任务调度的时机。当Task1释放信号量后,如果Task2优先级高于Task1,系统会立即切换到Task2执行,导致Task2的打印先于Task1的释放成功信息。
6. 二值信号量高级特性与注意事项
-
跨任务操作:信号量的获取和释放可以在不同任务间进行,这是实现任务同步的基础。
-
初始状态选择:
- 使用
vSemaphoreCreateBinary()
:初始状态为"可用"(值为1) - 使用
xSemaphoreCreateBinary()
:初始状态为"不可用"(值为0)
- 使用
-
超时参数:
portMAX_DELAY
:永久等待0
:不等待,立即返回- 其他值:等待指定时间(单位为tick)
-
中断中使用:中断服务程序中必须使用
FromISR
结尾的函数版本。
7. 总结与实践建议
二值信号量是FreeRTOS中极为强大且使用简单的同步工具,适用于互斥访问和任务同步场景。通过本教程的学习,你应该已经掌握了:
✅ 二值信号量的基本概念与原理
✅ 信号量的创建、获取与释放操作
✅ 常见应用场景与实现方法
✅ 底层实现机制与高级特性
应用建议
-
选择合适的场景:二值信号量适合简单的同步场景,复杂场景考虑计数信号量或事件组。
-
避免优先级反转:在互斥访问场景中,考虑使用互斥量(Mutex)代替二值信号量,因为互斥量支持优先级继承机制。
-
防止死锁:确保获取信号量的任务最终会释放它,避免系统陷入死锁。
📚 想深入学习FreeRTOS?
我整理了一套完整的FreeRTOS开发学习资源,从环境搭建到高级特性应用,包含大量实例代码和详细教程。欢迎star和fork!
扩展思考:在什么情况下,你会选择使用二值信号量而非互斥量(Mutex)或计数信号量?欢迎在评论区讨论!
相关文章:
FreeRTOS二值信号量详解与实战教程
FreeRTOS二值信号量详解与实战教程 📚 作者推荐:想系统学习FreeRTOS嵌入式开发?请访问我的FreeRTOS开源学习库,内含从入门到精通的完整教程和实例代码! 1. 二值信号量核心概念解析 二值信号量(Binary Semaphore)是Fre…...
数据结构与算法[零基础]---6.算法概况
六、算法概述 (一)算法的概述 任何解决问题的过程都是由一定的步骤组成的,把解决问题的方法和有限的步骤称作算法 (二)算法的基本特征 1.有穷性 算法必须在执行有限个操作之后终止,且每一步都可在有限时间内完成。 2.确定性 算…...
STL简介(了解)
1.什么是STL STL(standard template libaray)是标准模板库,它是C标准库的一部分。C标准库中还有一些其它东西,比如之前用的IO流。它主要是数据结构和算法的库。 2.STL的版本 C3.0出来后就有了模板,此时大家已经深受没有数据结构算法库的痛苦…...
使用 Oh My Posh 自定义 PowerShell 提示符
使用 Oh My Posh 自定义 PowerShell 提示符 由于ai生图,ai视频这方面mac太差了,买N卡,转windows了,这里也记录一下 PowerShell 配置Oh My Posh 先上效果图 一、下载 PowerShell7 默认的 PowerShell5 太差了,下载地…...
4月17号
//1.编码 String str "ai你哟"; byte[] bytes1 str.getBytes(); System.out.println(Arrays.toString(bytes1)); byte[] bytes2 str.getBytes(charsetName: "GBK"); System.out.println(Arrays.toString(bytes2));//2.解码 String str2 new String(byt…...
react-native搭建开发环境过程记录
主要参考:官网的教程 https://reactnative.cn/docs/environment-setup 环境介绍:macos ios npm - 已装node18 - 已装,通过nvm进行版本控制Homebrew- 已装yarn - 已装ruby - macos系统自带的2.2版本。watchman - 正常安装Xcode - 正常安装和…...
自然语言处理(NLP)技术。
自然语言处理(NLP)技术可以应用于多个领域,以下是一些示例: 情感分析:NLP可以用来分析文本中包含的情感,帮助企业了解用户对他们产品或服务的感受。例如,社交媒体平台可以利用情感分析技术来监测…...
Ubuntu 安装WPS Office
文章目录 Ubuntu 安装WPS Office下载安装文件安装WPS问题1.下载缺失字体文件2.安装缺失字体 Ubuntu 安装WPS Office 下载安装文件 需要到 WPS官网 下载最新软件,比如wps-office_12.1.0.17900_amd64.deb 安装WPS 执行命令进行安装 sudo dpkg -i wps-office_12.1…...
【WPF】 自定义控件的自定义属性
文章目录 前言一、自定义控件部分二、在页面中使用总结 前言 在一个页面,重复用到同一个自定义控件时,该如何对控件分别进行数据绑定呢?这时候可以赋予控件一个自定义的属性,来完成此操作。 一、自定义控件部分 为自定以控件设置…...
Unity URP Moblie AR示例工程,真机打包出来,没阴影
效果: unity ar示例演示 现象: 真机打包测试私活没有阴影 Unity版本:2022.3.4f1c1 分析原因: Prefab :ARFeatheredPlane中也有材质,一个用于环境遮挡,一个用于阴影接受。 按理说有啊。 urp …...
如何删除word中的长横线(由三个减号---自动生成/由三个等号===自动生成/由三个###自动生成)_word三个减号回车的横线怎么删除-CSDN博客
方法1、选中前后行ctrlX剪切掉 方法2:如果文件中没有表格就非常简单,直接CtrlA全选整个文档,然后在表格边框里面选择“无框线”OK,如果有表格的话,就从横线的下行开始向上随意选取一部分,同样在表格边框中选…...
函数返回const引用,使用const修饰变量接收
函数返回const引用,使用const修饰变量接收 1、背景 想获取红绿灯时长数组并添加新的值。有个函数是返回红绿灯时长数组的。函数返回类型为const引用,我使用无修饰的变量接收。但是感觉有些问题,并且之前看到const变量变成非const还需要使用…...
在激烈竞争下B端HMI设计怎样打造独特用户体验?
在当今数字化高度发展的时代,B 端市场竞争愈发激烈。对于 B 端 HMI(人机界面)设计而言,打造独特的用户体验已成为在竞争中脱颖而出的关键因素。B 端用户在复杂的工作场景中,对 HMI 设计有着独特的需求和期望࿰…...
数理逻辑(Mathematical Logic)综论与跨学科应用
李升伟 整理 数理逻辑(Mathematical Logic)是现代逻辑学与数学交叉的核心学科,以严格的数学方法研究逻辑推理的形式与规律。其发展深刻影响了数学基础、计算机科学、语言哲学等领域。以下从多个维度综论数理逻辑: 1. 核心分支 命…...
4.17---实现商铺和缓存与数据库双写一致以及宕机处理
实现商铺和缓存与数据库双写一致(以及强双写一致策略) redis点评项目采用的是延时双删策略 双删: 我们更新完数据库之后删除缓存,这样即使有线程并发进来查询,会发现缓存中没有数据,从而会去mysql中查找…...
qt与html通信
**Cef视图(CefView)**是指在使用Chromium Embedded Framework(CEF)时,嵌入到应用程序中的浏览器视图。CEF是一个开源项目,它基于Google的Chromium浏览器,允许开发者将Web浏览器功能嵌入到自己的…...
【从零实现高并发内存池】thread cache、central cache 和 page cache 回收策略详解
📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...
算法5-16 对二进制字符串解码
输入样例: 5 a 4 b 3 c 2 w 1 z 1 100001110101101101100111输出样例: baaacabwbzc ac代码: #include<iostream> #include<queue> #include<map> using namespace std; const int N10010; int idx; int a[N][2]; char b…...
[MySQL数据库] InnoDB存储引擎(三): 内存结构详解
🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…...
TDengine 存储引擎剖析:数据文件与索引设计(一)
TDengine 存储引擎简介 在物联网、工业互联网等快速发展的今天,时间序列数据呈爆发式增长。这些数据具有产生频率高、依赖采集时间、测点多信息量大等特点,对数据存储和处理提出了极高要求。TDengine 作为一款高性能、分布式、支持 SQL 的时序数据库&am…...
CentOS更换yum源
CentOS更换yum源 视频教程: https://www.bilibili.com/video/BV1yWaSepE6z/?spm_id_from333.1007.top_right_bar_window_history.content.click 步骤: 第一步: cd /etc/yum.repos.d第二步:cp CentOS-Base.repo CentOS-Base.repo…...
【Kubernetes基础--持久化存储原理】--查阅笔记5
目录 持久化存储机制PV 详解PV 关键配置参数PV 生命周期的各个阶段 PVC 详解PVC 关键配置参数PV 和 PVC 的生命周期 StorageClass 详解StorageClass 关键配置参数设置默认的 StorageClass 持久化存储机制 k8s 对于有状态的容器应用或对数据需要持久化的应用,不仅需…...
数据库子查询实验全解析
目录 一、验证性实验:夯实基础(一)查询同班学生信息(二)查询成绩相关信息(三)查询课程选课人数(四)相关子查询(五)EXISTS嵌套子查询(六…...
HTML:表格数据展示区
<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>人员信息表</title><link rel"styl…...
webgl入门实例-08索引缓冲区的基本概念
WebGL 索引缓冲区 (Index Buffer) 索引缓冲区(也称为元素数组缓冲区)是WebGL中一种优化渲染性能的重要机制,它允许您重用顶点数据来绘制复杂的几何图形。 基本概念 索引缓冲区的工作原理: 您创建一个顶点缓冲区(包含所有顶点数据)然后创建一个索引缓…...
大数据应用开发——大数据平台集群部署
目录 前言 目录 基础环境 安装虚拟机 基础环境 VMware Workstation 虚拟机版本 : centos7 主机名 ip 用户名 密码 master192.168.245.100root123456slave1192.168.245.101root123456slave2192.168.245.102root123456 安装虚拟机 安装 名称、路径自己改 我有16核&…...
GPT对话UI--通义千问API
GPT对话UI 项目介绍 一个基于 GPT 的智能对话界面,提供简洁优雅的用户体验。本项目使用纯前端技术栈实现,无需后端服务器即可运行。 功能特点 💬 实时对话:支持与 AI 进行实时对话交互🌓 主题切换:支持…...
智能体数据分析
数据概览: 展示智能体的累计对话次数、累计对话用户数、对话满意度、累计曝光次数。数据分析: 统计对话分析、流量分析、用户分析、行为分析数据指标,帮助开发者完成精准的全面分析。 ps:数据T1更新,当日12点更新前一天…...
泛型算法——只读算法(一)
在 C 标准库中,泛型算法的“只读算法”指那些 不会改变它们所操作的容器中的元素,仅用于访问或获取信息的算法,例如查找、计数、遍历等操作。 accumulate std::accumulate()是 C 标准库**numeric**头文件中提供的算法,用于对序列…...
树莓派超全系列教程文档--(29)config.txt介绍
config.txt介绍 什么是 config.txt ?文件格式高级功能include条件过滤 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 什么是 config.txt ? Raspberry Pi 设备使用名为 config.txt 的配置文件,而不是传统 PC …...
第十六届蓝桥杯大赛软件赛省赛 C++ 大学 B 组 部分题解
赛时参加的是Python组,这是赛后写的题解,还有两题暂时还不会,待更新 题目链接题目列表 - 洛谷 | 计算机科学教育新生态 A 移动距离 答案:1576 C 可分解的正整数 Python3 import itertools from functools import cmp_to_ke…...
C++栈与堆内存详解:Visual Studio实战指南
C++栈与堆内存详解:Visual Studio实战指南 IDE环境:Visual Studio 2022 一、内存分区与核心概念 在C++程序中,内存分为**栈(Stack)和堆(Heap)**两大核心区域,两者的管理方式、生命周期和适用场景差异显著。 1. 栈内存(Stack Memory) • 特性: • 自动管理:由编…...
在Ubuntu服务器上部署xinference
一、拉取镜像 docker pull xprobe/xinference:latest二、启动容器(GPU) docker run -d --name xinference -e XINFERENCE_MODEL_SRCmodelscope -p 9997:9997 --gpus all xprobe/xinference:latest xinference-local -H 0.0.0.0 # 启动一个新的Docker容…...
非洲电商争夺战:中国闪电战遭遇本土游击队的降维打击
2024年5月,南非电商市场爆发史诗级对决——Temu闪电突袭下载量破百万,却在30天内遭遇Takealot的本土化反击致留存率腰斩。这场价值500亿美元市场的攻防战,揭开了非洲电商最残酷的生存法则:低价利刃砍不动本土化铁壁。 一、跨境模式…...
亚瑟阿伦36问
问 36 个问题,你就能爱上一个人,对方也能爱上你。 第一组 聚焦个人背景与价值观 例如“你最感激生命中的什么?”、“如果可以改变成长经历,你会改变什么?” 1、如果可以跟世上任何人共进晚餐,你会选择谁&…...
Ubuntu 20.04.6编译安装COMFAST CF-AX90无线网卡驱动
目录 0 前言 1 CF-AX90无线网卡驱动 1.1 驱动下载 1.2 驱动准备 2 编译安装驱动 2.1 拷贝驱动依赖到系统 2.2 驱动安装编译 3 重启 0 前言 COMFAST CF-AX90或者说AIC8800D80的Linux版本驱动不支持高版本的linux内核,实测目前仅支持最高5.15的内核。Ubuntu2…...
函数的极限与连续(强化和真题)
强化错题如下:...
4.15【Q】netsafe
我正在学习网络空间安全,” Cookie:使用防hash技术防御SYN泛洪攻击,减少服务器内存消耗“什么意思?什么是SYN泛洪攻击?什么又是防hash技术防御? ?详细解释,越细节越好 连接成功率 …...
多个路由器互通(静态路由)无单臂路由(简单版)
多个路由器互通(静态路由)无单臂路由(简单版) 开启端口并配ip地址 维护1 Router>en Router#conf t Router(config)#int g0/0 Router(config-if)#no shutdown Router(config-if)#ip address 192.168.10.254 255.255.255.0 Ro…...
opencv HSV的具体描述
色调H: 使用角度度量,取值范围为0\~360,从红色开始按逆时针方向计算,红色为0,绿色为120,蓝色为240。它们的补色是:黄色为60,青色为180,紫色为300。通过改变H的值&#x…...
ubuntu磁盘挂载
1、查看磁盘设备及分区 命令:列出所有块设备(磁盘及分区) lsblk 0表示此块未挂载 2、格式化分区 sudo mkfs.ext4 /dev/sdb 注意sdb换成自己的块名称 3、创建挂载点目录 sudo mkdir -p /mnt/data4、永久挂载 sudo blkid /dev…...
Visual Studio C++引入第三方库
前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文主要整理visual studio C导入第三方库的注意事项与操作 bilibili配套视频:【visual studio C导入第三方库-哔哩哔哩】 https://b23.tv/vphfXnv 运行库选项 右键项目 -> 属性 -> C/C ->代码生成->…...
2025中国移动云智算大会回顾:云智变革,AI+跃迁
4月10日,2025中国移动云智算大会在苏州举办。会上,中国移动开启“由云向智”新范式,以“智”为核心开辟算网新生态,彰显其在AI新时代的战略远见与技术引领力。 “云智算”将如何通过算网基础设施与人工智能核心技术的深度融合&am…...
海珠区公示人工智能大模型应用示范区第二批资金奖励企业名单,助力产业蓬勃发展
2025 年 4 月 15 日,广州琶洲人工智能与数字经济试验区管理委员会在广州市海珠区人民政府门户网站发布重要通知,对人工智能大模型应用示范区政策兑现工作(第二批)(大模型专题)资金奖励企业名单予以公示。这…...
golang处理时间的包time一次性全面了解
本文旨在对官方time包有个全面学习了解。不钻抠细节,但又有全面了解,重点介绍常用的内容,一些低频的可能这辈子可能都用不上。主打一个花最少时间办最大事。 Duration对象: 两个time实例经过的时间,以长度为int64的纳秒来计数。 常见的durati…...
文件的加密与解密学习笔记
一些可能想知道的: cryptography库:密码学工具包 Fernet 是crytography 里的一个模块,用于对称加密 with open() as file #为了保证无论是否出错都能正确地关闭文件,与try...finally...相同 open() #用于读文件(默认…...
《TCP/IP网络编程》学习笔记 | Chapter 24:制作 HTTP 服务器端
《TCP/IP网络编程》学习笔记 | Chapter 24:制作 HTTP 服务器端 《TCP/IP网络编程》学习笔记 | Chapter 24:制作 HTTP 服务器端HTTP 概要理解 Web 服务器端无状态的 Stateless 协议请求消息(Request Message)的结构响应消息&#x…...
Apache POI(笔记)
介绍: 坐标: 写入Excel表格: 读取Excel表格:...
Table类型的表单
形如下面的图片 1 label与prop属性 const columns[{label: "文件名",prop: "fileName",scopedSlots: "fileName",},{ label: "删除时间",prop: "recoveryTime",width: "200",},{ label: "大小",prop:…...
Spring 中的验证、数据绑定和类型转换
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...