内核基础
包括:内核简介、系统的启动流程及内核配置的部分内容,为后面的章节奠定基础。
RT-Thread 内核介绍
内核是一个操作系统的核心,是操作系统最基础也最重要的部分。它负责管理系统的线程、线程间通信、系统时钟、中断及内存等。
下图为RT-Thread内核架构图,可以看到内核处于硬件层之上,内核部分包括内核库、实时内核实现。
内核库是为了保证内核能够独立运行的一套小型的类似C库的函数实现子集。这部分根据编译器的不同,自带C库的情况也会有些不同,当使用GNU GCC编译器时,会携带更多的标准C库实现。
C库:也叫C运行库(C Runtime Library),它提供了类似strcpy、memcpy等函数,有些也会包括"printf"、“scanf”函数的实现。
RT-Thread Kernel Service Library仅提供内核用到的一小部分C库函数实现,为了避免与标准C库重名,这些函数前都会加上rt_前缀。
实时内核的实现包括:对象管理、线程管理及调度器、线程间通信管理、时钟管理及内存管理等,内核最小的资源占用情况是3KB ROM,1.2KB RAM。
线程管理
线程是RT-Thread操作系统中最小的调度单位,线程调度算法是基于优先级的全抢占式多线程调度算法,即在系统中除了中断处理函数、调度器上锁部分的代码和禁止中断的代码是不可抢占的之外,系统的其它部分都是可以抢占的,包括线程调度器自身。
支持256个线程优先级(也可通过配置文件更改为最大支持32个或8个线程优先级,针对STM32默认配置是32个线程优先级),0优先级代表最高优先级,最低优先级留给空闲线程使用;同时它也支持创建多个具有相同优先级的线程,相同优先级的线程间采用时间片的轮转调度算法进行调度,使每个线程运行相应时间;调度器在寻找那些处于就绪状态的具有最高优先级的线程时,所经历的时间是恒定的。
系统也不限制线程数量的多少,线程数目只和硬件平台的具体内存相关。
时钟管理
RT-Thread的时钟管理以时钟节拍为基础,时钟节拍是RT-Thread操作系统中最小的时钟单位。
RTT的定时器提供两类定时器机制:第一类是单次触发定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。
第二类是周期触发定时器,这类定时器会周期性的触发定时器事件,直到用户手动的停止定时器,否则将永远持续执行下去。
另外,根据超时函数执行时所处的上下文环境,RT-Thread的定时器可以设置为HARD_TIMER模式或者SOFT_TIMER模式。
通常使用定时器定时回调函数(即超时函数),完成定时服务。用户根据自己对定时处理的实时性要求选择合适类型的定时器。
线程间同步
RT-Thread采用信号量、互斥量与事件集实现线程间同步。
线程通过对信号量、互斥量的获取与释放进行同步。
互斥量采用优先级继承的方式解决了实时系统常见的优先级翻转问题。
线程同步机制支持按优先级等待方式获取信号量或互斥量。
线程通过对事件的发送与接收进行同步。
事件集支持多个事件的“或触发”和“与触发”,适合于线程等待多个事件的情况。
线程间通信
RT-Thread支持邮箱和消息队列等通信机制。
邮箱中一封邮件的长度固定为4字节大小;消息队列能够接收不固定长度的消息,并把消息缓存在自己的内存空间中。
邮箱效率较消息队列更为高效。
邮箱和消息队列的发送动作可安全用于中断服务例程中。
通信机制支持线程按优先级等待方式获取。
内存管理
RT-Thread支持静态内存池管理及动态内存堆管理。
当静态内存池具有可用内存时,系统对内存块分配的时间将是恒定的。
当静态内存池为空时,系统将申请内存块的线程挂起或阻塞掉(即线程等待一段时间后仍未获得内存块就放弃申请并返回,或者立刻返回。等待的时间取决于申请内存块时设置的等待时间参数),当其它线程释放内存块到内存池时,如果有挂起的待分配内存块的线程存在的话,则系统会将这个线程唤醒。
动态内存堆管理模块在系统资源不同的情况下,分别提供了面向小内存系统的内存管理算法及面向大内存系统的SLAB内存管理算法。
还有一种动态内存堆管理叫做memheap,适用于系统含有多个地址且不连续的内存堆。使用memheap可以将多个内存堆“粘贴”在一起,让用户操作起来像是在操作一个内存堆。
I/O设备管理
RT-Thread将PIN、I2C、SPI、USB、UART等作为外设设备,统一通过设备注册完成。实现了按名称访问的设备管理子系统,可按照统一的API界面访问硬件设备。
在设备驱动接口上,根据嵌入式系统的特点,对不同的设备可以挂接相应的事件。当设备事件触发时,由驱动程序通知给上层的应用程序。