项目实战-外卖自提柜 3. FreeRTOS主要API的应用

2023-05-16

项目实战-外卖自提柜 1.项目介绍、协议制定
项目实战-外卖自提柜 2. CubeMX + FreeRTOS入门
项目实战-外卖自提柜 3. FreeRTOS主要API的应用
项目实战-外卖自提柜 4. FreeRTOS 堆栈分配、调试技巧
项目实战-外卖自提柜 5. ESP8266 01S配置与掉线处理
项目实战-外卖自提柜 6. 硬件工作与测试(原理图、PCB绘制、测试视频)

一、第一个任务

        初步入门FreeRTOS以后,着重解决通信部分,重新梳理一下与服务器通信部分的需求:

1、设备端和服务器通信,发送方每发送一条指令,接收方都要在收到后返回一个应答帧,发送方收到应答帧后,才判断此次通信正常,若规定时间内未收到应答帧,则重新发送。
2、另外需要注意的是,发送方在等待接收方返回应答帧时,不能阻塞系统运行,也就是说,即便当前有一帧数据在等待应答,也不影响下一帧数据的发送,且理论上应该保证同时在等待应答的帧的数量不受限制

        根据上述需求,显而易见的,应当把每一帧的发送单独作为一个任务,这个任务对这一帧进行监听,并控制重发。只要系统还有足够的剩余栈,就可以不断地创建新的发送任务,这样就可以保证最大限度地使用硬件资源保证每一帧的通信【并行】。
        刚好,FreeRTOS创建任务时是可以传入一个参数的,这个参数就可以传入我们要发送的数据。
        第一个任务诞生了:

数据发送任务:

/**
  * @brief  数据发送任务
  * @note	需要向服务器发送一条指令时,就创建一个发送任务,特点是等待回复和重发时不会阻塞其他任务进行
  * @param  argument:要发送的数据
  * @retval None
  */
void SendData_Task(void const * argument)
{
	//待添加
	for(;;)
	{
		//待添加
	}
}

下面来构思函数体中要写些什么

首先,肯定是要发送数据了,发送数据之前,有一件事要考虑,由于传入的是argument是指针,这个任务在进行过程中,这个指针指向的内容很可能被其他任务更改,所先需要先申请空间来拷贝要发送的数据
再来回顾一下帧格式:
帧头 + Length + CmdId + DevId + Content + FrameId + 校验和

成分描述
帧头0x0a 0x0a 0x0a 0x0a
Length指令字节数总长度,包括其本身和校验和,两个字节的无符号short类型,顺序为 [低字节,高字节]
CmdId指令的Id , 一个字节的无符号byte类型
DevId目标设备的Id,两个字节的无符号short类型,顺序为 [低字节,高字节]
Content该条指令包含的详细信息
FrameId每一帧的唯一Id,两字节无符号short类型,顺序为[低字节,高字节]
校验和一字节有符号byte类型

我们通过上述的Length获取数据长度,然后用FreeRTOS提供的API:
pvPortMalloc 申请内存,这个函数与C语言的malloc的区别是,前者从FreeRTOS的TOTAL_HEAP_SIZE中申请空间,而后者是从系统的堆(heap)中申请空间。
详细的分析看这篇博客:
https://www.cnblogs.com/LinTeX9527/p/8007541.html

数据发送任务的前几行代码有着落了:

void SendData_Task(void const * argument)
{
	uint8_t *Data;				//创建指针
	uint16_t Data_Len = 0;		//数据长度
	Data_Len = ((uint16_t*)argument)[0];//获取数据长度
	Data = pvPortMalloc(Data_Len-1);	//申请内存,去掉校验和1字节
	memcpy(Data,(uint8_t*)argument,sizeof(uint8_t)*(Data_Len-1));	//复制数组,去掉校验和
	for(;;)
	{
		//待添加
	}
}

二、互斥量的使用

        当然,如果这里严谨一点的话,你会发现,即便这里进行了数据拷贝,但拷贝也不是一瞬间完成的,所以拷贝的时候,这段数据仍然不是安全的,仍可能被更改,下面就用到FreeRTOS的另一个功能了: 互斥量

        正如其名,一个资源在被一个任务访问时,不能再被另一个任务访问,就叫互斥
        通过下面两个函数实现互斥:

osMutexWait(mutex_CopyData_h, osWaitForever);	//等待互斥量被释放
osMutexRelease(mutex_CopyData_h);	//释放互斥量

        其中mutex_CopyData_h是互斥量的句柄(可以看作是名称),osWaitForever表示一直阻塞等待,直到互斥量被释放。

        如何使用呢?
        按照上述情形举例,我们要在拷贝数据时用互斥量进行保护,数据发送任务就改进为下面这种形式:

/**
  * @brief  数据发送任务
  * @note	需要向服务器发送一条指令时,就创建一个发送任务,特点是等待回复和重发时不会阻塞其他任务进行
  * @param  argument:要发送的数据
  * @retval None
  */
void SendData_Task(void const * argument)
{
	uint8_t *Data;				//申请内存指针
	uint16_t Data_Len = 0;		//数据长度
	Data_Len = ((uint16_t*)argument)[0];//获取数据长度
	Data = pvPortMalloc(Data_Len-1);	//申请内存,去掉校验和1字节
	osMutexWait(mutex_CopyData_h, osWaitForever);	//等待互斥量被释放
	/*被互斥量保护的区域*/
	memcpy(Data,(uint8_t*)argument,sizeof(uint8_t)*(Data_Len-1));	
	/*被互斥量保护的区域*/
	osMutexRelease(mutex_CopyData_h);	//释放互斥量
	for(;;)
	{
		//待添加发送函数
	}
}


        osMutexWaitosMutexRelease之间,就是我们希望保护的位置。当然这只完成了一半,同样的,我们需要在存在数据覆盖风险的位置设置互斥量的保护区。

        例如下面:传入数据发送任务的参数是名为Data_Buf的数组

osThreadDef(DATA_SEND_TASK_H,SendData_Task, osPriorityHigh,0, 128);	//心跳帧重发任务的宏
osThreadCreate(osThread(DATA_SEND_TASK_H),Data_Buf)

        那么我需要在修改Data_Buf的位置设置互斥量保护区:

osMutexWait(mutex_CopyData_h, osWaitForever);	//等待互斥量被释放
Data_Buf[0] = 0;
osMutexRelease(mutex_CopyData_h);	//释放互斥量

        被互斥量保护的区域,同时只能被一个任务访问,直到这个任务释放互斥量,下一个任务才能访问。这样,我们就可以保证拷贝数据的时候,数据不会被误修改。

三、消息队列的使用

        我们继续完善数据发送任务,回到需求分析,数据发送任务除了需要完成数据发送,还需要监听是否收到与此帧数据匹配的应答帧。如果同时有好几个数据发送任务在等待应答帧,这时候收到了一条应答帧,对于某一个数据发送任务来说,如何判断这条应答帧是发给自己的呢?

        上翻查阅数据帧格式的表格,可以看到,每一帧数据有唯一的FrameId,回复帧也有FrameId,它的FrameId与它要回复的数据帧的FrameId相同。对于某一个数据发送任务来说,它只需要与收到的回复帧的FrameId进行匹配,若与自己的Frame相同,则判断这个回复帧是回复给自己的,如果是回复给自己的,这个数据发送任务就完成了自己的使命,可以把自己删除了。所以当有多帧数据同时等待回复帧时,需要开设一个缓存区,存放收到的回复帧的FrameId,供数据发送任务查询。

        这个缓存区,就交给 消息队列来完成。FreeRTOS对消息队列的处理,我用到了下面几个API:

//查询队列中元素的个数
osMessageWaiting(MsgBox_Frame_Id_Handle);
//获取并删除队列中的一个元素
osMessageGet(MsgBox_Frame_Id_Handle,osWaitForever);
//向队列存放一个元素
osMessagePut(MsgBox_Frame_Id_Handle,evt.value.v,osWaitForever);
  • MsgBox_Frame_Id_Handle是这个队列的句柄
  • osWaitForever表示这个函数执行的超时时间,超过了这个值就会自动退出,这里是永久等待
  • evt.value.v是要向队列里存入的元素

        如何实现查询队列中是否有与自己匹配的FrameId呢?

        我的思路是,先通过osMessageWaiting读出当前队列中元素的数量N,进入循环,每个循环中,使用osMessageGet取出一个元素,由于队列是先进先出,所以这个元素是从队列头部取出的,判断是否匹配,如果匹配,皆大欢喜,这个数据发送任务就解脱了;如果不匹配,再将这个元素用osMessagePut重新加入到队列尾部,这样循环N次,就相当于把队列查询了一遍。

        数据发送任务就基本完成了:

/**
  * @brief  数据发送任务
  * @note	需要向服务器发送一条指令时,就创建一个发送任务,特点是等待回复和重发时不会阻塞其他任务进行
  * @param  argument:要发送的数据
  * @retval None
  */
void SendData_Task(void const * argument)
{
	uint8_t *Data;				//申请内存指针
	uint16_t Data_Len = 0;		//数据长度
	Data_Len = ((uint16_t*)argument)[0];//获取数据长度
	uint16_t FrameId = 0;		//帧Id
	uint32_t MsgBox_Data_Num = 0;//队列中有效数据的数量
	osEvent evt;				//存放osMessageGet的返回值
	Data = pvPortMalloc(Data_Len-1);	//申请内存,去掉校验和1字节
	osMutexWait(mutex_CopyData_h, osWaitForever);	//等待互斥量被释放
	/*被互斥量保护的区域*/
	memcpy(Data,(uint8_t*)argument,sizeof(uint8_t)*(Data_Len-1));	
	/*被互斥量保护的区域*/
	osMutexRelease(mutex_CopyData_h);	//释放互斥量
	FrameId = (uint16_t)Data[Data_Len-2]<<8|(uint16_t)Data[Data_Len-3];	//装载这一帧数据的FrameId
	for(;;)
	{
		osMutexWait(mutex_id_Resend, osWaitForever);//获取互斥量,防止其他的数据发送任务打断
		MsgBox_Data_Num = osMessageWaiting(MsgBox_Frame_Id_Handle);	//获取当前队列数量
		if(MsgBox_Data_Num != 0)		//如果队列非空
		{
			for(i=0;i<MsgBox_Data_Num;i++)
			{
				evt = osMessageGet(MsgBox_Frame_Id_Handle,100);	//从队列中取出一个元素
				if(evt.value.v == FrameId)		//如果FrameId匹配
				{
					/****删除任务****/
					osMutexRelease(mutex_id_Resend);	//释放令牌
					vPortFree(Data);					//释放内存
					osThreadTerminate (NULL);			//删除本任务
				}
				else		//如果不匹配
				{
					osMessagePut(MsgBox_Frame_Id_Handle,evt.value.v,500) //存回队列尾
				}
			}
		}
		User_SendData(Data,Data_Len);	//发送数据
		osMutexRelease(mutex_id_Resend);//释放互斥量
		osDelay(5000);	//每5s检测一次
	}
}

        除了上面的思路,我这里还使用了一个互斥量,用以保护整个发送过程,因为当有多个数据发送任务都再执行时,队列的取出和放回动作可能会被打断,出现某种极端情况。

        例如任务A刚刚从队列中取出一个元素,发现跟自己的FrameId不匹配,但还没来得及放回去,CPU控制权就被任务B抢去了,任务B查询的时候,就少了这个任务A取走的元素,造成误判。
        另外,发送数据是通过串口的,执行时间也比较长,如果发送时被打断,可能造成不可预估的后果,所以使用互斥量进行保护是十分有必要的。

        在整个项目中,主要用到的就是上面几个API数据发送任务,也是仅有的稍显复杂的任务,另外还有一些调试用的API,下一节更新。

 

四、任务划分

        根据功能划分了下面几个任务

  1. 人机交互任务:
    包括按键扫描、LCD显示、蜂鸣器扫描,优先级较低

  2. 无线模块管理任务:
    包括检测到服务器离线时,对WIFI模块/GPRS模块进行重新初始化,切换wifi网络或运营商网络模式等,优先级最高

  3. TCP透传发送任务
    当要发送一帧数据时,该任务被创建,发送一帧数据,并对这帧数据进行监听,等待接收方回复,若未收到回复,则重新发送,通信完成则删除本任务。优先级较高

  4. TCP接收数据解析任务
    由接收中断触发,解析数据,执行相应操作,优先级最高

        这里简单列两个
        人机交互任务:

/**
  * @brief  人机交互任务
  * @note	包括按键扫描、LCD显示、蜂鸣器鸣叫
  * @param  argument:任务参数(未用到)
  * @retval None
  */
void Interactive_Task(void const * argument)
{
	for(;;)
	{
		/**矩阵键盘扫描**/
		/**键值处理**/
		/**LCD显示**/
		/**蜂鸣器扫描**/
		osDelay(20);
	}
}

        无线模块管理任务:

/**
  * @brief  无线模块管理任务
  * @note	检测服务器是否离线,若离线则重新初始化无线模块
  * @param  argument:任务参数(未用到)
  * @retval None
  */
void WirelessCTR_Task(void const * argument)
{
	osDelay(1000);		//等待ESP8266上电
	for(;;)
	{
		if(server_sta == SERVER_OFF_LINE)	//服务器离线
		{
//			osThreadSetPriority(NULL,osPriorityHigh);	//调高优先级,防止打断
			esp8266_init();		//初始化esp8266
//			osThreadSetPriority(NULL,osPriorityNormal);	//调低优先级
		}
		osDelay(20);
	}
}

代码和硬件都打包上传至立创开源社区了:
https://oshwhub.com/doee/wai-mai-zi-ti-gui-she-bei-duan-z

项目实战-外卖自提柜 1.项目介绍、协议制定
项目实战-外卖自提柜 2. CubeMX + FreeRTOS入门
项目实战-外卖自提柜 3. FreeRTOS主要API的应用
项目实战-外卖自提柜 4. FreeRTOS 堆栈分配、调试技巧
项目实战-外卖自提柜 5. ESP8266 01S配置与掉线处理
项目实战-外卖自提柜 6. 硬件工作与测试(原理图、PCB绘制、测试视频)

https://blog.csdn.net/weixin_44578655/article/details/105969808

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

项目实战-外卖自提柜 3. FreeRTOS主要API的应用 的相关文章

  • 什么是枚举【详解】

    本期介绍 x1f356 主要介绍 xff1a 什么是枚举 xff0c 枚举是如何定义 初始化的 xff0c 以及枚举到底如何使用 xff0c 还有枚举这种语法存在的优点有那些 x1f440 文章目录 一 什么是枚举 x1f356 二 枚举类
  • vscode将项目导入远程仓库 git

    1 打开软件 点击第三个图标 远程仓库 点击代码管理右上角三个小点 远程 远程仓库 添加远程存储库 跳出输入框 2 复制git的地址 3 将上一步复制的仓库链接 粘贴进去 回车 4 命名 5 打开命令行 输入下列命令 用户名 邮箱 PS D
  • 深度学习二

    BT神经元为按照误 差逆向传播算法训练的多层前馈神经网络 BT神经网络分为输入层 隐藏层 输出层 输入层一般有数据种类多个神经元 xff0c 接受数据 隐藏层的神经元为根号下隐藏层 输出层加b个 xff0c 输入的每个数据加权和返回数之和为
  • ROS学习(五)

    学习古月 ROS机器人开发实践 一书时 xff0c 在第六章的6 3遇到的问题的总结 在执行将xacro文件转化成urdf的文件格式时 xff0c 执行语句 rosrun xacro xacro py mrobot urdf xacro g
  • 新建Mavlink消息

    1 下载Mavlink生成器 1 1 Git clone 需要在翻墙的网络环境下下载 span class token function git span clone https github com mavlink mavlink git
  • Python从入门到精通11天(lambda匿名函数和map函数的使用)

    lambda匿名函数和map函数的使用 lambda匿名函数map函数lambda与map的联用 lambda匿名函数 匿名函数在计算机编程中是指一类无需定义标识符 xff08 函数名 xff09 的函数或子程序 xff0c lambda函
  • STM32F407单片机移植ADS1115驱动程序

    最近一个工程项目需要使用ADS1115采集电压 xff0c 网上研究了一下 xff0c 测试成功 xff0c 期间走了很多弯路 xff0c 为避免后来的研究者重走我的老路 xff0c 特分享给大家 注 xff1a 网上很多ADS1115驱动
  • Python入门到精通12天(迭代器与生成器)

    迭代器与生成器 迭代器生成器 迭代器 迭代器是可迭代的对象 xff0c 即可以进行遍历的对象 列表 字符串 元组 字典和集合这些都是可迭代的对象 xff0c 都可以进行遍历 迭代器是一种访问序列元素的方式 xff0c 它可以通过next 函
  • C语言从入门到精通第8天(分支结构if、else、switch的使用)

    分支结构if else switch的使用 if语句if else语句if else嵌套if else if else语句switch语句 if语句 语法 xff1a if 表达式 语句 xff1b 如果表达式为真 xff0c 则执行 里面
  • Python入门到精通13天(global和nonlocal关键字的使用)

    global和nonlocal关键字的使用 作用域global关键字的使用nonlocal关键字的使用 作用域 在Python中变量的作用域由其代码块决定 xff0c 在代码块中定义的的变量和函数属于局部作用域 xff1b 在函数中定义的变
  • Python从入门到精通14天(eval、literal_eval、exec函数的使用)

    eval literal eval exec函数的使用 eval函数literal eval函数exec函数三者的区别 eval函数 eval 是Python中的内置函数 xff0c 它可以将一个字符串作为参数 xff0c 并将该字符串作为
  • Python从入门到精通15天(浅拷贝和深拷贝)

    浅拷贝和深拷贝 深浅拷贝概述浅拷贝深拷贝 深浅拷贝概述 在Python中 xff0c 对象是通过引用传递的 xff0c 这意味如果创建了一个对象 xff0c 然后将其赋值给另一个变量 xff0c 那么两个变量将引用同一个对象 xff0c 即
  • C语言从入门到精通第9天(循环结构的使用)

    循环结构的使用 while语句do while语句for语句嵌套循环 循环结构可以重复的执行一段代码块 xff0c 在C语言中提供了三种不同类型的循环结构 xff1a for while和do while while语句 语法 xff1a
  • C语言从入门到精通第10天(break和continue的使用)

    break和continue的使用 break语句continue语句 break和continue是两种控制流程的语句 xff0c 他们只能在循环中被使用 xff0c 用于控制循环的执行 如果在非循环中被使用了则会导致语法的错误 brea
  • C语言从入门到精通第11天(数组的基本操作)

    数组的基本操作 数组的概念一维数组二维数组 数组的概念 在程序设计中 xff0c 为了方便处理数据把具有相同类型的若干变量按有序形式集合在一起 xff0c 这些按序排列的同类数据元素的集合称为数组 在C语言中 xff0c 数组属于构造数据类
  • C语言从入门到精通第12天(函数的定义)

    函数的定义 函数的概念函数的定义函数的参数函数的返回值 函数的概念 在程序设计中 xff0c 为了实现某个功能需要编写多行代码 xff0c 我们每次在使用时都将原来的代码重复编码 xff0c 这样就非常的麻烦 xff0c 而且编程的效率也不
  • C语言从入门到精通第13天(函数的调用)

    函数的调用 无参函数的调用有参函数的调用函数的嵌套调用递归函数的调用函数的声明 函数在定义完以后 xff0c 如果不被调用时不会被执行到的 xff1b 在程序中main函数是主函数 xff0c 是会被自动调用 xff0c C程序有且只有一个
  • 项目实战-外卖自提柜 2. CubeMX + FreeRTOS入门

    项目实战 外卖自提柜 1 项目介绍 协议制定 项目实战 外卖自提柜 2 CubeMX 43 FreeRTOS入门 项目实战 外卖自提柜 3 FreeRTOS主要API的应用 项目实战 外卖自提柜 4 FreeRTOS 堆栈分配 调试技巧 项
  • C语言从入门到精通第14天(局部变量和全局变量)

    局部变量和全局变量 局部变量全局变量 局部变量 简单来说 xff0c 在C语言中的局部变量就是定义在 中的变量 xff0c 他的作用域也在 内 xff0c 他的生命周期随着 结束而结束 例如 xff1a span class token k
  • C语言从入门到精通第15天(C语言预处理)

    C语言预处理 预处理概述宏定义条件编译 预处理概述 在前面我们已经对C语言的基础语法知识有所了解了 xff0c 每次进行程序的编写之前 xff0c 我们会使用 include命令去导入我们的库函数 xff0c 而这种以 号开头的命令称为预处

随机推荐

  • C语言从入门到精通第16天(指针的定义与基本使用)

    指针的定义与基本使用 什么是指针 xff1f 指针变量的定义指针变量的基本使用 什么是指针 xff1f 在使用指针之前我们需要对指针进行初步的了解 xff0c 首先我们要知道什么是指针 xff1f 通过前面的学习我们已经知道了内存的存储方式
  • 作为一个大学生你应该知道的事情

    作为一个大学生你应该知道的事情 大学生毕业去向 今天 xff0c 我们不写技术 xff0c 来谈一谈大学生的毕业现状 xff1a 以下内容为本人的一些观点和看法 xff0c 仅限于沟通交流 大学生毕业去向 大学生的毕业去向大致可以分为 xf
  • C语言从入门到精通第17天(指针和数组联用)

    指针和数组联用 不同类型指针变量之间的区别数组的指针指针数组 不同类型指针变量之间的区别 在了解数组和指针联用之前 xff0c 我们先对指针变量进行补充 我们对比一下int p1和char p2的区别 xff1f 相同点 xff1a 都是指
  • 使用 Keil uVision 和 STM32CubeMX 对 STM32F103C8 进行编程

    采用ARM Cortex M架构的STM32微控制器因其特性 成本和性能而在许多应用中得到广泛应用 在之前的教程中 xff0c 我们已经使用Arduino IDE编程了STM32F103C8 使用Arduino IDE编程STM32很简单
  • 适用于 STM32F103C8 的 FreeRTOS,STM32的多任务同时进行

    概述 xff1a 适用于 STM32F103C8 的 FreeRTOS STM32F103C 是一款ARM Cortex M3 处理器 我们可以在 Arduino IDE 中使用适用于 STM32F103C8 的 FreeRTOS 我们也可
  • PLC为什么会被上位机取代

    随着我们进入高速发展的轨道 xff0c 许多工厂都已经完成了自动化流水线生产的打造 我们可以看到很多大厂已经搭建了智能生产线 所以越来越多的plc工程师开始感觉到 xff0c 只会传统的plc控制 xff0c 已经无法满足公司的企业发展业务
  • 【Vue2】生命周期——钩子函数

    钩子函数 xff1a 在一个Vue实例从创建到销毁的过程自动执行的函数 1 分析生命周期 1 xff09 初始化阶段 xff1a beforeCreate xff08 xff09 生命周期中第一个函数 xff0c 在该函数执行时Vue实例仅
  • 计算机考研全年规划

    此文转载的 xff0c 作为参考 文章目录 一 关于考研常识二 择校择专业 xff08 一 xff09 为什么要考研 xff08 二 xff09 怎么样才能考上研究生 xff08 三 xff09 如何择校选专业1 学硕和专硕该如何选择 xf
  • c#串口编程(傻瓜教程,手把手教你学会)

    在单片机项目开发中 xff0c 上位机也是一个很重要的部分 xff0c 主要用于数据显示 xff08 波形 温度等 xff09 用户控制 xff08 LED xff0c 继电器等 xff09 xff0c 下位机 xff08 单片机 xff0
  • CMakeLists.txt编写规则

    一 基本语法 语法格式 指令 参数1 参数2 1 参数间用空格或分号隔开 2 指令大小写无关 参数和变量大小写相关 3 变量用 方式取值 但在if语句中直接用变量名 二 重要指令 1 cmake minimum required 指定CMa
  • [stm32] Start Tour-一些元件的连接

    如果觉得有帮助的话就点个赞吧 持续更新 目录 一 蜂鸣器 注意点 xff1a 二 独立按键 一 蜂鸣器 根据原理图连的实物图如右 xff1a 注意点 xff1a 1 xff09 蜂鸣器分正负极 2 xff09 VCC和GND是32板的总电源
  • ROS中Gazebo无响应解决办法

    标题ROS中Gazebo无响应解决办法 在终端输入gazebo没有反映 xff0c 进行下面两句操作 首先输入下面的代码 gazebo verbose 观察到报错显示原因为有另一个gazebo进程于是杀死这个进程则问题解决代码如下 xff1
  • 别害羞,开源社区真的很需要你,教你如何参与开源社区~

    前言 相信各位开发者多多少少会在实际开发的过程中会使用一些开源的技术 xff0c 例如前端的 vue react 以及大量的第三方库如 echart xff0c color js day js 等等 xff0c 后端就更多了 xff0c 从
  • VBox 快照备份虚拟机

    目录 虚拟机快照概念 什么是虚拟机快照 VBox 快照备份恢复 FreeBSD 系统 拍摄 Snapshots 快照 拍摄快照示例 恢复快照 虚拟机快照概念 什么是虚拟机快照 简单来说 xff0c 就是将你当前状态的虚拟机复制保存一份镜像
  • [Linux 调试 Android]-Linux 命令行调试 Android 设备

    目录 Slackware 15 0 下调试安卓 4 4 2 系统环境配置 获取 linux 版本的 adb 程序 将 ADB 程序安装到 Linux 系统上 配置 adb 环境变量 在 Linux 系统上 adb 调试安卓系统 Slackw
  • docker 容器如何查看正在运行容器的端口映射

    1 查看docker容器的版本 root 64 opt docker version Docker version 19 03 5 build 633a0ea 2 查看正在运行的容器 root 64 opt docker ps CONTAI
  • docker退出关闭容器

    可以使用 docker stop 来终止一个运行中的容器 此外 xff0c 当Docker容器中指定的应用终结时 xff0c 容器也自动终止 例如对于上一章节中只启动了一个终端的容器 xff0c 用户通过 exit 命令或 Ctrl 43
  • STM32收入高也好找工作,所以我学嵌入式linux终究是错付了吗

    STM32收入高也好找工作 xff0c 所以我学嵌入式linux终究是错付了吗 经常有同学纠结问我 xff1a 我到底是学STM32还是学嵌入式linux 这个问题很多人都会有自己的看法 xff0c 今天我试着从多个角度 xff0c 把了解
  • Java面试基础篇

    Java面试基础篇 基础总结 博客链接导航 Java语言基础常识 https blog csdn net article details 88531257 J2EE基础知识 https blog csdn net article detai
  • 项目实战-外卖自提柜 3. FreeRTOS主要API的应用

    项目实战 外卖自提柜 1 项目介绍 协议制定 项目实战 外卖自提柜 2 CubeMX 43 FreeRTOS入门 项目实战 外卖自提柜 3 FreeRTOS主要API的应用 项目实战 外卖自提柜 4 FreeRTOS 堆栈分配 调试技巧 项