FreeRTOS学习笔记——FreeRTOS 任务基础知识

2023-05-16

 

  RTOS 系统的核心就是任务管理,FreeRTOS 也不例外,而且大多数学习RTOS 系统的工程师或者学生主要就是为了使用RTOS 的多任务处理功能,初步上手RTOS 系统首先必须掌握的也是任务的创建、删除、挂起和恢复等操作,由此可见任务管理的重要性。由于任务相关的知识很多,所以接下来我们将用几章的内容来讲解FreeRTOS 的任务。本章先学习一下FreeRTOS的任务基础知识,本章是后面学习的基础,所以一定要掌握本章关于FreeRTOS 任务管理的基础知识,本章分为如下几部分:


  5.1 什么是多任务系统

  5.2 FreeRTOS 任务与协程

  5.3 初次使用

  5.3 任务状态

  5.4 任务优先级

  5.5 任务实现

  5.6 任务控制块

  5.7 任务堆栈  

 

  5.1 什么是多任务系统?

  回想一下我们以前在使用51、AVR、STM32 单片机裸机(未使用系统)的时候一般都是在main 函数里面用while(1)做一个大循环来完成所有的处理,即应用程序是一个无限的循环,循环中调用相应的函数完成所需的处理。有时候我们也需要中断中完成一些处理。相对于多任务系统而言,这个就是单任务系统,也称作前后台系统,中断服务函数作为前台程序,大循环while(1)作为后台程序,如图5.1.1 所示:

  前后台系统的实时性差,前后台系统各个任务(应用程序)都是排队等着轮流执行,不管你这个程序现在有多紧急,没轮到你就只能等着!相当于所有任务(应用程序)的优先级都是一样的。但是前后台系统简单啊,资源消耗也少啊!在稍微大一点的嵌入式应用中前后台系统就明显力不从心了,此时就需要多任务系统出马了。多任务系统会把一个大问题(应用)“分而治之”,把大问题划分成很多个小问题,逐步的把小问题解决掉,大问题也就随之解决了,这些小问题可以单独的作为一个小任务来处理。这些小任务是并发处理的,注意,并不是说同一时刻一起执行很多个任务,而是由于每个任务执行的时间很短,导致看起来像是同一时刻执行了很多个任务一样。多个任务带来了一个新的问题,究竟哪个任务先运行,哪个任务后运行呢?完成这个功能的东西在RTOS 系统中叫做任务调度器。不同的系统其任务调度器的实现方法也不同,比如FreeRTOS 是一个抢占式的实时多任务系统,那么其任务调度器也是抢占式的,运行过程如图5.1.2 所示:

  在图5.1.2 中,高优先级的任务可以打断低优先级任务的运行而取得CPU 的使用权,这样就保证了那些紧急任务的运行。这样我们就可以为那些对实时性要求高的任务设置一个很高的优先级,比如自动驾驶中的障碍物检测任务等。高优先级的任务执行完成以后重新把CPU 的使用权归还给低优先级的任务,这个就是抢占式多任务系统的基本原理。

  5.2 FreeRTOS 任务与协程

  再FreeRTOS 中应用既可以使用任务,也可以使用协程(Co-Routine),或者两者混合使用。但是任务和协程使用不同的API 函数,因此不能通过队列(或信号量)将数据从任务发送给协程,反之亦然。协程是为那些资源很少的MCU 准备的,其开销很小,但是FreeRTOS 官方已经不打算再更新协程了,所以本教程只讲解任务。

  5.2.1 任务(Task)的特性

  在使用RTOS 的时候一个实时应用可以作为一个独立的任务。每个任务都有自己的运行环境,不依赖于系统中其他的任务或者RTOS 调度器。任何一个时间点只能有一个任务运行,具体运行哪个任务是由RTOS 调度器来决定的,RTOS 调度器因此就会重复的开启、关闭每个任务。任务不需要了解RTOS 调度器的具体行为,RTOS 调度器的职责是确保当一个任务开始执行的时候其上下文环境(寄存器值,堆栈内容等)和任务上一次退出的时候相同。为了做到这一点,每个任务都必须有个堆栈,当任务切换的时候将上下文环境保存在堆栈中,这样当任务再次执行的时候就可以从堆栈中取出上下文环境,任务恢复运行。

  任务特性:

  1、简单。

  2、没有使用限制。

  3、支持抢占

  4、支持优先级

  5、每个任务都拥有堆栈导致了RAM 使用量增大。

  6、如果使用抢占的话的必须仔细的考虑重入的问题。

  5.2.2 协程(Co-routine)的特性

  协程是为那些资源很少的MCU 而做的,但是随着MCU 的飞速发展,性能越来越强大,现在协程几乎很少用到了!但是FreeRTOS 目前还没有把协程移除的计划,但是FreeRTOS 是绝对不会再更新和维护协程了,因此协程大家了解一下就行了。在概念上协程和任务是相似的,但是有如下根本上的不同:

  1、堆栈使用

  所有的协程使用同一个堆栈(如果是任务的话每个任务都有自己的堆栈),这样就比使用任

  务消耗更少的RAM。

  2、调度器和优先级

  协程使用合作式的调度器,但是可以在使用抢占式的调度器中使用协程。

  3、宏实现

  协程是通过宏定义来实现的。

  4、使用限制

  为了降低对RAM 的消耗做了很多的限制。

  5.3 任务状态

  FreeRTOS 中的任务永远处于下面几个状态中的某一个:

  ● 运行态

  当一个任务正在运行时,那么就说这个任务处于运行态,处于运行态的任务就是当前正在使用处理器的任务。如果使用的是单核处理器的话那么不管在任何时刻永远都只有一个任务处于运行态。

  ● 就绪态

  处于就绪态的任务是那些已经准备就绪(这些任务没有被阻塞或者挂起),可以运行的任务,但是处于就绪态的任务还没有运行,因为有一个同优先级或者更高优先级的任务正在运行!

  ● 阻塞态

  如果一个任务当前正在等待某个外部事件的话就说它处于阻塞态,比如说如果某个任务调用了函数vTaskDelay()的话就会进入阻塞态,直到延时周期完成。任务在等待队列、信号量、事件组、通知或互斥信号量的时候也会进入阻塞态。任务进入阻塞态会有一个超时时间,当超过这个超时时间任务就会退出阻塞态,即使所等待的事件还没有来临!

  ● 挂起态

  像阻塞态一样,任务进入挂起态以后也不能被调度器调用进入运行态,但是进入挂起态的任务没有超时时间。任务进入和退出挂起态通过调用函数vTaskSuspend()和xTaskResume()。任务状态之间的转换如图5.4.1 所示:

  5.4 任务优先级

  每个任务都可以分配一个从0~(configMAX_PRIORITIES-1) 的优先级,configMAX_PRIORITIES 在文件FreeRTOSConfig.h 中有定义,前面我们讲解FreeRTOS 系统配置的时候已经讲过了。如果所使用的硬件平台支持类似计算前导零这样的指令(可以通过该指令选择下一个要运行的任务, Cortex-M 处理器是支持该指令的) , 并且宏configUSE_PORT_OPTIMISED_TASK_SELECTION 也设置为了1 , 那么宏configMAX_PRIORITIES 不能超过32 ! 也就是优先级不能超过32 级。其他情况下宏configMAX_PRIORITIES 可以为任意值,但是考虑到RAM 的消耗,宏configMAX_PRIORITIES最好设置为一个满足应用的最小值。优先级数字越低表示任务的优先级越低,0 的优先级最低,configMAX_PRIORITIES-1 的优先级最高。空闲任务的优先级最低,为0。FreeRTOS 调度器确保处于就绪态或运行态的高优先级的任务获取处理器使用权,换句话说就是处于就绪态的最高优先级的任务才会运行。当宏configUSE_TIME_SLICING 定义为1 的时候多个任务可以共用一个优先级,数量不限。默认情况下宏configUSE_TIME_SLICING 在文件FreeRTOS.h 中已经定义为1。此时处于就绪态的优先级相同的任务就会使用时间片轮转调度器获取运行时间。

  5.5 任务实现

  在使用FreeRTOS 的过程中,我们要使用函数xTaskCreate()或xTaskCreateStatic()来创建任务,这两个函数的第一个参数pxTaskCode,就是这个任务的任务函数。什么是任务函数?任务函数就是完成本任务工作的函数。我这个任务要干嘛?要做什么?要完成什么样的功能都是在这个任务函数中实现的。 比如我要做个任务,这个任务要点个流水灯,那么这个流水灯的程序就是任务函数中实现的。FreeRTOS 官方给出的任务函数模板如下:


  void vATaskFunction(void *pvParameters) (1)

  {

  for( ; ; ) (2)

  {

  --任务应用程序-- (3)

  vTaskDelay(); (4)

  }

  /* 不能从任务函数中返回或者退出, 从任务函数中返回或退出的话就会调用

  configASSERT(),前提是你定义了configASSERT()。如果一定要从任务函数中退出的话那一定

  要调用函数vTaskDelete(NULL)来删除此任务。*/

  vTaskDelete(NULL); (5)

  }  

  void vATaskFunction(void *pvParameters) (1)

  {

  for( ; ; ) (2)

  {

  --任务应用程序-- (3)

  vTaskDelay(); (4)

  }

  /* 不能从任务函数中返回或者退出, 从任务函数中返回或退出的话就会调用

  configASSERT(),前提是你定义了configASSERT()。如果一定要从任务函数中退出的话那一定

  要调用函数vTaskDelete(NULL)来删除此任务。*/

  vTaskDelete(NULL); (5)

  }  

 

  (1)、任务函数本质也是函数,所以肯定有任务名什么的,不过这里我们要注意:任务函数的返回类型一定要为void 类型,也就是无返回值,而且任务的参数也是void 指针类型的!任务函数名可以根据实际情况定义。

  (2)、任务的具体执行过程是一个大循环,for(; ; )就代表一个循环,作用和while(1)一样,笔者习惯用while(1)。

  (3)、循环里面就是真正的任务代码了,此任务具体要干的活就在这里实现!

  (4)、FreeRTOS 的延时函数,此处不一定要用延时函数,其他只要能让FreeRTOS 发生任务切换的API 函数都可以,比如请求信号量、队列等,甚至直接调用任务调度器。只不过最常用的就是FreeRTOS 的延时函数。

  (5)、任务函数一般不允许跳出循环,如果一定要跳出循环的话在跳出循环以后一定要调用函数vTaskDelete(NULL)删除此任务!FreeRTOS 的任务函数和UCOS 的任务函数模式基本相同的,不止FreeRTOS,其他RTOS的任务函数基本也是这种方式的。

  5.6 任务控制块

  FreeRTOS 的每个任务都有一些属性需要存储,FreeRTOS 把这些属性集合到一起用一个结构体来表示,这个结构体叫做任务控制块:TCB_t,在使用函数xTaskCreate()创建任务的时候就会自动的给每个任务分配一个任务控制块。在老版本的FreeRTOS 中任务控制块叫做tskTCB,新版本重命名为TCB_t,但是本质上还是tskTCB,本教程后面提到任务控制块的话均用TCB_t表示,此结构体在文件tasks.c 中有定义,如下:


  typedef struct tskTaskControlBlock

  {

  volatile StackType_t *pxTopOfStack; //任务堆栈栈顶

  #if ( portUSING_MPU_WRAPPERS == 1 )

  xMPU_SETTINGS xMPUSettings; //MPU 相关设置

  #endif

  ListItem_t xStateListItem; //状态列表项

  ListItem_t xEventListItem; //事件列表项

  UBaseType_t uxPriority; //任务优先级

  StackType_t *pxStack; //任务堆栈起始地址

  char pcTaskName[ configMAX_TASK_NAME_LEN ];//任务名字

  #if ( portSTACK_GROWTH > 0 )

  StackType_t *pxEndOfStack; //任务堆栈栈底

  #endif

  #if ( portCRITICAL_NESTING_IN_TCB == 1 )

  UBaseType_t uxCriticalNesting; //临界区嵌套深度

  #endif

  #if ( configUSE_TRACE_FACILITY == 1 ) //trace 或到debug 的时候用到

  UBaseType_t uxTCBNumber;

  UBaseType_t uxTaskNumber;

  #endif

  #if ( configUSE_MUTEXES == 1 )

  UBaseType_t uxBasePriority; //任务基础优先级,优先级反转的时候用到

  UBaseType_t uxMutexesHeld; //任务获取到的互斥信号量个数

  #endif

  #if ( configUSE_APPLICATION_TASK_TAG == 1 )

  TaskHookFunction_t pxTaskTag;

  #endif

  #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) //与本地存储有关

  void

  *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];

  #endif

  #if( configGENERATE_RUN_TIME_STATS == 1 )

  uint32_t ulRunTimeCounter; //用来记录任务运行总时间

  #endif

  #if ( configUSE_NEWLIB_REENTRANT == 1 )

  struct _reent xNewLib_reent; //定义一个newlib 结构体变量

  #endif

  #if( configUSE_TASK_NOTIFICATIONS == 1 ) //任务通知相关变量

  volatile uint32_t ulNotifiedValue; //任务通知值

  volatile uint8_t ucNotifyState; //任务通知状态

  #endif

  #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )

  //用来标记任务是动态创建的还是静态创建的,如果是静态创建的此变量就为pdTURE,

  //如果是动态创建的就为pdFALSE

  uint8_t ucStaticallyAllocated;

  #endif

  #if( INCLUDE_xTaskAbortDelay == 1 )

  uint8_t ucDelayAborted;

  #endif

  } tskTCB;

  //新版本的FreeRTOS 任务控制块重命名为TCB_t,但是本质上还是tskTCB,主要是为了兼容

  //旧版本的应用。

  typedef tskTCB TCB_t;  

 

  可以看出来FreeRTOS 的任务控制块中的成员变量相比UCOSIII 要少很多,而且大多数与裁剪有关,当不使用某些功能的时候与其相关的变量就不参与编译,任务控制块大小就会进一步的减小。

  5.7 任务堆栈

  FreeRTOS 之所以能正确的恢复一个任务的运行就是因为有任务堆栈在保驾护航,任务调度器在进行任务切换的时候会将当前任务的现场(CPU 寄存器值等)保存在此任务的任务堆栈中,等到此任务下次运行的时候就会先用堆栈中保存的值来恢复现场,恢复现场以后任务就会接着从上次中断的地方开始运行。创建任务的时候需要给任务指定堆栈,如果使用的函数xTaskCreate()创建任务(动态方法)的话那么任务堆栈就会由函数xTaskCreate()自动创建,后面分析xTaskCreate()的时候会讲解。如果使用函数xTaskCreateStatic()创建任务(静态方法)的话就需要程序员自行定义任务堆栈,然后堆栈首地址作为函数的参数puxStackBuffer 传递给函数,如下:


  TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,

  const char * const pcName,

  const uint32_t ulStackDepth,

  void * const pvParameters,

  UBaseType_t uxPriority,

  StackType_t * const puxStackBuffer, (1)

  StaticTask_t * const pxTaskBuffer )  

 

  (1)、任务堆栈,需要用户定义,然后将堆栈首地址传递给这个参数。堆栈大小:我们不管是使用函数xTaskCreate()还是xTaskCreateStatic()创建任务都需要指定任务堆栈大小。任务堆栈的数据类型为StackType_t,StackType_t 本质上是uint32_t,在portmacro.h 中有定义,如下:


  #define portSTACK_TYPE uint32_t

  #define portBASE_TYPE long

  typedef portSTACK_TYPE StackType_t;

  typedef long BaseType_t;

  typedef unsigned long UBaseType_t;  

 

  可以看出StackType_t 类型的变量为4 个字节,那么任务的实际堆栈大小就应该是我们所定义的4 倍

 

最后还是给大家搞些FreeRTOS的资料供后续学习参考

实时操作系统-FreeRTOS

http://www.makeru.com.cn/live/1758_1192.html?s=45051

FreeRTOS内核源码深度剖析

http://www.makeru.com.cn/live/4381_1587.html?s=45051​

 

转载于:https://www.cnblogs.com/923327iu/p/11497734.html

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

FreeRTOS学习笔记——FreeRTOS 任务基础知识 的相关文章

  • linux系统编程之进程(八):守护进程详解及创建,daemon()使用

    一 xff0c 守护进程概述 Linux Daemon xff08 守护进程 xff09 是运行在后台的一种特殊进程 它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件 它不需要用户输入就能运行而且提供某种服务 xff0c 不
  • IMU&GPS融合定位::加速度计基本原理

    加速度计基本原理 核心 xff1a 牛顿第二定律 一 mems加速度计基本原理 加速度计基本结构如上图 xff0c 由上电容 中电容板 可移动 下电容板等组成 xff1b 当加速度达到一定值后 xff0c 中电容板会移动 xff0c 与上
  • 深入理解事件(Event)

    前言 在前一篇文章中讲到了Event 发布与订阅 一 里面用到了事件来实现一些发布与订阅 xff0c 当时对事件及其委托理解的还不是太深入 xff0c 可能在使用上有点捉急 这篇来好好讲讲事件 xff0c 以及通过一些小DEMO来加深理解
  • 数据结构知识体系框图

    数据结构知识体系框图 xff1a 静态顺序表 xff1a https blog csdn net adorable article details 78720919 静态顺序表之二 xff1a https blog csdn net ado
  • 想做嵌入式却没经验找不到工作!!!

    从大学三年级就想做嵌入式 xff0c 但是却到处打酱油 先是帮老师做Java项目 xff0c 后来又去外包公司做了一年的通信系统OAM代码维护 xff0c 啥技术也没有学到 现在年底裸辞出来又找不到合适的嵌入式工作 基础知识不够 xff0c
  • 学习一个陌生的开源库的方法建议

    转载 xff0c 初看这句话 xff0c 感觉没什么意义 xff0c 但当你在看开源库的例子的时候 xff0c 不妨多想想这句话 对于一个不熟悉的开源库和模块 xff0c 我觉的最好的学习方法莫过于 xff1a 1 使用库 xff0c 看库
  • 将函数实现放在头文件中

    研究一个开源算法库 xff0c 采用C 43 43 模板编程 xff0c 所有函数实现都放在了头文件中 xff0c 现在把模板去掉 xff0c 链接时发生冲突 xff0c 具体原因如下 xff1a 因为多个源文件包含了含有函数定义的头文件
  • 编译器错误消息: CS1617: 选项“6”对 /langversion 无效

    编译错误 说明 在编译向该请求提供服务所需资源的过程中出现错误 请检查下列特定错误详细信息并适当地修改源代码 编译器错误消息 CS1617 选项 6 对 langversion 无效 xff1b 必须是 ISO 1 ISO 2 3 4 5
  • 无法序列化会话状态

    添加购物车功能遇到返回错误500 xff0c 解决办法 xff1a 因为ajax post请求后 xff0c 只返回错误500的信息 xff0c 并不能清楚的知道具体问题 xff0c 所以要在js处理返回错误500的方法中添加上xhr re
  • C#获取网络图片

    简单获取图片 string url 61 zhi txt Text 图片地址 string dizhi 61 lujing Text 图片下载后保存路径及图片名称要写在一块 WebClient wc 61 new WebClient wc
  • 在vscode中使用Git

    用了git最方便的就是比如在公司写了很多代码后回到家打开vscode只需要点击一下pull就能全部同步过来 是不是很方便 毕竟之前我都是拿u盘拷贝回家或者存到云盘再下载下来 我这里用的是国内的码云托管的代码 xff0c xff0c gith
  • vscode同步设置&扩展插件

    首先安装同步插件 xff1a Settings Sync 第二步 xff1a 进入你的github如图 xff1a 打开设置选项 xff1a 新建一个token xff1a 如图 xff1a 记住这个token值 转到vscode 按shi
  • mysql 常用语句使用

    1 查询语句 SELECT FROM table 2 更改语句 UPDATE table SET name 61 39 123456 39 WHERE id 61 100 3 插入语句 INSERT INTO table VALUES 1
  • STM32学习第七天--串口调试助手没弄懂

    啊啊 啊 今天真的好沮丧 调代码足足调了一晚上 xff0c 不知道什么原因工程就是错 xff0c 最后好不容易啊 xff0c 在主函数加了个 include 34 stm32f10x lib h 34 就好使了 xff0c 真不知道为什么
  • swoole 相关

    安装虚拟机 VMware Workstation Pro 安装CentOS CentOS 7 x86 64 Minimal 1708 iso 安装FinalShell 教程地址 安装lnmp 教程地址 服务状态管理命令 1 安装lnmp 2
  • ffmpeg编程:读取摄像头信息,保存为裸yuv420p、yuyv422视频流

    1 源码下载 xff1a https download csdn net download dijkstar 10898462 2 编程环境使用Windows下的QT5 11 minGW32 xff0c 源码中已经放好了fmpeg的bin
  • C中__FILE__ __LINE__的用法

    include lt stdio h gt void main void printf 34 File s Successfully reached line d n 34 FILE LINE Other statements here l
  • ubuntu中添加和删除源

    添加PPA源的命令为 xff1a br sudo add apt repository ppa user ppa name 添加好更新一下 xff1a sudo apt get update 删除命令格式则为 xff1a br sudo a
  • jetson nano 部署yoloV3,yoloV4,yoloV3-tiny,yoloV4-tiny

    系统 ubuntu nbsp nbsp 自带cuda10 0 nbsp 1 下载与安装darknet git clone https github com AlexeyAB darknet cd darknet 2 以下步骤我都在直接进入c
  • 对比first-fit/best-fit/worst-fit/slab以及buddy这几种算法的特点

    以下均为自己对这些算法的理解 xff1a fitst fit算法 First fit算法 xff1a 连续物理内存分配算法的一种 xff0c 将空闲内存块按照地址从小到大的方式连起来 xff0c 具体实现时使用了双向链表的方式 当分配内存时

随机推荐

  • MIT6_0001F16_Pset2

    MIT6 0001F16 Pset2 完成Hangman Game的编写 xff0c 就是一个猜词游戏 span class token comment Problem Set 2 hangman py span span class to
  • 利用python进行数据分析 pdf

    利用python进行数据分析 链接 xff1a https pan baidu com s 1mFg7kB0WG6edKnhumMbbJg 提取码 xff1a 6kos 如果带来帮助 xff0c 可点赞或关注博主 xff01
  • 数据库系统概念第六版 第六章练习题6.11

    6 11 考虑下图所示的关系数据库 xff0c 主码加了下划线 给出关系代数表达式来表达下列的每一个查询 xff1a a 找出First Bank Corporation的所有员工姓名 b 找出First Bank Corporation所
  • 数据库实验4 SQL语言-SELECT查询操作

    数据库实验4 SQL语言 SELECT查询操作 1 首先按照第三章的jxgl数据库的模板创建jxgl数据库并插入数据 xff1a 创建数据库jxgl create database jxgl 创建相应的表 xff1a 创建student表
  • Docker安装RabbitMQ,RabbitMQ Management使用

    上一篇文章介绍了RabbitMQ的一些基本概念 xff0c 如果没看过没了解 xff0c 推荐先去了解一下 xff1a 下面我们一起来安装一下RabbitMQ并且访问一下它的Management吧 我这边是使用了Docker容器来安装和启动
  • 数据库系统概念第六版 第七章练习题 15 22

    数据库第七章理论习题 7 15 为医院构造一个包含一组病人和一组医生的E R图 为每个病人关联一组不同的检查和化验记录 说明 xff1a 医生和病人间存在联系 xff0c 同时病人有特有的检查和化验记录 xff0c 病人有病床 xff0c
  • 操作系统设计思想--主奴思想

    操作系统设计思想 主奴思想 对于操作系统而言 xff0c 如何稳定可靠运行无疑是最重要的 目前的方案均为将用户进程和其他用户进程 将用户进程和操作系统进行分离 实现操作系统可以管理用户进程 xff0c 但用户进程不能侵入内核 xff0c 同
  • 从零开始学GO ---- 错误处理

    从零开始学GO 错误处理 Go 语言通过内置的错误接口提供了非常简单的错误处理机制 error类型接口 在这个接口类型的声明中只包含了一个方法Error Error方法不接受任何参数 xff0c 但是会返回一个string类型的结果 它的作
  • 从零开始学GO ---- 接口

    从零开始学GO 接口 接口是一个编程规范 xff0c 一组方法签名的集合 Go的接口是非侵入式的设置 xff0c 一个具体类型实现接口不需要在语法上显式地声明 xff0c 只要具体类型的方法集是接口方法集的超集 xff0c 就代表该类型实现
  • Golang通过反射对结构体进行赋值和其他操作

    Golang通过反射对结构体进行赋值和其他操作 通过反射可以方便快捷地访问Golang的结构体字段 xff0c 并进行赋值或其他操作 当两个结构体内容相同但名字不同时 xff0c 如何快捷地进行赋值 xff1f 或者内容有交集 xff0c
  • 如何使用github来下载你需要使用的ros资源

    使用ros系统 xff0c 需要用到许多数据包 xff0c 有些时候你需要使用的ROS数据包并没有Debian包的形式 xff0c 这时你需要从数据源安装它 代码开发人员通常使用的有三种主流的版本控制系统 xff1a SVN xff0c G
  • VLC RTSP视频播放终极解决方案

    VLC播放RTSP视频流遇到的问题 摄像头是RTSP协议的 xff0c 需要在Android端实时显示摄像头视频流 xff0c 这里采用了开源的VLC播放器 xff0c 可能会有如下需求 xff1a 一 有截屏的需求 二 有屏幕录制的需求
  • docker push 实现过程

    这一篇文章分析一下docker push的过程 xff1b docker push是将本地的镜像上传到registry service的过程 xff1b 根据前几篇文章 xff0c 可以知道客户端的命令是在api client push g
  • FreeRTOS专题六:支持多优先级

    在 FreeRTOS 中 xff0c 数字优先级越小 xff0c 逻辑优先级也越小 xff0c 这与RT Thread 和 C OS刚好相反 就绪列表 pxReadyTasksLists configMAX PRIORITIES 是一个数组
  • 操作系统中的中断(详细介绍+图片理解)

    中断的概念 中断是指程序执行过程中 xff0c 遇到急需处理的事件时 xff0c 暂时中止CPU上现行程序的运行 xff0c 转去执行相应的事件处理程序 xff0c 待处理完成后再返回原程序被中断处或调度其他程序执行的过程操作系统是 中断驱
  • Android 如何杀死Service

    方法很简单就是用ActivityManager private void killeService List lt RunningAppProcessInfo gt infos TODO 自动生成的方法存根 ActivityManager
  • [自动驾驶]Build a Traffic Sign Recognition Program

    看 准确率98 的深度学习交通标志识别是如何做到的 xff1f 这篇文章的时候 xff0c 发现了udacity的自动驾驶课程 可惜要收费 xff0c 不过课程project在github上有 xff0c 那直接做project就好了 xf
  • 教你快速学习PID控制原理

    教你快速学习PID控制原理 写在前面 在这篇文章中我会通过举例的方式来让大家了解什么是PID控制 xff0c 这篇博客是让大家更加容易的理解PID控制 xff0c 如果大家想要跟深入的了解的话最好是自己上手去做一个关于PID控制的实物 xf
  • opencv HSV找颜色,找轮廓用最小旋转矩形框出

    include lt opencv2 opencv hpp gt include lt iostream gt include lt string gt using namespace cv using namespace std 输入图像
  • FreeRTOS学习笔记——FreeRTOS 任务基础知识

    RTOS 系统的核心就是任务管理 xff0c FreeRTOS 也不例外 xff0c 而且大多数学习RTOS 系统的工程师或者学生主要就是为了使用RTOS 的多任务处理功能 xff0c 初步上手RTOS 系统首先必须掌握的也是任务的创建 删