RTT3-RTThread内核实验-任务的基本管理

合集下载

rtthread 任务调度原理

rtthread 任务调度原理

rtthread 任务调度原理(原创版)目录1.RT-Thread 简介2.任务调度原理3.RT-Thread 的任务管理4.RT-Thread 的任务调度方式5.总结正文RT-Thread 是我国自主研发的一款面向物联网和嵌入式系统的实时操作系统。

其全称是 Real-Time Thread,意指实时线程。

RT-Thread 具有小巧轻量、可扩展性强、实时性能优异等特点,广泛应用于各种物联网设备和嵌入式系统中。

一、RT-Thread 简介RT-Thread 操作系统的底层是基于线程调度的,它将任务调度作为核心功能,以满足物联网设备对实时性能的高要求。

在 RT-Thread 中,任务调度原理是基于优先级和时间片轮转的。

通过这种原理,RT-Thread 可以实现对多个任务的公平调度和高效运行。

二、任务调度原理RT-Thread 的任务调度原理主要包括两个方面:任务优先级和时间片轮转。

1.任务优先级:RT-Thread 中的任务分为多个优先级,从高到低依次为:高优先级、中优先级和低优先级。

优先级高的任务会优先被执行,优先级相同的任务按照先进先出(FIFO)的顺序执行。

2.时间片轮转:RT-Thread 中的任务执行时间是有限的,每个任务都有一个时间片。

当时间片用完时,任务会被挂起,下一个优先级较高的任务会立即执行。

任务调度器会根据任务的优先级和时间片轮转来调度任务,以实现多个任务的公平和高效执行。

三、RT-Thread 的任务管理RT-Thread 的任务管理主要包括任务的创建、删除、挂起和恢复等操作。

1.任务创建:在 RT-Thread 中,开发者可以通过调用特定的 API 函数创建任务。

创建任务时,需要指定任务的优先级、执行函数、任务参数等。

2.任务删除:当任务完成或不再需要时,可以通过调用 API 函数删除任务。

3.任务挂起:当任务的时间片用完时,任务会被挂起。

挂起后的任务会从就绪队列中移除,等待下一个时间片到来时再执行。

【RTX操作系统教程】第7章任务管理

【RTX操作系统教程】第7章任务管理

【RTX操作系统教程】第7章任务管理第7章 任务管理对于初学者,特别是对于没有RTOS基础的同学来说,了解RTX的任务管理⾮常重要,了解任务管理的⽬的就是让初学者从裸机的,单任务编程过渡到带OS的,多任务编程上来。

搞清楚了这点,那么RTX学习就算⼊门了。

本章教程配套的例⼦含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407。

7.1 单任务系统7.2 多任务系统7.3 任务设置7.4 任务栈设置7.5 系统栈设置7.6 栈溢出检测7.7 RTX初始化和启动7.9 任务删除7.10 空闲任务7.11实验例程说明7.12 总结7.1 单任务系统学习多任务系统之前,我们先来回顾下单任务系统的编程框架,即裸机时的编程框架。

裸机编程主要是采⽤超级循环(super-loops)系统,⼜称前后台系统。

应⽤程序是⼀个⽆限的循环,循环中调⽤相应的函数完成相应的操作,这部分可以看做后台⾏为,中断服务程序处理异步事件,这部分可以看做是前台⾏为。

后台也可以叫做任务级,前台也叫作中断级。

图7.1 单任务系统对于前后台系统的编程思路主要有以下两种⽅式:7.1.1 查询⽅式对于⼀些简单的应⽤,处理器可以查询数据或者消息是否就绪,就绪后进⾏处理,然后再等待,如此循环下去。

对于简单的任务,这种⽅式简单易处理。

但⼤多数情况下,需要处理多个接⼝数据或者消息,那就需要多次处理,如下⾯的流程图所⽰:⽤查询⽅式处理简单的应⽤,效果⽐较好,但是随着⼯程的复杂,采⽤查询⽅式实现的⼯程就变的很难维护,同时,由于⽆法定义查询任务的优先级,这种查询⽅式会使得重要的接⼝消息得不到及时响应。

⽐如程序⼀直在等待⼀个⾮紧急消息就绪,如果这个消息后⾯还有⼀个紧急的消息需要处理,那么就会使得紧急消息长时间得不到执⾏。

7.1.2 中断⽅式对于查询⽅式⽆法有效执⾏紧急任务的情况,采⽤中断⽅式就有效的解决了这个问题,下⾯是中断⽅式简单的流程图:采⽤中断和查询结合的⽅式可以解决⼤部分裸机应⽤,但随着⼯程的复杂,裸机⽅式的缺点就暴露出来了u 必须在中断(ISR)内处理时间关键运算:l ISR 函数变得⾮常复杂,并且需要很长执⾏时间。

rt-thread 线程调度原理

rt-thread 线程调度原理

一、概述RT-Thread是一个开源的嵌入式实时操作系统,它具有微内核架构和高度可裁剪性。

在RT-Thread中,线程调度是实现多任务处理的关键部分。

本文将介绍RT-Thread的线程调度原理,以及其在实时操作系统中的应用。

二、RT-Thread线程调度概述1. 线程在RT-Thread中,线程是进行任务调度和管理的基本单元。

每个线程都具有自己的堆栈空间和上下文环境。

通过线程的创建、运行和销毁,实现对各种任务的分配和调度。

2. 线程调度器线程调度器是RT-Thread的核心组件之一,负责根据线程的优先级、状态和时间片等信息对线程进行调度,以确保系统中的各个任务得到合理的执行。

3. 调度策略RT-Thread中采用了优先级抢占式调度策略,即优先级高的线程可以抢占优先级低的线程的CPU资源。

这种调度策略能够确保高优先级任务的及时响应,并且避免了低优先级任务长时间占用CPU资源的情况。

三、RT-Thread线程调度原理1. 线程控制块(TCB)每个线程在RT-Thread中都有对应的线程控制块(TCB),TCB中保存了线程的状态、优先级、堆栈指针和其他运行时信息。

线程被创建时,系统会为其分配对应的TCB,并将其加入到就绪队列中。

2. 调度器调度器是用来决定哪个线程获得CPU资源并运行的组件。

RT-Thread 中的调度器会根据线程的优先级和当前状态,选择合适的线程进行调度。

3. 就绪队列和延迟队列就绪队列是存放所有可运行线程的队列,而延迟队列是存放因某种原因暂时不能运行的线程的队列。

调度器会根据优先级从就绪队列中选择线程进行调度,而延迟队列中的线程则会在满足条件后被移动到就绪队列中。

四、RT-Thread线程调度实现1. 自旋锁在RT-Thread中,为了保证线程调度的原子性,通常会使用自旋锁来进行线程的互斥访问。

使用自旋锁可以确保在多线程环境中对共享资源的访问不会发生冲突。

2. 中断在嵌入式系统中,中断是一种常见的事件响应机制。

rtthread任务调度原理

rtthread任务调度原理

rtthread任务调度原理rt-thread是一个开源的实时操作系统,广泛应用于嵌入式系统中。

它具有高效的任务调度机制,能够有效地管理和调度系统中的各个任务。

本文将从任务调度的原理和实现方式两个方面介绍rt-thread任务调度的工作原理。

一、任务调度的原理rt-thread采用的是抢占式的优先级调度算法。

此算法通过为每个任务分配优先级,并根据优先级来决定任务的执行顺序。

具体来说,rt-thread将任务划分为两种类型:线程和实时线程。

线程是最基本的任务单元,通过线程来实现系统中不同功能的并发执行。

每个线程都有自己的优先级,优先级高的线程在系统空闲时会被优先执行。

线程的调度是通过rt-thread内核中的调度器来完成的。

实时线程是一种特殊的线程,它具有固定的周期和执行时间要求。

为了满足实时线程的要求,rt-thread引入了时钟滴答机制,以固定的时间间隔来调度实时线程的执行。

时钟滴答机制是rt-thread 的核心功能之一,它通过硬件定时器来实现,确保实时线程能够按时执行。

任务调度的过程是在时钟滴答中完成的。

每当时钟滴答到来时,调度器会根据当前任务的状态和优先级来选择下一个要执行的任务,并进行上下文切换。

上下文切换是指将当前任务的上下文保存起来,并恢复下一个任务的上下文,使其能够继续执行。

二、任务调度的实现方式rt-thread任务调度的实现方式主要包括任务控制块、就绪队列和调度器三个部分。

任务控制块(TCB)是rt-thread中用于管理任务的数据结构,它包含了任务的状态、优先级、堆栈等信息。

每个任务都有一个对应的任务控制块,通过任务控制块可以对任务进行管理和调度。

就绪队列是用来保存所有处于就绪状态的任务的数据结构,它按照任务的优先级进行排序。

当任务进入就绪状态时,会被插入到就绪队列中的适当位置。

调度器会从就绪队列中选择优先级最高的任务进行执行。

调度器是rt-thread中的核心组件,它负责任务的调度和上下文切换。

干货扒一扒RT-Thread内核对象管理器设计思路

干货扒一扒RT-Thread内核对象管理器设计思路

干货扒一扒RT-Thread内核对象管理器设计思路RT-Tread内核架构RT-Thread,全称是 Real Time-Thread,顾名思义,它是一个嵌入式实时多线程操作系统,基本属性之一是支持多任务,允许多个任务同时运行并不意味着处理器在同一时刻真地执行了多个任务。

其内核架构如下图所示:RT-Thread 内核及底层结构对于各部分的功能,这里不做展开描述。

RT-Tread内核吸引我的方面:•代码优雅、可读性非常高•体积小巧、代码类Linux风格,可裁剪•社区活跃,国人自主开发,用户越来越多•优秀的设计,对于面向对象设计思想可以说是非常优秀的实践•主要定位于物联网应用,各种组件丰富,融合的也很好•........所以如果是RTOS应用或者开发从业者,面对这么优秀且比较容易深入学习的内核,如果不去好好读读,实在有点可惜。

要去体会RT-Thread对象设计思想,从其对内核对象object的管理入手,不失为一个非常好的切入点。

什么是RT-Thread内核对象管理?RT-Thread 采用内核对象管理系统来访问/ 管理所有内核对象,内核对象包含了内核中绝大部分设施,这些内核对象既可以是静态分配的静态对象,也可以是从系统内存堆中分配的动态对象。

通过这种内核对象的设计方式,RT-Thread 做到了不依赖于具体的内存分配方式,系统的灵活性得到极大的提高。

RT-Thread 内核对象包括:线程,信号量,互斥量,事件,邮箱,消息队列和定时器,内存池,设备驱动等。

对象容器中包含了每类内核对象的信息,包括对象类型,大小等。

对象容器给每类内核对象分配了一个链表,所有的内核对象都被链接到该链表上,如图RT-Thread 的内核对象容器及链表如下图所示:RT-Thread 的内核对象容器及链表参考自:/document/site/programming-manual/basic/basic/#_7这个集中管理的内核对象容器在内存的开销方面代价很小,但却具有高度的灵活性,从设计的角度看其代码也非常利于扩展,增加新的内核对象类别,以及对于相应的内核对象功能的裁剪适配。

rtthread 任务调度原理

rtthread 任务调度原理

rtthread 任务调度原理## RT-Thread 任务调度原理RT-Thread是一个实时操作系统(RTOS),其任务调度原理是其核心设计之一。

任务调度是操作系统的关键功能之一,它决定了任务的执行顺序和时间分配。

RT-Thread采用抢占式优先级调度算法,下面将介绍RT-Thread任务调度的原理。

### 任务调度器RT-Thread的任务调度器是操作系统内核中的一个重要组件,主要负责管理和调度任务。

任务调度器根据任务的优先级和状态来决定任务的执行顺序。

### 任务控制块(TCB)每个任务在RT-Thread中都有一个对应的任务控制块(Task Control Block,TCB),TCB是一个数据结构,用于描述和管理任务的各种信息。

TCB中包含了任务的优先级、状态、栈空间等。

### 任务状态RT-Thread中的任务有以下几种状态:1. 就绪态(Ready):任务已经创建完成,但还未执行。

2. 运行态(Running):任务正在执行。

3. 阻塞态(Blocked):任务由于某些原因暂时无法执行,如等待信号量、等待事件等。

4. 挂起态(Suspended):任务被挂起,不会被调度执行。

### 优先级调度算法RT-Thread采用抢占式优先级调度算法,具体如下:1. 在就绪队列中,任务按照优先级由高到低排序。

当就绪队列中只有一个任务时,该任务被调度执行。

2. 当有新的任务就绪或者当前任务被阻塞等原因无法继续执行时,调度器会选择优先级最高的就绪任务来执行。

3. 当高优先级任务被调度执行后,低优先级任务会被挂起,等待下一次调度执行。

### 任务调度过程下面是RT-Thread任务调度的基本流程:1. 系统启动后,创建和初始化空闲任务。

空闲任务是一个特殊任务,当没有其他任务可以运行时,被调度器执行。

2. 创建其他任务,并设置它们的优先级和初始状态为就绪态。

3. 启动调度器,开始任务调度。

4. 调度器会根据任务的优先级来选择一个就绪任务,将其状态设置为运行态,切换到该任务执行。

RT-Thread Shell实验-Finsh Shell的基本使用

RT-Thread Shell实验-Finsh Shell的基本使用

RT-Thread Shell实验1 Finsh的基本使用实验目的:了解RT-Thread的命令行工具Finsh Shell组件掌握Finsh Shell的基本使用方法;掌握使用Finsh Shell观察RT-Thread内核对象运行时信息的方法;实验设计:Finsh是RT-Thread 的shell组件,通过它能够直接在shell中调用系统函数,访问系统变量;接受C语言中大多数运算符(包括指针运算符)进行简单计算;通过定义指针(函数)变量并指向某特定地址,可以完成匿名函数调用的功能。

表面感觉简单,内部实则非常复杂和强大。

它包含了一个可接受C语言表达式的shell系统,而且被实现成类似于一个编译器,实现了纯手工编写的完整词法分析,语法分析,然后产生中间二进制代码,最后放到虚拟机中运行。

对于用户而言,主要有以下功能:(1) 获取系统运行时信息,如各种RT-Thread内核对象的动态信息。

(2) 能够对任意寄存器和内存地址进行读写操作(3) 能够直接在shell中调用系统函数,访问系统变量在该实验设计中,我们主要实验功能(1)。

系统配置:在例程源代码中,系统配置已经完毕,首先是修改了rtconfig.h文件,将使用Finsh组件的宏打开其次将Finsh组件的源文件加入到工程中编译输出信息:编译程序,将生成的目标文件烧写到开发板后运行,然后通过串口输出可以看到如图所示的信息,除了输出RT-Thread的字符Logo外,最后还有一行finsh>>提示符,这表明Finsh shell已经运行起来。

在Finsh>>提示符下就可以接受字符输入,尝试输入list()命令,然后敲回车,看看效果吧。

请注意list命令后面的括号一定不能少。

从图中可以看出,list()命令的作用就是将系统中支持的所有shell命令都打印出来。

有点类似与其他系统中的help命令。

有了这些命令和描述信息,我们就可以深入内核,查看它们的信息咯。

rtthread 任务调度原理

rtthread 任务调度原理

rtthread 任务调度原理RT-Thread是一个基于实时操作系统的开源项目,它具有高效、稳定和可移植的特点。

任务调度是RT-Thread的关键特性之一,它确保了实时任务的按时执行和系统资源的合理利用。

本文将详细介绍RT-Thread任务调度的原理,包括任务优先级、抢占式调度、时间片轮转和任务状态管理等方面。

一、任务优先级在RT-Thread中,每个任务都有一个唯一的任务控制块(TCB),其中包含了任务的状态、优先级和其他相关信息。

任务优先级通过一个整数值表示,数值越小表示优先级越高,优先级为0的任务为最高优先级任务。

当多个任务同时可运行时,RT-Thread通过任务优先级来确定哪个任务被执行。

在任务调度时,RT-Thread将选择优先级最高的任务来运行。

如果存在多个优先级相同的任务,则按照先进先出的原则进行调度。

二、抢占式调度RT-Thread采用了抢占式调度机制,即在系统中存在多个优先级任务时,优先级更高的任务可以抢占正在执行的任务,以确保高优先级任务得以及时执行。

这种调度机制保证了实时任务的及时响应和系统的高可靠性。

当一个优先级更高的任务就绪时,RT-Thread会立即终止当前正在执行的任务,并切换到高优先级任务的上下文进行执行。

这个过程是由操作系统内核自动完成的,开发人员无需手动干预。

三、时间片轮转除了任务优先级的抢占机制,RT-Thread还使用了时间片轮转(Round-Robin)算法来保证任务公平调度。

时间片轮转算法是将每个任务的执行时间划分为固定大小的时间片,每个任务在一个时间片内尽可能多地运行。

当一个任务的时间片用完后,RT-Thread会将CPU时间切换给具有相同优先级的下一个就绪任务。

时间片轮转算法的优点是能够避免长时间运行的任务占用过多的CPU时间,提高系统的响应速度。

然而,如果系统中存在过多的任务或者某个任务占用时间过长,时间片轮转算法可能导致上下文切换的开销增加,降低系统性能。

rtthread设计与实现

rtthread设计与实现

rtthread设计与实现RT-Thread 是一个开源的实时操作系统(RTOS),它主要适用于嵌入式系统开发。

RT-Thread 具有高度可定制性,并且提供了丰富的中间件组件,例如TCP/IP 网络堆栈、文件系统、GUI 图形界面等。

RT-Thread 的设计和实现主要包括以下几个部分:1、内核:RT-Thread 的内核基于组件化的设计思想,提供了一个可配置的核心框架。

核心组件包括:(1)RT-Thread Scheduler:这是RT-Thread 的核心调度器,负责任务管理和调度。

(2)RT-Thread Timer:定时器管理,用于实现延迟操作和定时任务。

(3)RT-Thread Mailbox:用于实现任务间的通信和同步。

(4)RT-Thread Message Queue:消息队列,用于任务间的数据传输。

(5)RT-Thread Memory Pool:内存池管理,用于动态内存分配和管理。

2、组件:RT-Thread 提供了一系列中间件组件,例如:(1)RT-Thread Networking:TCP/IP 网络协议栈,支持各种网络接口和协议。

(2)RT-Thread File System:支持多种文件系统,例如Fat 文件系统、ext2/3 文件系统等。

(3)RT-Thread GUI:支持多种图形界面,例如Qt、MiniGUI 等。

(4)RT-Thread Device Driver:设备驱动框架,用于支持各种硬件设备的驱动程序开发。

3、工具链:RT-Thread 提供了一套完整的工具链,包括编译器、调试器、烧录器等。

同时,RT-Thread 支持多种编程语言,例如C/C++、Python 等。

4、应用编程接口(API):RT-Thread 提供了一套简单易用的API,使得开发者可以方便地使用RT-Thread 的各种功能。

例如,通过RT-Thread 的API 可以创建任务、管理任务、管理内存、管理网络连接等。

rt-thread 事件集的使用方法

rt-thread 事件集的使用方法

一、什么是rt-thread事件集?rt-thread是一个开源的嵌入式实时操作系统,具有高度灵活性和可扩展性。

事件集是rt-thread提供的一种事件管理机制,用于实现任务之间的同步和通信。

二、事件集的创建和初始化1. 创建事件集在rt-thread中创建事件集非常简单,只需调用相应的API即可。

示例代码如下:```c/* 定义事件集变量 */static rt_event_t ev;/* 在m本人n函数中创建事件集 */int m本人n(){/* 创建事件集 */rt_event_init(ev, "event", RT_IPC_FLAG_FIFO);/* 其他代码 */}```2. 初始化事件集rt-thread的事件集初始化函数为rt_event_init,其原型为:```crt_err_t rt_event_init(rt_event_t event, const char *name,rt_uint8_t flags);```其中,event为事件集指针,name为事件集的名称,flags为事件集的标志位。

三、事件集的使用方法1. 设置事件标志位使用rt_event_send函数可以设置事件集的指定标志位,示例代码如下:```crt_uint32_t set = 0x01; // 要设置的标志位rt_event_send(ev, set);```2. 清除事件标志位使用rt_event_recv函数可以清除事件集的指定标志位,示例代码如下:```crt_uint32_t clear = 0x01; // 要清除的标志位rt_event_recv(ev, clear, RT_EVENT_AND_CLEAR, set, RT_W本人TING_FOREVER);```3. 等待事件集标志位使用rt_event_recv函数可以等待事件集的指定标志位,示例代码如下:```crt_uint32_t w本人t = 0x01; // 要等待的标志位rt_event_recv(ev, w本人t, RT_EVENT_AND, set, RT_W本人TING_FOREVER);```四、事件集的优势和适用场景事件集是一种轻量级的事件管理机制,具有以下优势:- 灵活性高:可以灵活地设置、清除和等待事件标志位,便于实现复杂的任务同步和通信。

RT-Thread——线程管理

RT-Thread——线程管理

RT-Thread——线程管理1.线程的概念线程可以理解为⼀个个相互独⽴运⾏的单元任务。

这些任务共同使⽤CPU和内存空间等系统资源,不过,每⼀时刻,只能有⼀个线程在运⾏。

各个线程的运⾏是相互独⽴,不断切换的,所以线程都要有⾃⼰的堆栈,从⽽再次运⾏时能够恢复运⾏环境。

2.线程的调度RT-Thread提供的线程调度器是基于优先级的全抢占式调度,但中断函数和临界段程序是不可抢占的。

系统总共⽀持256个优先级,即0~255,数值越⼩,优先级越⾼,0为最⾼优先级,255是空闲线程的优先级,⽤户⼀般不会使⽤。

当有⽐当前运⾏线程优先级更⾼的线程就绪时,当前线程将⽴刻被换出,⾼优先级线程抢占运⾏。

RT-Thread还⽀持创建相同优先级的线程。

这些线程采⽤时间⽚轮转进⾏调度,但前提是没有更⾼优先级的线程出现。

所有准备好的线程都链接到了优先级队列中,选择优先级⾼的线程就是在优先级数组中寻找最⾼优先级线程对应的⾮空链表。

3.线程的状态操作系统中的线程有的在执⾏,有的被抢占,还有的即将被运⾏,也就是说有多种运⾏状态。

RT-Thread分5种运⾏状态:①初始态:RT_THREAD_INIT,创建线程时设置为初始态;②就绪态:RT_THREAD_READY,线程在就绪列表中,具备执⾏的条件,等待CPU运⾏;③运⾏态:RT_THREAD_RUNNING,线程正在被CPU执⾏;④挂起态:RT_THREAD_SUSPEND,线程正在等待某个信号量、消息队列、、事件或被延时等情况,不在就绪列表;⑤关闭态:RT_THREAD_CLOSE,线程运⾏结束,等待系统回收资源。

线程的状态是不断转换的,⽤⼀张图来表⽰线程状态迁移:4.建⽴线程实例下⾯介绍⼀下线程创建的步骤,以下发⽣在main.c源⽂件中。

(1)定义线程控制块和声明线程函数static rt_thread_t example_thread = RT_NULL; //初始化线程控制块static void example_thread_entry(void *parameter); //线程函数声明(2)在main函数中创建线程example_thread = //线程控制块指针rt_thread_create("example", //线程名字example_thread_entry, //线程⼊⼝函数RT_NULL, //线程⼊⼝函数参数512, //线程栈⼤⼩3, //线程的优先级20); //线程时间⽚(单位tick)// 启动线程,开启调度if(example_thread != RT_NULL)rt_thread_startup(example_thread);elsereturn -1;(3)编写线程函数内容static void example_thread_entry(void *parameter){while(1){ //⽆限循环,该线程不会被系统删除//若⽆这个循环,则线程运⾏完毕后会被系统⾃动删除// ....⽤户⾃定义线程操作}}通过以上三个步骤,就能建⽴可运⾏的线程了。

rtthread设计与实现

rtthread设计与实现

中国证券登记结算有限责任公司上海分公司关于2005年记账式(四期)国债付息有关事宜的通知
文章属性
•【制定机关】中国证券登记结算有限责任公司上海分公司
•【公布日期】2006.11.03
•【字号】
•【施行日期】2006.11.03
•【效力等级】地方规范性文件
•【时效性】现行有效
•【主题分类】金融债券,证券,国债
正文
中国证券登记结算有限责任公司上海分公司关于2005年记账式(四期)国债付息有关事宜的通知
各结算单位、基金管理公司:
根据《财政部关于2006年记账式国债还本付息工作有关事宜的通知》(财库[2006]3号),我公司将从2006年11月15日起代理兑付2005年记账式(四期)国债(以下简称本期国债)第2年第1期利息(以下简称本期利息),现将有关事项通知如下:
一、本期国债挂牌名称为“05国债(4)”,交易代码为“010504”,付息代码为“010504”,期限20年,年利率为4.11%,每半年付息一次。

二、本期国债付息的债权登记日为11月14日,凡于当日闭市后仍持有本期国债的投资者,为本期利息的最终所有者。

本期利息支付日为11月15日,每百元面值的利息为2.055元。

三、我公司在确认代理付息资金到帐后,于11月14日汇总指定交易在各法人结算单位名下投资者的应收本期利息清算数据,并于次一工作日将兑息资金划付至相关结算单位在我公司的交收账户内,由相关法人结算单位负责及时支付给投资
者。

享有本次利息但尚未办理指定交易的投资者,我公司将在其办妥指定交易后,通过结算单位兑付本次利息。

中国证券登记结算有限责任公司上海分公司
二OO六年十一月三日。

Rt-thread:任务调度

Rt-thread:任务调度

Rt-thread:任务调度启动顺序:1 rtthread_startup进⾏对象初始化2 rt_application_init进⾏线程对象初始化rt_thread_create创建线程1 调⽤rt_object_allocate(RT_Object_Class_Thread,name);获取线程对象并创建线程(a) rt_object_get_information(type),根据type获取线程的对象实例。

查找⽅法是遍历rt_object_container并找到type能匹配上的。

Rt-thread中所有的对象都包含在object.c中的静态变量rt_object_container中static struct rt_object_information rt_object_container[RT_Object_Info_Unknown] ={/* initialize object container - thread */{RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread)},#ifdef RT_USING_SEMAPHORE/* initialize object container - semaphore */{RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)},#endif#ifdef RT_USING_MUTEX/* initialize object container - mutex */{RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)},#endif#ifdef RT_USING_EVENT/* initialize object container - event */{RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)},#endif#ifdef RT_USING_MAILBOX/* initialize object container - mailbox */{RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox)},#endif#ifdef RT_USING_MESSAGEQUEUE/* initialize object container - message queue */{RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(structrt_messagequeue)},#endif#ifdef RT_USING_MEMHEAP/* initialize object container - memory heap */{RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap)},#endif#ifdef RT_USING_MEMPOOL/* initialize object container - memory pool */{RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool)},#endif#ifdef RT_USING_DEVICE/* initialize object container - device */{RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)},#endif/* initialize object container - timer */{RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)},#ifdef RT_USING_MODULE/* initialize object container - module */{RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)},#endif};(b) object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size); 根据该对象的object_size⼤⼩⽣成线程对象。

4.2.RTOS内核-任务管理

4.2.RTOS内核-任务管理

任务还可能处于等待状态
• 如果任务在需要等待I/O设备或其他任务提供的数 据,而数据又还没有到达该任务的情况下,就处 于等待状态
17:50
HDU
任务状态与变迁
任务会在不同的状态之间进行转换,即任务状 态的变迁
运行态
需要 资源
获得CPU 就绪态
被高优先级 任务抢占或 超时
获得资源
等待态
任务状态变迁
17:50
HDU
任务参数
任务的就绪时间
任务具备了在处理器上被执行所需要条件时的时间。
任务的截止时间
• 意味着任务需要在该时间到来之前被执行完成。 • 截止时间可以通过绝对截止时间(absolute deadline)和相对 截止时间(relative time)两种方式来表示 – 相对截止时间为任务的绝对截止时间减去任务的就绪时间。 • 截止时间可以分为强截止时间(hard deadline)和弱截止时 间(soft deadline)两种情况: – 具有强截止时间的任务即为关键任务,如果截止时间不能 得到满足,就会出现严重的后果。 – 拥有关键任务的实时系统又被称为强实时(hard realtime)系统,否则称为弱实时(soft real-time)系统。
• 飞行器中处理稳定性控制的任务,就需要具有较 高的优先级,一旦执行条件得到满足,应及时得 到执行
任务的优先级分为静态优先级和动态优先级。
• 静态优先级:任务的优先级被确定后,在系统运 行过程中将不再发生变化; • 动态优先级:系统运行过程中,任务的优先级是
可以动态变化的。
17:50
HDU
任务参数
周期 周期任务所具有的参数,表示任务周期性执行 的间隔时间 任务的计算时间 任务在特定硬件环境下被完整执行所需要的时 间,也被称为是任务的执行时间(execution time)。 由于任务每次执行的软件环境的差异性,导致 任务在各次具体执行过程中的计算时间各有不 同。 通常用最坏情况下的执行时间(worst case time)或是需要的最长执行时间来表示,也可 用统计时间(statistical time)来表示。

rt-thread的线程调度与管理

rt-thread的线程调度与管理

rt-thread的线程调度与管理rt-thread的线程调度与管理1.调度是什么?2.调度怎么实现?3.什么时候系统做调度?3.1 任务主动block3.2 被更高优先级的任务唤醒3.3 yield放弃cpu使用3.4 中断中执行调度4.调度做了哪些事情?5.总结要想使用好rtos,做出更加稳定可靠的产品,必须非常清楚底层的调度原理。

由于RTOS的可控性,所以只有了解了其核心部分的设计思路,才能用起来得心应手,游刃有余。

本文主要是听完熊大对rt-thread调度讲解之后,自己做了一些反思总结,打算分享一下rt-thread线程的调度与管理相关的比较核心和重要的部分的笔记。

1.调度是什么?调度一般就是合理的安排,协调资源,统一指挥去完成一件事,而在操作系统中,线程调度就是有多个就绪优先级的任务,找到最高优先级任务,交给CPU去运行。

rt-thread调度器就是起到判决线程当前的优先级,然后去执行当前最高优先级的就绪的线程。

调度又可以细分为两种。

可打断调度:关键防止优先级倒置;不可打断调度:先来先服务,不可中断。

2.调度怎么实现?在创建任务的时候,指定了任务的优先级,一般来说,每个任务都有自己特定的优先级。

所以内核线程对象中有不同的优先级的任务列表。

如果最大指定为32个优先级,那么可以用u32,每一个bit表示一个优先级就绪的状态。

使用位图的优点就是速度快,而且内存占用小。

一般来说,调度去找到最高优先级的任务时,就需要去做判断。

如何去找到最高优先级的任务。

一般来说,有两种办法:软件计算硬件计算这两种的差别仅仅在于计算效率的问题,本质目的并无差别。

而寻找最高优先级的事情也是有两种实现的策略:1.遍历就绪的队列,找到最小的就绪的队列,寻找的时间不确定,时间复杂度O(n)。

2.采用空间换时间的办法,事先做好一个bitmap例如系统中最大有8个优先级,那么bitmap如下:const rt_uint8_t __lowest_bit_bitmap[] ={/* 00 */ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};一般每一位代表一个就绪的状态,所以__rt_ffs程序的设计如下int __rt_ffs(int value){if (value == 0) return 0;if (value & 0xff)return __lowest_bit_bitmap[value & 0xff] + 1;if (value & 0xff00)return __lowest_bit_bitmap[(value & 0xff00) >> 8] + 9;if (value & 0xff0000)return __lowest_bit_bitmap[(value & 0xff0000) >> 16] + 17;return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25;}如果当前系统的线程状态为0b0110 0000,那么转换成十六进制就是0x60,根据表中的状态此时的最高优先级是5+1=6。

录(八、理解 RT-Thread 内存管理)

录(八、理解 RT-Thread 内存管理)

RT-Thread记录(八、理解 RT-Thread 内存管理)•前言•一、为什么要内存管理•二、RT-Thread 内存堆管理▪ 2.1 RT-Thread 内存分配▪ 2.2 RT-Thread内存堆管理方式▪ 2.3 内存堆 API 函数•三、RT-Thread 内存池▪ 3.1 内存池的位置▪ 3.2 内存池程序配置和控制块▪ 3.3 内存池操作 API 函数•结语前言记得最初学习RT-Thread ,对于内存管理我也是简单看看然后一笔带过,当时觉得用不上,在我做的一些传感器单品项目上,对于内存管理确实知道与不知道没什么关系,但是随着认知的增长,项目复杂程度增加,发现内存管理还不可或缺,于是今时今日正好再次来更新RT-Thread记录,有必要好好的说一说。

RT-Thread 有2种内存管理方式,分别是动态内存堆管理和静态内存池管理。

先不管这两种方式是怎么实现的,首先要明白一个问题,为什么要内存管理?一、为什么要内存管理什么是内存管理?为什么需要内存管理?在我们的程序设计中,一些数据需要的内存大小需要在程序运行过程中根据实际情况确定,在用户需要一段内存空间时,向系统申请,系统选择一段合适的内存空间分配给用户,用户使用完毕后,再释放回系统,以便系统将该段内存空间回收再利用。

这样子不断的申请释放,如果没有内存管理,就会导致内存碎片,对程序产生极大的影响。

具体的原因我在下面博文有详细说明:浅谈 malloc 函数在单片机上的应用如果看完上面的博文,就应该知道了内存管理的重要性。

我们确实直接在函数或者线程里面创建临时变量使用线程栈或者系统栈处理临时变量,但是正如上面博文里面所说的,作为一个通用的操作系统,都会且必须得有自己的合理的内存管理方式。

这个在我们现在说明的RT-Thread 操作系统上是内核已经实现好的,我们得了解它。

知道了为什么,那么接下来我们就来了解一下RT-Thread 的这2种内存管理方式。

RT-Thread--线程管理

RT-Thread--线程管理

RT-Thread--线程管理线程管理的功能特点RT-Thread系统中线程是调度的最⼩单位;线程分为:系统线程和⽤户线程,系统线程是由 RT-Thread 内核创建的线程,⽤户线程是由应⽤程序创建的线程,这两类线程都会从内核对象容器中分配线程对象,当线程被删除时,也会被从对象容器中删除RT-Thread 的线程调度器是抢占式的,主要的⼯作就是从就绪线程列表中查找最⾼优先级线程,保证最⾼优先级的线程能够被运⾏,最⾼优先级的任务⼀旦就绪,总能得到 CPU 的使⽤权。

当调度器调度线程切换时,先将当前线程上下⽂保存起来,当再切回到这个线程时,线程调度器将该线程的上下⽂信息恢复。

线程的⼯作机制线程控制块线程控制块由结构体 struct rt_thread 表⽰,线程控制块是操作系统⽤于管理线程的⼀个数据结构,它会存放线程的⼀些信息,例如优先级、线程名称、线程状态等,也包含线程与线程之间连接⽤的链表结构,线程等待事件集合等/*** Thread structure*/struct rt_thread{/* rt object */char name[RT_NAME_MAX]; /**< the name of thread */rt_uint8_t type; /**< type of object */rt_uint8_t flags; /**< thread's flags */#ifdef RT_USING_MODULEvoid *module_id; /**< id of application module */#endifrt_list_t list; /**< the object list */rt_list_t tlist; /**< the thread list *//* stack point and entry */void *sp; /**< stack point */void *entry; /**< entry */void *parameter; /**< parameter */void *stack_addr; /**< stack address */rt_uint32_t stack_size; /**< stack size *//* error code */rt_err_t error; /**< error code */rt_uint8_t stat; /**< thread status *//* priority */rt_uint8_t current_priority; /**< current priority */rt_uint8_t init_priority; /**< initialized priority */#if RT_THREAD_PRIORITY_MAX > 32rt_uint8_t number;rt_uint8_t high_mask;#endifrt_uint32_t number_mask;#if defined(RT_USING_EVENT)/* thread event */rt_uint32_t event_set;rt_uint8_t event_info;#endif#if defined(RT_USING_SIGNALS)rt_sigset_t sig_pending; /**< the pending signals */rt_sigset_t sig_mask; /**< the mask bits of signal */void *sig_ret; /**< the return stack pointer from signal */rt_sighandler_t *sig_vectors; /**< vectors of signal handler */void *si_list; /**< the signal infor list */#endifrt_ubase_t init_tick; /**< thread's initialized tick */rt_ubase_t remaining_tick; /**< remaining tick */struct rt_timer thread_timer; /**< built-in thread timer */void (*cleanup)(struct rt_thread *tid); /**< cleanup function when thread exit *//* light weight process if present */#ifdef RT_USING_LWPvoid *lwp;#endifrt_uint32_t user_data; /**< private user data beyond this thread */};typedef struct rt_thread *rt_thread_t;nit_priority 是线程创建时指定的线程优先级,在线程运⾏过程当中是不会被改变的(除⾮⽤户执⾏线程控制函数进⾏⼿动调整线程优先级);cleanup 会在线程退出时,被空闲线程回调⼀次以执⾏⽤户设置的清理现场等⼯作;user_data 可由⽤户挂接⼀些数据信息到线程控制块中,以提供类似线程私有数据的实现。

RT-Thread内核对象控制块详解

RT-Thread内核对象控制块详解

RT-Thread内核对象控制块详解背景•学习RT-Thread,除了基础的应用,应该花点时间,研究下底层内核的实现方法。

•RT-Thread内核,整体代码量不大,很适合研究,后期,打算在这个基础上,开发一些软件包。

•之前了解了一点数据结构的知识,主要为结构体、链表。

不过感觉没有真正的使用起来。

•程序 = 数据结构+算法。

•万事开头难,先从最基本的概念开始。

内核对象控制块•对象(object)结构体•对象可以派生具体的对象导火索•今天,想仔细看看RT-Thread 的内核的对象,基本上都是结构体,看看结构体的大小,占用RAM的大小。

•单片机的程序,短小精悍是每个嵌入式软件工程师追求的,实现相同功能,占用最少资源,意味着硬件成本会进一步降低。

•编写一个函数,打印一下rt_object 等对象的结构体占用的内存(RAM)大小。

void print_kernel_object_size(void){struct rt_object obj;rt_kprintf("struct rt_object size=%d\\n", sizeof(obj));rt_kprintf("rt_list_t size=%d\\n", sizeof(rt_list_t));rt_kprintf("struct rt_ti mer size=%d\\n", sizeof(struct rt_timer)); rt_kprintf("struct rt_thre ad size=%d\\n", sizeof(structrt_thread));rt_kprintf("struct rt_ipc_object size=%d\\n", sizeof(structrt_ipc_object));rt_kprintf("struct rt_semaphore size=%d\\n", sizeof(structrt_semaphore));rt_kprintf("struct rt_mu te x size=%d\\n", sizeof(struct rt_mutex)); rt_kprintf("struct rt_event size=%d\\n", sizeof(struct rt_event)); rt_kprintf("struct rt_mailbox size=%d\\n", sizeof(structrt_mailbox));rt_kprintf("struct rt_messagequeue size=%d\\n", sizeof(structrt_messagequeue));rt_kprintf("struct rt_mempool size=%d\\n", sizeof(structrt_mempool));rt_kprintf("struct rt_device size=%d\\n", sizeof(structrt_device));rt_kprintf("struct rt_device_graphic_info size=%d\\n",sizeof(struct rt_device_graphic_info));}MSH_CMD_EXPORT(print_kernel_object_size, print_kernel_object_size);//导出命令•运行效果msh / >priprint_kernel_object_sizemsh / >print_kernel_object_sizestruct rt_object size=20rt_list_t size=8struct rt_timer size=44struct rt_thread size=128struct rt_ipc_object size=28struct rt_semaphore size=32struct rt_mutex size=36struct rt_event size=32struct rt_mailbox size=48struct rt_messagequeue size=60struct rt_mempool size=52struct rt_device size=80struct rt_device_graphic_info size=12•struct rt_object size=20,说明:RT_NAME_MAX为8时,内核对象大小为:20字节(8+ (4)+8 = 20)•初步分析,rt_uint8_t type,rt_uint8_t flag,因为内存对齐,占用了2+2=4个字节。

RT-Thread学习之内核基础

RT-Thread学习之内核基础

RT-Thread,全称是Real Time-Thread,顾名思义,它是一个嵌入式实时多线程操作系统,基本属性之一是支持多任务,允许多个任务同时运行并不意味着处理器在同一时刻真地执行了多个任务。

事实上,一个处理器核心在某一时刻只能运行一个任务,由于每次对一个任务的执行时间很短、任务与任务之间通过任务调度器进行非常快速地切换(调度器根据优先级决定此刻该执行的任务),给人造成多个任务在一个时刻同时运行的错觉。

RT-Thread 与其他很多 RTOS 如 FreeRTOS、uC/OS 的主要区别之一是,它不仅仅是一个实时内核,还具备丰富的中间层组件,如下图所示:RT-Thread提供了一些网络组件及软件包,我们可以运用这些软件包很方便地与云端进行通讯。

因此,RT-Thread是一个物联网操作系统(IoT OS)。

RT-Thread的架构由四层组成:硬件层、内核层、组件层、软件包。

其中硬件架构现在最常用的就是ARM架构,但是,同样值得关注的是RISC-V架构,这个势头很猛。

本篇笔记我们着重关注内核层。

分层的思想在我们软件方面来说是个很重要的思想,相邻层之间通过一些API接口进行交互,跨层之间不会互相影响。

此处,硬件层无论用哪一种架构,上面的组件层及软件包都能通用。

RT-Thread内核架构如下:其中,内核库kservice.c是为了保证内核能够独立运行的一套小型的类似 C 库的函数实现子集。

这部分根据编译器的不同自带 C 库的情况也会有些不同,当使用 GNU GCC 编译器时,会携带更多的标准 C 库实现。

kservice.c中的函数如下:C 库:也叫 C 运行库(C Runtime Library),它提供了类似“strcpy”、“memcpy” 等函数,有些也会包括“printf”、“scanf” 函数的实现。

RT-Thread Kernel Service Library 仅提供内核用到的一小部分 C 库函数实现,为了避免与标准 C 库重名,在这些函数前都会添加上 rt_前缀。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
RT-Thread 内核实验 1 任务的基本管理
实验目的:
理解 RTOS 中任务管理的基本原理,了解任务的基本状态及其变迁过程; 掌握 RT-Thread 任务管理子系统中的任务创建,启动,延时机制 掌握 RT-Thread 任务管理子系统中静态任务与动态任务创建的区别
实验设计:
为了体现任务的状态切换过程,本实验设计了两个线程,分别是 thread1,thread2,此外,系统 中还有另外一个空闲任务,当没有其他任务运行时,系统自动调度空闲任务并投入运行。
实验流程:
1) 系统进入应用程序入口 2) 初 始 化 静 态 线 程 thread1 , 线 程 的 入 口 是 thread1_entry, 参 数 是 RT_NULL , 线 程 栈 是 thread1_stack,优先级是 30,时间片是 10 个 OS Tick 3) 启动线程 thread1 4) 创建动态线程 thread2,线程的入口是 thread2_entry,,参数是 RT_NULL,栈空间是 512,优 先级是 31,时间片是 25 个 OS Tick 5) 启动线程 thread2 6) [1]系统首先调度 thread1 投入运行,打印第 0 次运行的信息,然后通过延时函数将自己挂起 100 个 OS Tick,系统转入调度 thread2 投入运行 7) [2]Thread2 打印第 0 次运行信息,然后通过延时函数将自己挂起 50 个 OS Tick 8) [3]系统中无任务运行,转入调度空闲任务 9) [4]50 个 OS Tick 时间后,Thread2 被唤醒,打印第 1 次运行的信息,继续通过延时函数将自 己挂起 50 个 OS Tick 10) [5]系统中无任务运行,系统转入调度空闲任务,运行 50 个 OS Tick
/* 初始化线程1 */ /* 线程的入口是thread1_entry,参数是RT_NULL * 线程栈是thread1_stack * 优先级是200,时间片是10个OS Tick */ result = rt_thread_init(&thread1, "thread1", 初始化线程丆与创建线程功能相同。最后再启动线程 thread1_entry, RT_NULL, &thread1_stack[0], sizeof(thread1_stack), 30, 10); /* 启动线程 */ if (result == RT_EOK) rt_thread_startup(&thread1); /* 创建线程2 */ /* 线程的入口是thread2_entry, 参数是RT_NULL * 栈空间是512,优先级是250,时间片是25个OS Tick */ thread2_ptr = rt_thread_create("thread2", thread2_entry, RT_NULL, 512, 31, 25); /* 启动线程 */ if (thread2_ptr != RT_NULL) rt_thread_startup(thread2_ptr); retu 13) 14) 15) 16)
[6]Thread1 被唤醒,打印第 1 次运行信息,继续挂起 100 个 OS Tick [7]Thread2 被唤醒,打印第 2 次运行的信息,继续挂起 50 个 OS Tick [8]系统中无任务运行,系统转入调度空闲任务,运行 50 个 OS Tick [9]Thread2 被唤醒,打印第 3 次运行的信息,继续挂起 50 个 OS Tick [10]系统中无任务运行,系统转入调度空闲任务,运行 50 个 OS Tick 循环上述过程
输出信息:
运行程序,通过观察串口输出,就可以观察到任务的运行和切换情况了。
断点设置
使用 MDK 调试工具在程序中设置一些合理断点来运行,可以清晰地看到线程运行和切换的完 整过程。
TIPS:动态线程和静态线程
RT-Thread 中支持静态和动态两种定义方式。用线程来举例的话,rt_thread_init 对应静态定义方 式,rt_thread_create 对应动态定义方式。 使用静态定义方式时,必须先定义静态的线程控制块,并且定义好堆栈空间,然后调用 rt_thread_init 来完成线程的初始化工作。采用这种方式,线程控制块和堆栈占用的内存会放在 RW 段,这段空间在编译时就已经确定,它不是可以动态分配的,所以不能被释放,而只能使 用 rt_thread_detach 函数将该线程控制块从对象管理器中脱离。 使用动态定义方式 rt_thread_create 时, RT-Thread 会动态申请线程控制块和堆栈空间。 在编译时, 编译器是不会感知到这段空间的,只有在程序运行时, RT-Thread 才会从系统堆中申请分配这段 内存空间,当不需要使用该线程时,调用 rt_thread_delete 函数就会将这段申请的内存空间重新 释放到内存堆中。 这两种方式各有利弊,静态定义方式会占用 RW/ZI 空间,但是不需要动态分配内存,运行时效 率较高,实时性较好。 动态方式不会占用额外的 RW/ZI 空间,占用空间小,但是运行时需要 动态分配内存,效率没有静态方式高。 总的来说,这两种方式就是空间和时间效率的平衡,可以根据实际环境需求选择采用具体的分 配方式。
源程序说明:
/* 线程1的对象和运行时用到的栈 */ static struct rt_thread thread1; ALIGN(4) static rt_uint8_t thread1_stack[512]; /* 线程1入口 */ void thread1_entry(void* parameter) { int i; while (1) { for (i = 0; i < 10; i ++) { rt_kprintf("%d\n", i); /* 延时100个OS Tick */ rt_thread_delay(100); } } } /* 线程2入口 */ void thread2_entry(void* parameter) { int count = 0; while (1) { rt_kprintf("Thread2 count:%d\n", ++count); /* 延时50个OS Tick */ rt_thread_delay(50); } } /* 用户应用程序入口 */ int rt_application_init() { rt_thread_t thread2_ptr; rt_err_t result;
相关文档
最新文档